From 9493055c603a730e41c03f9cf82063b65be0c994 Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Wed, 5 Feb 2025 03:10:21 -0800 Subject: [PATCH] Added prettier, added husky pre-commit hook to ensure formatting --- .husky/pre-commit | 1 + .prettierignore | 37 + .prettierrc.js | 22 + README.md | 1 + app/api/proxy/route.ts | 24 +- app/layout.tsx | 9 +- .../components/custom-edge/custom-edge.tsx | 5 +- .../components/action-bar/action-bar.tsx | 40 +- .../connection-blocks/connection-blocks.tsx | 14 +- .../sub-block/components/checkbox-list.tsx | 20 +- .../components/sub-block/components/code.tsx | 22 +- .../sub-block/components/dropdown.tsx | 9 +- .../sub-block/components/long-input.tsx | 27 +- .../sub-block/components/short-input.tsx | 29 +- .../sub-block/components/slider-input.tsx | 4 +- .../sub-block/components/switch.tsx | 7 +- .../components/sub-block/components/table.tsx | 21 +- .../sub-block/components/tool-input.tsx | 53 +- .../sub-block/hooks/use-sub-block-value.ts | 7 +- .../components/sub-block/sub-block.tsx | 46 +- .../workflow-block/workflow-block.tsx | 45 +- .../workflow-canvas/workflow-canvas.tsx | 26 +- .../workflow-node/workflow-node.tsx | 10 +- app/w/[id]/workflow.tsx | 11 +- .../console-entry/console-entry.tsx | 31 +- .../components/json-view/json-view.tsx | 28 +- app/w/components/console/console.tsx | 12 +- .../components/history-dropdown-item.tsx | 12 +- .../components/notification-dropdown-item.tsx | 22 +- app/w/components/control-bar/control-bar.tsx | 65 +- .../notifications/notifications.tsx | 18 +- .../sidebar/components/nav-item/nav-item.tsx | 8 +- .../settings-modal/settings-modal.tsx | 70 +- app/w/components/sidebar/sidebar.tsx | 38 +- .../toolbar-block/toolbar-block.tsx | 9 +- .../components/toolbar-tabs/toolbar-tabs.tsx | 5 +- app/w/components/toolbar/toolbar.tsx | 18 +- app/w/hooks/use-block-connections.ts | 12 +- app/w/hooks/use-workflow-execution.ts | 65 +- app/w/layout.tsx | 12 +- blocks/blocks/agent.ts | 51 +- blocks/blocks/api.ts | 14 +- blocks/blocks/condition.ts | 20 +- blocks/blocks/crewai.ts | 32 +- blocks/blocks/firecrawl.ts | 26 +- blocks/blocks/function.ts | 16 +- blocks/blocks/github.ts | 18 +- blocks/blocks/jina.ts | 30 +- blocks/blocks/serper.ts | 53 +- blocks/blocks/slack.ts | 30 +- blocks/blocks/tavily.ts | 50 +- blocks/blocks/translate.ts | 48 +- blocks/consts.ts | 6 +- blocks/index.ts | 58 +- blocks/types.ts | 44 +- blocks/utils.ts | 2 +- components.json | 2 +- components/icons.tsx | 120 ++- components/ui/alert-dialog.tsx | 61 +- components/ui/alert.tsx | 53 +- components/ui/badge.tsx | 24 +- components/ui/breadcrumb.tsx | 111 +-- components/ui/button.tsx | 48 +- components/ui/card.tsx | 117 +-- components/ui/checkbox.tsx | 17 +- components/ui/command.tsx | 31 +- components/ui/dialog.tsx | 49 +- components/ui/dropdown-menu.tsx | 58 +- components/ui/env-var-dropdown.tsx | 46 +- components/ui/formatted-text.tsx | 2 +- components/ui/input.tsx | 1 - components/ui/label.tsx | 22 +- components/ui/popover.tsx | 13 +- components/ui/scroll-area.tsx | 21 +- components/ui/select.tsx | 46 +- components/ui/sheet.tsx | 66 +- components/ui/slider.tsx | 14 +- components/ui/switch.tsx | 13 +- components/ui/tabs.tsx | 15 +- components/ui/tag-dropdown.tsx | 35 +- components/ui/textarea.tsx | 36 +- components/ui/tooltip.tsx | 11 +- executor/__tests__/executor.test.ts | 934 +++++++++--------- executor/index.ts | 231 ++--- executor/types.ts | 2 +- jest.config.js | 13 +- lib/utils.ts | 6 +- lib/workflow.ts | 12 +- next.config.ts | 6 +- package-lock.json | 748 +++++++++++++- package.json | 15 +- postcss.config.mjs | 4 +- providers/anthropic/index.ts | 104 +- providers/deepseek/index.ts | 57 +- providers/google/index.ts | 107 +- providers/openai/index.ts | 45 +- providers/service.ts | 59 +- providers/types.ts | 15 +- providers/xai/index.ts | 61 +- serializer/__tests__/serializer.test.ts | 222 ++--- serializer/index.ts | 53 +- serializer/types.ts | 38 +- stores/console/store.ts | 12 +- stores/console/types.ts | 2 +- stores/environment/store.ts | 10 +- stores/environment/types.ts | 2 +- stores/notifications/store.ts | 14 +- stores/notifications/types.ts | 2 +- stores/workflow/history-types.ts | 2 +- stores/workflow/logger.ts | 4 +- stores/workflow/middleware.ts | 23 +- stores/workflow/registry-types.ts | 2 +- stores/workflow/registry.ts | 82 +- stores/workflow/store.ts | 44 +- stores/workflow/types.ts | 11 +- tailwind.config.ts | 176 ++-- tools/anthropic/chat.ts | 52 +- tools/crewai/vision.ts | 76 +- tools/deepseek/chat.ts | 30 +- tools/deepseek/reasoner.ts | 32 +- tools/firecrawl/scrape.ts | 24 +- tools/function/execute.ts | 62 +- tools/github/repo.ts | 29 +- tools/google/chat.ts | 70 +- tools/http/request.ts | 106 +- tools/hubspot/contacts.ts | 86 +- tools/index.ts | 80 +- tools/jina/reader.ts | 26 +- tools/openai/chat.ts | 101 +- tools/salesforce/opportunities.ts | 92 +- tools/serper/search.ts | 102 +- tools/slack/message.ts | 20 +- tools/tavily/extract.ts | 34 +- tools/tavily/search.ts | 36 +- tools/types.ts | 47 +- tools/xai/chat.ts | 68 +- tsconfig.json | 19 +- types/global.d.ts | 4 +- 138 files changed, 3597 insertions(+), 3162 deletions(-) create mode 100755 .husky/pre-commit create mode 100644 .prettierignore create mode 100644 .prettierrc.js diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100755 index 000000000..95efa798f --- /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 000000000..3a8d5a973 --- /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 000000000..41708aec7 --- /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 d2141d0ae..5bc14ee44 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 cfebe278b..dd1aec465 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 1579049bf..60d4844e6 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 2bbdb0624..f07bca46a 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 b575fc5d1..d0400c44c 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 e13d34156..a7b90fcf5 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 22ba6abcd..5576560a4 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 027ba5db5..16c8b7e25 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 b31d8c434..b3fdc352c 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 878628873..da01423e5 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 d75e05eb5..2925d6a8d 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 f26a3de55..29c5368d8 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 b32996ace..1011ce836 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 852297157..eabb6000c 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 72bdd8c68..f53a7fb23 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 ccc1436c5..910b5313d 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 fb003ba9d..e3e06034f 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 c46b6e992..803b93c59 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 8ac8e7794..839b4013e 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 f835b4245..7bde3cff7 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 1a3e9b872..2cc05c46f 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 34e609ae6..f9ec157a7 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 33d2640a3..158699fbb 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 44e16bfd5..2fd2262ab 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 9243d7e23..069c90155 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 e607fcd4f..6fa80bd1b 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 a06e1b72e..064f67035 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 bc2ff44a3..12e09f8b8 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 0710edef5..9db8aaef1 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() {