diff --git a/apps/docs/app/(docs)/[[...slug]]/page.tsx b/apps/docs/app/(docs)/[[...slug]]/page.tsx index 6d32146aff..5af882aa90 100644 --- a/apps/docs/app/(docs)/[[...slug]]/page.tsx +++ b/apps/docs/app/(docs)/[[...slug]]/page.tsx @@ -1,6 +1,6 @@ +import defaultMdxComponents from 'fumadocs-ui/mdx' import { DocsBody, DocsDescription, DocsPage, DocsTitle } from 'fumadocs-ui/page' import { notFound } from 'next/navigation' -import mdxComponents from '@/components/mdx-components' import { source } from '@/lib/source' export const dynamic = 'force-dynamic' @@ -36,7 +36,7 @@ export default async function Page(props: { params: Promise<{ slug?: string[] }> {page.data.title} {page.data.description} - + ) diff --git a/apps/docs/app/(docs)/layout.tsx b/apps/docs/app/(docs)/layout.tsx index e29263efbc..18bf0fac61 100644 --- a/apps/docs/app/(docs)/layout.tsx +++ b/apps/docs/app/(docs)/layout.tsx @@ -1,6 +1,7 @@ import type { ReactNode } from 'react' import { DocsLayout } from 'fumadocs-ui/layouts/docs' import { ExternalLink, GithubIcon } from 'lucide-react' +import Image from 'next/image' import Link from 'next/link' import { source } from '@/lib/source' @@ -23,7 +24,17 @@ export default function Layout({ children }: { children: ReactNode }) { Sim, + title: ( +
+ Sim +
+ ), }} links={[ { @@ -33,9 +44,10 @@ export default function Layout({ children }: { children: ReactNode }) { }, ]} sidebar={{ - defaultOpenLevel: 1, + defaultOpenLevel: 0, collapsible: true, footer: null, + banner: null, }} > {children} diff --git a/apps/docs/app/global.css b/apps/docs/app/global.css index c3c1f9bac3..e0e1f47138 100644 --- a/apps/docs/app/global.css +++ b/apps/docs/app/global.css @@ -6,6 +6,150 @@ --color-fd-primary: #802fff; /* Purple from control-bar component */ } +/* Target any potential border classes */ +* { + --fd-border-sidebar: transparent !important; +} + +/* Override any CSS custom properties for borders */ +:root { + --fd-border: transparent !important; + --fd-border-sidebar: transparent !important; +} + +/* Sidebar improvements for cleaner design */ +[data-sidebar] { + --fd-sidebar-width: 280px; + background-color: rgb(255 255 255); + padding-top: 16px; +} + +/* Clean sidebar container */ +[data-sidebar] > div { + padding: 0 16px; +} + +/* Section headers/separators styling */ +[data-sidebar] .text-sm.font-medium.text-muted-foreground, +[data-sidebar] [data-separator] { + font-size: 11px; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.05em; + margin-top: 20px; + margin-bottom: 6px; + padding-left: 12px; + padding-right: 12px; + color: rgb(115 115 115); + border: none; + background: none; +} + +/* First separator should have less top margin */ +[data-sidebar] [data-separator]:first-of-type { + margin-top: 12px; +} + +/* Clean sidebar item styling */ +[data-sidebar] a { + padding: 8px 12px; + margin: 1px 0; + border-radius: 6px; + font-size: 14px; + font-weight: 400; + line-height: 1.4; + transition: all 0.15s ease; + display: block; + color: rgb(71 85 105); + text-decoration: none; +} + +[data-sidebar] a[data-active="true"] { + background-color: rgba(128, 47, 255, 0.08); + color: var(--color-fd-primary); + font-weight: 500; +} + +[data-sidebar] a:hover:not([data-active="true"]) { + background-color: rgb(248 250 252); + color: rgb(51 65 85); +} + +/* Improve spacing between sidebar items */ +[data-sidebar] nav > * + * { + margin-top: 2px; +} + +/* Section group styling */ +[data-sidebar] [data-folder] { + margin-bottom: 4px; +} + +[data-sidebar] [data-folder] > div:first-child { + font-weight: 500; + font-size: 13px; + color: rgb(15 23 42); + padding: 6px 12px; + margin-bottom: 4px; +} + +/* Clean up folder toggle buttons */ +[data-sidebar] button[data-folder-toggle] { + padding: 4px 8px 4px 12px; + border-radius: 6px; + font-size: 13px; + font-weight: 500; + color: rgb(51 65 85); +} + +[data-sidebar] button[data-folder-toggle]:hover { + background-color: rgb(248 250 252); +} + +/* Nested item indentation */ +[data-sidebar] [data-folder] a { + padding-left: 24px; + font-size: 14px; +} + +/* Dark mode adjustments */ +@media (prefers-color-scheme: dark) { + [data-sidebar] { + background-color: rgb(2 8 23); + } + + [data-sidebar] a { + color: rgb(148 163 184); + } + + [data-sidebar] a:hover:not([data-active="true"]) { + background-color: rgb(30 41 59); + color: rgb(226 232 240); + } + + [data-sidebar] a[data-active="true"] { + background-color: rgba(128, 47, 255, 0.15); + color: var(--color-fd-primary); + } + + [data-sidebar] .text-sm.font-medium.text-muted-foreground, + [data-sidebar] [data-separator] { + color: rgb(148 163 184); + } + + [data-sidebar] [data-folder] > div:first-child { + color: rgb(226 232 240); + } + + [data-sidebar] button[data-folder-toggle] { + color: rgb(148 163 184); + } + + [data-sidebar] button[data-folder-toggle]:hover { + background-color: rgb(30 41 59); + } +} + /* Custom text highlighting styles */ .text-highlight { color: var(--color-fd-primary); @@ -16,6 +160,23 @@ color: var(--color-fd-primary); } +/* Add bottom spacing to prevent abrupt page endings */ +[data-content] { + padding-bottom: 4rem; +} + +/* Alternative fallback for different Fumadocs versions */ +main article, +.docs-page main { + padding-bottom: 4rem; +} + +/* Remove any unwanted borders/outlines from video elements */ +video { + outline: none !important; + border-style: solid !important; +} + /* Tailwind v4 content sources */ @source '../app/**/*.{js,ts,jsx,tsx,mdx}'; @source '../components/**/*.{js,ts,jsx,tsx,mdx}'; diff --git a/apps/docs/components/mdx-components.tsx b/apps/docs/components/mdx-components.tsx deleted file mode 100644 index cdd241bea9..0000000000 --- a/apps/docs/components/mdx-components.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import defaultMdxComponents from 'fumadocs-ui/mdx' -import { ThemeImage } from './ui/theme-image' - -// Extend the default MDX components with our custom components -const mdxComponents = { - ...defaultMdxComponents, - ThemeImage, -} - -export default mdxComponents diff --git a/apps/docs/components/ui/block-types.tsx b/apps/docs/components/ui/block-types.tsx deleted file mode 100644 index c76ecb92d7..0000000000 --- a/apps/docs/components/ui/block-types.tsx +++ /dev/null @@ -1,163 +0,0 @@ -import { - AgentIcon, - ApiIcon, - ChartBarIcon, - CodeIcon, - ConditionalIcon, - ConnectIcon, - ResponseIcon, -} from '@/components/icons' -import { cn } from '@/lib/utils' - -// Custom Feature component specifically for BlockTypes to handle the 6-item layout -const BlockFeature = ({ - title, - description, - icon, - href, - index, - totalItems, - itemsPerRow, -}: { - title: string - description: string - icon: React.ReactNode - href?: string - index: number - totalItems: number - itemsPerRow: number -}) => { - const blockColor = { - '--block-color': - title === 'Agent' - ? '#8b5cf6' - : title === 'API' - ? '#3b82f6' - : title === 'Condition' - ? '#f59e0b' - : title === 'Function' - ? '#10b981' - : title === 'Router' - ? '#6366f1' - : title === 'Evaluator' - ? '#ef4444' - : '#8b5cf6', - } as React.CSSProperties - - const content = ( - <> - {index < itemsPerRow && ( -
- )} - {index >= itemsPerRow && ( -
- )} -
- {icon} -
-
-
- - {title} - -
-

- {description} -

- - ) - - const containerClasses = cn( - 'flex flex-col lg:border-r py-5 relative group/feature dark:border-neutral-800', - (index === 0 || index === itemsPerRow) && 'lg:border-l dark:border-neutral-800', - index < itemsPerRow && 'lg:border-b dark:border-neutral-800', - href && 'cursor-pointer hover:bg-neutral-50 dark:hover:bg-neutral-900/50 transition-colors' - ) - - if (href) { - return ( - - {content} - - ) - } - - return
{content}
-} - -export function BlockTypes() { - const features = [ - { - title: 'Agent', - description: - 'Create powerful AI agents using any LLM provider with customizable system prompts and tool integrations.', - icon: , - href: '/blocks/agent', - }, - { - title: 'API', - description: - 'Connect to any external API with support for all standard HTTP methods and customizable request parameters.', - icon: , - href: '/blocks/api', - }, - { - title: 'Condition', - description: - 'Add a condition to the workflow to branch the execution path based on a boolean expression.', - icon: , - href: '/blocks/condition', - }, - { - title: 'Function', - description: - 'Execute custom JavaScript or TypeScript code within your workflow to transform data or implement complex logic.', - icon: , - href: '/blocks/function', - }, - { - title: 'Router', - description: - 'Intelligently direct workflow execution to different paths based on input analysis.', - icon: , - href: '/blocks/router', - }, - { - title: 'Evaluator', - description: - 'Assess content using customizable evaluation metrics and scoring criteria across multiple dimensions.', - icon: , - href: '/blocks/evaluator', - }, - { - title: 'Response', - description: - 'Send a response back to the caller with customizable data, status, and headers.', - icon: , - href: '/blocks/response', - }, - ] - - const totalItems = features.length - const itemsPerRow = 3 // For large screens - - return ( -
- {features.map((feature, index) => ( - - ))} -
- ) -} diff --git a/apps/docs/components/ui/features.tsx b/apps/docs/components/ui/features.tsx deleted file mode 100644 index 94ae6b72de..0000000000 --- a/apps/docs/components/ui/features.tsx +++ /dev/null @@ -1,102 +0,0 @@ -import { - IconAdjustmentsBolt, - IconCloud, - IconEaseInOut, - IconHeart, - IconHelp, - IconHistory, - IconRouteAltLeft, - IconTerminal2, -} from '@tabler/icons-react' -import { cn } from '@/lib/utils' - -export function Features() { - const features = [ - { - title: 'Multi-LLM Support', - description: 'Connect to any LLM provider including OpenAI, Anthropic, and more', - icon: , - }, - { - title: 'API Deployment', - description: 'Deploy your workflows as secure, scalable APIs', - icon: , - }, - { - title: 'Webhook Integration', - description: 'Trigger workflows via webhooks from external services', - icon: , - }, - { - title: 'Scheduled Execution', - description: 'Schedule workflows to run at specific times or intervals', - icon: , - }, - { - title: '40+ Integrations', - description: 'Connect to hundreds of external services and data sources', - icon: , - }, - { - title: 'Visual Debugging', - description: 'Debug workflows visually with detailed execution logs', - icon: , - }, - { - title: 'Version Control', - description: 'Track changes and roll back to previous versions', - icon: , - }, - { - title: 'Team Collaboration', - description: 'Collaborate with team members on workflow development', - icon: , - }, - ] - return ( -
- {features.map((feature, index) => ( - - ))} -
- ) -} - -export const Feature = ({ - title, - description, - icon, - index, -}: { - title: string - description: string - icon: React.ReactNode - index: number -}) => { - return ( -
- {index < 4 && ( -
- )} - {index >= 4 && ( -
- )} -
{icon}
-
-
- - {title} - -
-

- {description} -

-
- ) -} diff --git a/apps/docs/components/ui/image.tsx b/apps/docs/components/ui/image.tsx new file mode 100644 index 0000000000..dc9ce29ec0 --- /dev/null +++ b/apps/docs/components/ui/image.tsx @@ -0,0 +1,53 @@ +'use client' + +import { useState } from 'react' +import NextImage, { type ImageProps as NextImageProps } from 'next/image' +import { cn } from '@/lib/utils' +import { Lightbox } from './lightbox' + +interface ImageProps extends Omit { + className?: string + enableLightbox?: boolean +} + +export function Image({ + className = 'w-full rounded-xl border border-border shadow-sm overflow-hidden', + enableLightbox = true, + alt = '', + src, + ...props +}: ImageProps) { + const [isLightboxOpen, setIsLightboxOpen] = useState(false) + + const handleImageClick = () => { + if (enableLightbox) { + setIsLightboxOpen(true) + } + } + + return ( + <> + + + {enableLightbox && ( + setIsLightboxOpen(false)} + src={typeof src === 'string' ? src : String(src)} + alt={alt} + type='image' + /> + )} + + ) +} diff --git a/apps/docs/components/ui/lightbox.tsx b/apps/docs/components/ui/lightbox.tsx new file mode 100644 index 0000000000..0dacda7e24 --- /dev/null +++ b/apps/docs/components/ui/lightbox.tsx @@ -0,0 +1,74 @@ +'use client' + +import { useEffect, useRef } from 'react' +import { getVideoUrl } from '@/lib/utils' + +interface LightboxProps { + isOpen: boolean + onClose: () => void + src: string + alt: string + type: 'image' | 'video' +} + +export function Lightbox({ isOpen, onClose, src, alt, type }: LightboxProps) { + const overlayRef = useRef(null) + + useEffect(() => { + const handleKeyDown = (event: KeyboardEvent) => { + if (event.key === 'Escape') { + onClose() + } + } + + const handleClickOutside = (event: MouseEvent) => { + if (overlayRef.current && event.target === overlayRef.current) { + onClose() + } + } + + if (isOpen) { + document.addEventListener('keydown', handleKeyDown) + document.addEventListener('click', handleClickOutside) + document.body.style.overflow = 'hidden' + } + + return () => { + document.removeEventListener('keydown', handleKeyDown) + document.removeEventListener('click', handleClickOutside) + document.body.style.overflow = 'unset' + } + }, [isOpen, onClose]) + + if (!isOpen) return null + + return ( +
+
+ {type === 'image' ? ( + {alt} + ) : ( +
+
+ ) +} diff --git a/apps/docs/components/ui/theme-image.tsx b/apps/docs/components/ui/theme-image.tsx deleted file mode 100644 index 000029f812..0000000000 --- a/apps/docs/components/ui/theme-image.tsx +++ /dev/null @@ -1,48 +0,0 @@ -'use client' - -import { useEffect, useState } from 'react' -import Image from 'next/image' -import { useTheme } from 'next-themes' - -interface ThemeImageProps { - lightSrc: string - darkSrc: string - alt: string - width?: number - height?: number - className?: string -} - -export function ThemeImage({ - lightSrc, - darkSrc, - alt, - width = 600, - height = 400, - className = 'rounded-lg border border-border my-6', -}: ThemeImageProps) { - const { resolvedTheme } = useTheme() - const [imageSrc, setImageSrc] = useState(lightSrc) - const [mounted, setMounted] = useState(false) - - // Wait until component is mounted to avoid hydration mismatch - useEffect(() => { - setMounted(true) - }, []) - - useEffect(() => { - if (mounted) { - setImageSrc(resolvedTheme === 'dark' ? darkSrc : lightSrc) - } - }, [resolvedTheme, lightSrc, darkSrc, mounted]) - - if (!mounted) { - return null - } - - return ( -
- {alt} -
- ) -} diff --git a/apps/docs/components/ui/video.tsx b/apps/docs/components/ui/video.tsx index 3313509f84..d25ecfb1f8 100644 --- a/apps/docs/components/ui/video.tsx +++ b/apps/docs/components/ui/video.tsx @@ -1,4 +1,8 @@ +'use client' + +import { useState } from 'react' import { getVideoUrl } from '@/lib/utils' +import { Lightbox } from './lightbox' interface VideoProps { src: string @@ -7,24 +11,47 @@ interface VideoProps { loop?: boolean muted?: boolean playsInline?: boolean + enableLightbox?: boolean } export function Video({ src, - className = 'w-full -mb-2 rounded-lg', + className = 'w-full rounded-xl border border-border shadow-sm overflow-hidden outline-none focus:outline-none', autoPlay = true, loop = true, muted = true, playsInline = true, + enableLightbox = true, }: VideoProps) { + const [isLightboxOpen, setIsLightboxOpen] = useState(false) + + const handleVideoClick = () => { + if (enableLightbox) { + setIsLightboxOpen(true) + } + } + return ( -
-### Create Support Ticket - -
-

Scenario: Submit support request to ticketing system

-
    -
  1. Agent analyzes user issue and generates ticket data
  2. -
  3. API block POSTs ticket to support system
  4. -
  5. Condition block checks if ticket was created successfully
  6. -
  7. Response block confirms ticket creation with ID
  8. -
-
- ### Payment Processing
@@ -222,7 +220,7 @@ if ( === 200) {
  • Function block validates payment data
  • API block creates payment intent via Stripe
  • Condition block handles payment success/failure
  • -
  • Function block updates order status in database
  • +
  • Supabase block updates order status in database
  • diff --git a/apps/docs/content/docs/blocks/condition.mdx b/apps/docs/content/docs/blocks/condition.mdx index 998fde8e1b..4e6f19004b 100644 --- a/apps/docs/content/docs/blocks/condition.mdx +++ b/apps/docs/content/docs/blocks/condition.mdx @@ -1,23 +1,24 @@ --- title: Condition -description: Create conditional logic and branching in your workflows --- import { Callout } from 'fumadocs-ui/components/callout' import { Step, Steps } from 'fumadocs-ui/components/steps' import { Tab, Tabs } from 'fumadocs-ui/components/tabs' import { Accordion, Accordions } from 'fumadocs-ui/components/accordion' -import { ThemeImage } from '@/components/ui/theme-image' +import { Image } from '@/components/ui/image' -The Condition block allows you to branch your workflow execution path based on boolean expressions. It evaluates conditions and routes the workflow accordingly, enabling you to create dynamic, responsive workflows with different execution paths. +The Condition block allows you to branch your workflow execution path based on boolean expressions, enabling you to create dynamic, responsive workflows with different execution paths. It evaluates conditions and routes the workflow accordingly, letting you control execution flow based on data or logic without requiring an LLM. - +
    + Condition Block +
    Condition blocks enable deterministic decision-making without requiring an LLM, making them ideal diff --git a/apps/docs/content/docs/blocks/evaluator.mdx b/apps/docs/content/docs/blocks/evaluator.mdx index 85291f2bf3..26b4bae3ed 100644 --- a/apps/docs/content/docs/blocks/evaluator.mdx +++ b/apps/docs/content/docs/blocks/evaluator.mdx @@ -1,31 +1,52 @@ --- title: Evaluator -description: Assess content quality using customizable evaluation metrics --- import { Callout } from 'fumadocs-ui/components/callout' import { Step, Steps } from 'fumadocs-ui/components/steps' import { Tab, Tabs } from 'fumadocs-ui/components/tabs' -import { ThemeImage } from '@/components/ui/theme-image' +import { Image } from '@/components/ui/image' import { Video } from '@/components/ui/video' -The Evaluator block uses AI to score and assess content quality based on metrics you define. Perfect for quality control, A/B testing, and ensuring your AI outputs meet specific standards. +The Evaluator block uses AI to score and assess content quality using customizable evaluation metrics that you define. Perfect for quality control, A/B testing, and ensuring your AI outputs meet specific standards. - +
    + Evaluator Block Configuration +
    -## What You Can Evaluate +## Overview -**AI-Generated Content**: Score chatbot responses, generated articles, or marketing copy -**User Input**: Evaluate customer feedback, survey responses, or form submissions -**Content Quality**: Assess clarity, accuracy, relevance, and tone -**Performance Metrics**: Track improvements over time with consistent scoring -**A/B Testing**: Compare different approaches with objective metrics +The Evaluator block enables you to: + + + + Score Content Quality: Use AI to evaluate content against custom metrics with numeric scores + + + Define Custom Metrics: Create specific evaluation criteria tailored to your use case + + + Automate Quality Control: Build workflows that automatically assess and filter content + + + Track Performance: Monitor improvements and consistency over time with objective scoring + + + +## How It Works + +The Evaluator block processes content through AI-powered assessment: + +1. **Receive Content** - Takes input content from previous blocks in your workflow +2. **Apply Metrics** - Evaluates content against your defined custom metrics +3. **Generate Scores** - AI model assigns numeric scores for each metric +4. **Provide Summary** - Returns detailed evaluation with scores and explanations ## Configuration Options @@ -64,7 +85,7 @@ Choose an AI model to perform the evaluation: **Local Models**: Any model running on Ollama
    -
    **Recommendation**: Use models with strong reasoning capabilities like GPT-4o or Claude 3.7 Sonnet for more accurate evaluations. @@ -81,46 +102,93 @@ Your API key for the selected LLM provider. This is securely stored and used for 4. The LLM evaluates the content and returns numeric scores for each metric 5. The Evaluator block formats these scores as structured output for use in your workflow +## Example Use Cases + +### Content Quality Assessment + +
    +

    Scenario: Evaluate blog post quality before publication

    +
      +
    1. Agent block generates blog post content
    2. +
    3. Evaluator assesses accuracy, readability, and engagement
    4. +
    5. Condition block checks if scores meet minimum thresholds
    6. +
    7. High scores → Publish, Low scores → Revise and retry
    8. +
    +
    + +### A/B Testing Content + +
    +

    Scenario: Compare multiple AI-generated responses

    +
      +
    1. Parallel block generates multiple response variations
    2. +
    3. Evaluator scores each variation on clarity and relevance
    4. +
    5. Function block selects highest-scoring response
    6. +
    7. Response block returns the best result
    8. +
    +
    + +### Customer Support Quality Control + +
    +

    Scenario: Ensure support responses meet quality standards

    +
      +
    1. Support agent generates response to customer inquiry
    2. +
    3. Evaluator scores helpfulness, empathy, and accuracy
    4. +
    5. Scores logged for training and performance monitoring
    6. +
    7. Low scores trigger human review process
    8. +
    +
    + ## Inputs and Outputs -### Inputs - -- **Content**: The text or structured data to evaluate -- **Metrics**: Custom evaluation criteria with scoring ranges -- **Model Settings**: LLM provider and parameters - -### Outputs - -- **Content**: A summary of the evaluation -- **Model**: The model used for evaluation -- **Tokens**: Usage statistics -- **Metric Scores**: Numeric scores for each defined metric - -## Example Usage - -Here's an example of how an Evaluator block might be configured for assessing customer service responses: - -```yaml -# Example Evaluator Configuration -metrics: - - name: Empathy - description: How well does the response acknowledge and address the customer's emotional state? - range: - min: 1 - max: 5 - - name: Solution - description: How effectively does the response solve the customer's problem? - range: - min: 1 - max: 5 - - name: Clarity - description: How clear and easy to understand is the response? - range: - min: 1 - max: 5 - -model: Anthropic/claude-3-opus -``` + + +
      +
    • + Content: The text or structured data to evaluate +
    • +
    • + Evaluation Metrics: Custom criteria with scoring ranges +
    • +
    • + Model: AI model for evaluation analysis +
    • +
    • + API Key: Authentication for selected LLM provider +
    • +
    +
    + +
      +
    • + evaluator.content: Summary of the evaluation +
    • +
    • + evaluator.model: Model used for evaluation +
    • +
    • + evaluator.tokens: Token usage statistics +
    • +
    • + evaluator.cost: Cost summary for the evaluation call +
    • +
    +
    + +
      +
    • + Metric Scores: Numeric scores for each defined metric +
    • +
    • + Evaluation Summary: Detailed assessment with explanations +
    • +
    • + Access: Available in blocks after the evaluator +
    • +
    +
    +
    ## Best Practices diff --git a/apps/docs/content/docs/blocks/function.mdx b/apps/docs/content/docs/blocks/function.mdx index 753b0bff10..b11a55ba81 100644 --- a/apps/docs/content/docs/blocks/function.mdx +++ b/apps/docs/content/docs/blocks/function.mdx @@ -1,22 +1,23 @@ --- title: Function -description: Execute custom JavaScript or TypeScript code in your workflows --- import { Callout } from 'fumadocs-ui/components/callout' import { Step, Steps } from 'fumadocs-ui/components/steps' import { Tab, Tabs } from 'fumadocs-ui/components/tabs' -import { ThemeImage } from '@/components/ui/theme-image' +import { Image } from '@/components/ui/image' -The Function block lets you run custom JavaScript or TypeScript code in your workflow. Use it to transform data, perform calculations, or implement custom logic that isn't available in other blocks. +The Function block lets you execute custom JavaScript or TypeScript code in your workflows. Use it to transform data, perform calculations, or implement custom logic that isn't available in other blocks. - +
    + Function Block with Code Editor +
    ## Overview @@ -42,164 +43,25 @@ The Function block enables you to: The Function block runs your code in a secure, isolated environment: 1. **Receive Input**: Access data from previous blocks via the `input` object -2. **Execute Code**: Run your JavaScript/TypeScript code +2. **Execute Code**: Run your JavaScript/Python code 3. **Return Results**: Use `return` to pass data to the next block 4. **Handle Errors**: Built-in error handling and logging -## Configuration Options +## Remote Execution (E2B) -### Code Editor - -Write your JavaScript/TypeScript code in a full-featured editor with: -- Syntax highlighting and error checking -- Line numbers and bracket matching -- Support for modern JavaScript features -- Native support for `fetch` - -### Accessing Input Data - -Use the `input` object to access data from previous blocks: - -```javascript -// Access data from connected blocks -const userData = ; -const orderData = ; - -// Access specific fields -const customerName = ; -const total = ; -``` - -### Common Examples - -**Data Transformation**: -```javascript -// Convert and format data -const formatted = { - name: + ' ' + , - email: .toLowerCase(), - joinDate: new Date().toLocaleDateString() -}; -return formatted; -``` - -**Calculations**: -```javascript -// Calculate discounts and totals -const subtotal = .reduce((sum, item) => sum + item.price, 0); -const discount = subtotal > 100 ? 0.1 : 0; -const total = subtotal * (1 - discount); - -return { subtotal, discount, total }; -``` - -**Data Validation**: -```javascript -// Validate email format -const email = ; -const isValid = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email); - -if (!isValid) { - throw new Error('Invalid email format'); -} -return { email, isValid }; -``` - -### Accessing Results - -After a function executes, you can access its outputs: - -- **``**: The value returned from your function -- **``**: Any console.log() output from your code - -## Advanced Features - -### Async/Await Support - -Use async functions for complex operations: - -```javascript -// Async function example -const processData = async () => { - const data = ; - - // Process data with async operations - const processed = await Promise.all( - data.map(async (item) => { - return { - id: item.id, - processed: true, - timestamp: new Date().toISOString() - }; - }) - ); - - return processed; -}; - -return await processData(); -``` - -### Error Handling - -Implement robust error handling: - -```javascript -try { - const result = ; - - if (!result || !result.length) { - throw new Error('No data received'); - } - - return result.map(item => ({ - id: item.id, - name: item.name.trim(), - valid: true - })); -} catch (error) { - console.error('Processing failed:', error.message); - return { error: error.message, valid: false }; -} -``` - -### Performance Optimization - -Optimize for large datasets: - -```javascript -// Efficient data processing -const data = ; - -// Use efficient array methods -const processed = data - .filter(item => item.status === 'active') - .map(item => ({ - id: item.id, - summary: item.description.substring(0, 100) - })) - .slice(0, 1000); // Limit results - -return processed; -``` - -## Security and Limitations - - - Functions run in a secure environment with these restrictions: - - **Execution timeout**: 30 seconds maximum to prevent infinite loops - - **Memory limits**: Limited memory to prevent resource exhaustion - - **No network access**: Cannot make HTTP requests (use API blocks instead) - - **Limited APIs**: Only safe JavaScript APIs are available - + - **Languages**: Run JavaScript and Python in an isolated E2B sandbox. + - **How to enable**: Toggle “Remote Code Execution” in the Function block. + - **When to use**: Heavier logic, external libraries, or Python-specific code. + - **Performance**: Slower than local JS due to sandbox startup and network overhead. + - **Notes**: Requires `E2B_API_KEY` if running locally. For lowest latency, use natively local JS (Fast Mode). ## Inputs and Outputs - +
    • - Code: Your JavaScript/TypeScript code to execute + Code: Your JavaScript/Python code to execute
    • Timeout: Maximum execution time (defaults to 30 seconds) @@ -217,25 +79,6 @@ return processed;
    • function.stdout: Console.log() output from your code
    • -
    • - function.error: Error details if function failed -
    • -
    • - function.execution_time: Time taken to execute -
    • -
    -
    - -
      -
    • - Function Result: Primary output from your code -
    • -
    • - Debug Information: Logs and execution details -
    • -
    • - Access: Available in blocks after the function -
    diff --git a/apps/docs/content/docs/blocks/index.mdx b/apps/docs/content/docs/blocks/index.mdx index 84a4816069..473572e8ed 100644 --- a/apps/docs/content/docs/blocks/index.mdx +++ b/apps/docs/content/docs/blocks/index.mdx @@ -6,13 +6,12 @@ description: The building components of your AI workflows import { Card, Cards } from 'fumadocs-ui/components/card' import { Step, Steps } from 'fumadocs-ui/components/steps' import { Tab, Tabs } from 'fumadocs-ui/components/tabs' -import { BlockTypes } from '@/components/ui/block-types' import { Video } from '@/components/ui/video' Blocks are the building components you connect together to create AI workflows. Think of them as specialized modules that each handle a specific task—from chatting with AI models to making API calls or processing data.
    -
    ## Core Block Types @@ -32,8 +31,6 @@ Sim provides seven core block types that handle the essential functions of AI wo ### Output Blocks - **[Response](/blocks/response)** - Format and return final results from your workflow - - ## How Blocks Work Each block has three main components: @@ -63,7 +60,7 @@ You create workflows by connecting blocks together. The output of one block beco - **Branching paths**: Some blocks can route to different paths based on conditions
    -
    ## Common Patterns diff --git a/apps/docs/content/docs/blocks/loop.mdx b/apps/docs/content/docs/blocks/loop.mdx index 11a75f3535..7d5a47c0bd 100644 --- a/apps/docs/content/docs/blocks/loop.mdx +++ b/apps/docs/content/docs/blocks/loop.mdx @@ -1,22 +1,15 @@ --- title: Loop -description: Create iterative workflows with loops that execute blocks repeatedly --- import { Callout } from 'fumadocs-ui/components/callout' import { Step, Steps } from 'fumadocs-ui/components/steps' import { Tab, Tabs } from 'fumadocs-ui/components/tabs' -import { ThemeImage } from '@/components/ui/theme-image' +import { Image } from '@/components/ui/image' -The Loop block is a container block in Sim that allows you to execute a group of blocks repeatedly. Loops enable iterative processing in your workflows. +The Loop block is a container block in Sim that allows you to create iterative workflows by executing a group of blocks repeatedly. Loops enable iterative processing in your workflows. - +The Loop block supports two types of iteration: Loop blocks are container nodes that can hold other blocks inside them. The blocks inside a loop will execute multiple times based on your configuration. @@ -33,8 +26,23 @@ The Loop block enables you to: Repeat operations: Execute blocks a fixed number of times + + Sequential processing: Handle data transformation in ordered iterations + + + Aggregate results: Collect outputs from all loop iterations + +## How It Works + +The Loop block executes contained blocks through sequential iteration: + +1. **Initialize Loop** - Set up iteration parameters (count or collection) +2. **Execute Iteration** - Run contained blocks for current iteration +3. **Collect Results** - Store output from each iteration +4. **Continue or Complete** - Move to next iteration or finish loop + ## Configuration Options ### Loop Type @@ -43,7 +51,19 @@ Choose between two types of loops: - A numeric loop that executes a fixed number of times. Use this when you need to repeat an operation a specific number of times. + **For Loop (Iterations)** - A numeric loop that executes a fixed number of times: + +
    + For Loop with iterations +
    + + Use this when you need to repeat an operation a specific number of times. ``` Example: Run 5 times @@ -55,7 +75,19 @@ Choose between two types of loops: ```
    - A collection-based loop that iterates over each item in an array or object. Use this when you need to process a collection of items. + **ForEach Loop (Collection)** - A collection-based loop that iterates over each item in an array or object: + +
    + ForEach Loop with collection +
    + + Use this when you need to process a collection of items. ``` Example: Process ["apple", "banana", "orange"] diff --git a/apps/docs/content/docs/blocks/meta.json b/apps/docs/content/docs/blocks/meta.json index b231fe1bd9..511620d6a9 100644 --- a/apps/docs/content/docs/blocks/meta.json +++ b/apps/docs/content/docs/blocks/meta.json @@ -11,5 +11,6 @@ "response", "router", "workflow" - ] + ], + "defaultOpen": false } diff --git a/apps/docs/content/docs/blocks/parallel.mdx b/apps/docs/content/docs/blocks/parallel.mdx index 4d1ae1dab8..2fa9fc64f7 100644 --- a/apps/docs/content/docs/blocks/parallel.mdx +++ b/apps/docs/content/docs/blocks/parallel.mdx @@ -1,22 +1,15 @@ --- title: Parallel -description: Execute multiple blocks concurrently for faster workflow processing --- import { Callout } from 'fumadocs-ui/components/callout' import { Step, Steps } from 'fumadocs-ui/components/steps' import { Tab, Tabs } from 'fumadocs-ui/components/tabs' -import { ThemeImage } from '@/components/ui/theme-image' +import { Image } from '@/components/ui/image' -The Parallel block is a container block in Sim that allows you to execute multiple instances of blocks concurrently. +The Parallel block is a container block in Sim that allows you to execute multiple instances of blocks concurrently for faster workflow processing. - +The Parallel block supports two types of concurrent execution: Parallel blocks are container nodes that execute their contents multiple times simultaneously, unlike loops which execute sequentially. @@ -49,7 +42,19 @@ Choose between two types of parallel execution: - Execute a fixed number of parallel instances. Use this when you need to run the same operation multiple times concurrently. + **Count-based Parallel** - Execute a fixed number of parallel instances: + +
    + Count-based parallel execution +
    + + Use this when you need to run the same operation multiple times concurrently. ``` Example: Run 5 parallel instances @@ -61,7 +66,19 @@ Choose between two types of parallel execution: ```
    - Distribute a collection across parallel instances. Each instance processes one item from the collection simultaneously. + **Collection-based Parallel** - Distribute a collection across parallel instances: + +
    + Collection-based parallel execution +
    + + Each instance processes one item from the collection simultaneously. ``` Example: Process ["task1", "task2", "task3"] in parallel @@ -105,8 +122,8 @@ After a parallel block completes, you can access aggregated results:

    Scenario: Get responses from multiple AI models

      -
    1. Count-based parallel set to 3 instances
    2. -
    3. Inside parallel: Agent configured with different model per instance
    4. +
    5. Collection-based parallel over a list of model IDs (e.g., ["gpt-4o", "claude-3.7-sonnet", "gemini-2.5-pro"])
    6. +
    7. Inside parallel: Agent's model is set to the current item from the collection
    8. After parallel: Compare and select best response
    diff --git a/apps/docs/content/docs/blocks/response.mdx b/apps/docs/content/docs/blocks/response.mdx index 5523cffdb0..5a59e823ea 100644 --- a/apps/docs/content/docs/blocks/response.mdx +++ b/apps/docs/content/docs/blocks/response.mdx @@ -1,33 +1,61 @@ --- title: Response -description: Send a structured response back to API calls --- import { Callout } from 'fumadocs-ui/components/callout' import { Step, Steps } from 'fumadocs-ui/components/steps' import { Tab, Tabs } from 'fumadocs-ui/components/tabs' -import { ThemeImage } from '@/components/ui/theme-image' +import { Image } from '@/components/ui/image' -The Response block is the final step in your workflow that formats and returns data to whoever called your workflow. It's like the "return" statement for your entire workflow—it packages up results and sends them back. +The Response block is the final step in your workflow that formats and sends a structured response back to API calls. It's like the "return" statement for your entire workflow—it packages up results and sends them back. - +
    + Response Block Configuration +
    Response blocks are terminal blocks - they end the workflow execution and cannot connect to other blocks. +## Overview + +The Response block enables you to: + + + + Format API Responses: Structure workflow results into proper HTTP responses + + + Set Status Codes: Configure appropriate HTTP status codes based on workflow outcomes + + + Control Headers: Add custom headers for API responses and webhooks + + + Transform Data: Convert workflow variables into client-friendly response formats + + + +## How It Works + +The Response block finalizes workflow execution: + +1. **Collect Data** - Gathers variables and outputs from previous blocks +2. **Format Response** - Structures data according to your configuration +3. **Set HTTP Details** - Applies status codes and headers +4. **Send Response** - Returns the formatted response to the API caller + ## When You Need Response Blocks -**API Endpoints**: When your workflow is called via API, Response blocks format the return data -**Webhooks**: Return confirmation or data back to the calling system -**Testing**: See formatted results when testing your workflow -**Data Export**: Structure data for external systems or reports +- **API Endpoints**: When your workflow is called via API, Response blocks format the return data +- **Webhooks**: Return confirmation or data back to the calling system +- **Testing**: See formatted results when testing your workflow ## Two Ways to Build Responses @@ -83,9 +111,9 @@ Set the HTTP status code for the response. Common status codes include:
    -

    +

    Default status code is 200 if not specified. -

    +
    ### Response Headers @@ -99,27 +127,90 @@ Headers are configured as key-value pairs: | Cache-Control | no-cache | | X-API-Version | 1.0 | +## Example Use Cases + +### API Endpoint Response + +
    +

    Scenario: Return structured data from a search API

    +
      +
    1. Workflow processes search query and retrieves results
    2. +
    3. Function block formats and paginates results
    4. +
    5. Response block returns JSON with data, pagination, and metadata
    6. +
    7. Client receives structured response with 200 status
    8. +
    +
    + +### Webhook Confirmation + +
    +

    Scenario: Acknowledge webhook receipt and processing

    +
      +
    1. Webhook trigger receives external system data
    2. +
    3. Workflow processes the incoming data
    4. +
    5. Response block returns confirmation with processing status
    6. +
    7. External system receives acknowledgment
    8. +
    +
    + +### Error Response Handling + +
    +

    Scenario: Return appropriate error responses

    +
      +
    1. Condition block detects validation failure or system error
    2. +
    3. Router directs to error handling path
    4. +
    5. Response block returns 400/500 status with error details
    6. +
    7. Client receives structured error information
    8. +
    +
    + ## Inputs and Outputs - +
    • - data (JSON, optional): The JSON data to send in the response body + Response Data: JSON structure for response body
    • - status (number, optional): HTTP status code (default: 200) + Status Code: HTTP status code (default: 200)
    • - headers (JSON, optional): Additional response headers + Headers: Custom HTTP headers as key-value pairs +
    • +
    • + Mode: Builder or Editor mode for response construction
      -
    • data: The response body data
    • -
    • status: HTTP status code
    • -
    • headers: Response headers
    • +
    • + response.data: The structured response body +
    • +
    • + response.status: HTTP status code sent +
    • +
    • + response.headers: Headers included in response +
    • +
    • + response.success: Boolean indicating successful completion +
    • +
    +
    + +
      +
    • + HTTP Response: Complete response sent to API caller +
    • +
    • + Workflow Termination: Ends workflow execution +
    • +
    • + Access: Response blocks are terminal - no subsequent blocks +
    @@ -146,36 +237,6 @@ Use the `` syntax to dynamically insert workflow variables into y Variable names are case-sensitive and must match exactly with the variables available in your workflow.
    -## Example Usage - -Here's an example of how a Response block might be configured for a user search API: - -```yaml -data: | - { - "success": true, - "data": { - "users": "", - "pagination": { - "page": "", - "limit": "", - "total": "" - } - }, - "query": { - "searchTerm": "", - "filters": "" - }, - "timestamp": "" - } -status: 200 -headers: - - key: X-Total-Count - value: - - key: Cache-Control - value: public, max-age=300 -``` - ## Best Practices - **Use meaningful status codes**: Choose appropriate HTTP status codes that accurately reflect the outcome of the workflow diff --git a/apps/docs/content/docs/blocks/router.mdx b/apps/docs/content/docs/blocks/router.mdx index bd189064da..b83d0c7481 100644 --- a/apps/docs/content/docs/blocks/router.mdx +++ b/apps/docs/content/docs/blocks/router.mdx @@ -1,24 +1,25 @@ --- title: Router -description: Route workflow execution based on specific conditions or logic --- import { Callout } from 'fumadocs-ui/components/callout' import { Step, Steps } from 'fumadocs-ui/components/steps' import { Tab, Tabs } from 'fumadocs-ui/components/tabs' import { Accordion, Accordions } from 'fumadocs-ui/components/accordion' -import { ThemeImage } from '@/components/ui/theme-image' +import { Image } from '@/components/ui/image' import { Video } from '@/components/ui/video' -The Router block uses AI to intelligently decide which path your workflow should take next. Unlike Condition blocks that use simple rules, Router blocks can understand context and make smart routing decisions based on content analysis. +The Router block uses AI to intelligently decide which path your workflow should take next, routing workflow execution based on specific conditions or logic. Unlike Condition blocks that use simple rules, Router blocks can understand context and make smart routing decisions based on content analysis. - +
    + Router Block with Multiple Paths +
    ## Overview @@ -104,7 +105,7 @@ Choose an AI model to power the routing decision: **Local Models**: Any model running on Ollama
    -
    **Recommendation**: Use models with strong reasoning capabilities like GPT-4o or Claude 3.7 Sonnet for more accurate routing decisions. @@ -120,6 +121,7 @@ After a router makes a decision, you can access its outputs: - **``**: Summary of the routing prompt used - **``**: Details of the chosen destination block - **``**: Token usage statistics from the LLM +- **``**: Cost summary for the routing call (input, output, total) - **``**: The model used for decision-making ## Advanced Features @@ -135,34 +137,9 @@ Target Block 2: "Billing inquiries, subscription changes, payment issues" Target Block 3: "General questions, feedback, feature requests" ``` -### Multi-Model Routing - -Use different models for different routing scenarios: - -```javascript -// Fast routing for simple cases -Model: GPT-4o-mini -Criteria: Simple, common routing patterns - -// Complex routing for nuanced decisions -Model: Claude 3.7 Sonnet -Criteria: Complex content analysis required -``` - -### Fallback Handling - -Implement robust fallback mechanisms: - -```javascript -// Router configuration -Primary Targets: ["Support", "Sales", "Technical"] -Fallback Target: "General" // Default when no specific match -Confidence Threshold: 0.7 // Minimum confidence for routing -``` - ## Inputs and Outputs - +
    • @@ -190,24 +167,14 @@ Confidence Threshold: 0.7 // Minimum confidence for routing
    • router.tokens: Token usage statistics
    • +
    • + router.cost: Cost summary for the routing call (input, output, total) +
    • router.model: Model used for decision-making
    - -
      -
    • - Routing Decision: Primary path selection result -
    • -
    • - Decision Context: Analysis summary and reasoning -
    • -
    • - Access: Available in blocks after the router -
    • -
    -
    ## Example Use Cases diff --git a/apps/docs/content/docs/blocks/workflow.mdx b/apps/docs/content/docs/blocks/workflow.mdx index 27040ecfc9..fcfa1dd561 100644 --- a/apps/docs/content/docs/blocks/workflow.mdx +++ b/apps/docs/content/docs/blocks/workflow.mdx @@ -1,22 +1,23 @@ --- title: Workflow -description: Execute other workflows as reusable components within your current workflow --- import { Callout } from 'fumadocs-ui/components/callout' import { Step, Steps } from 'fumadocs-ui/components/steps' import { Tab, Tabs } from 'fumadocs-ui/components/tabs' -import { ThemeImage } from '@/components/ui/theme-image' +import { Image } from '@/components/ui/image' -The Workflow block allows you to execute other workflows as reusable components within your current workflow. This powerful feature enables modular design, code reuse, and the creation of complex nested workflows that can be composed from smaller, focused workflows. +The Workflow block allows you to execute other workflows as reusable components within your current workflow. This enables modular design, code reuse, and the creation of complex nested workflows that can be composed from smaller, focused workflows. - +
    + Workflow Block +
    Workflow blocks enable modular design by allowing you to compose complex workflows from smaller, reusable components. @@ -46,9 +47,9 @@ The Workflow block serves as a bridge between workflows, enabling you to: The Workflow block: 1. Takes a reference to another workflow in your workspace -2. Passes input data from the current workflow to the child workflow +2. Passes input data from the current workflow to the child workflow (available via start.input) 3. Executes the child workflow in an isolated context -4. Returns the results back to the parent workflow for further processing +4. Returns the result back to the parent workflow for further processing ## Configuration Options @@ -60,26 +61,6 @@ Choose which workflow to execute from a dropdown list of available workflows in - Workflows shared with you by other team members - Both enabled and disabled workflows (though only enabled workflows can be executed) -### Input Data - -Define the data to pass to the child workflow: - -- **Single Variable Input**: Select a variable or block output to pass to the child workflow -- **Variable References**: Use `` to reference workflow variables -- **Block References**: Use `` to reference outputs from previous blocks -- **Automatic Mapping**: The selected data is automatically available as `start.input` in the child workflow -- **Optional**: The input field is optional - child workflows can run without input data -- **Type Preservation**: Variable types (strings, numbers, objects, etc.) are preserved when passed to the child workflow - -### Accessing Results - -After a workflow executes, you can access its outputs: - -- **``**: The complete output from the child workflow -- **``**: The name of the executed child workflow -- **``**: Boolean indicating successful completion -- **``**: Error details if the workflow failed -- **``**: Time taken to execute the workflow ### Execution Context @@ -88,58 +69,12 @@ The child workflow executes with: - Its own isolated execution context - Access to the same workspace resources (API keys, environment variables) - Proper workspace membership and permission checks -- Independent logging and monitoring - -## Safety and Limitations - -To prevent infinite recursion and ensure system stability, the Workflow block includes several safety mechanisms: +- Nested tracespan in the execution log **Cycle Detection**: The system automatically detects and prevents circular dependencies between workflows to avoid infinite loops. -- **Maximum Depth Limit**: Nested workflows are limited to a maximum depth of 10 levels -- **Cycle Detection**: Automatic detection and prevention of circular workflow dependencies -- **Timeout Protection**: Child workflows inherit timeout settings to prevent indefinite execution -- **Resource Limits**: Memory and execution time limits apply to prevent resource exhaustion - -## Advanced Features - -### Dynamic Workflow Selection - -Select workflows dynamically based on runtime conditions: - -```javascript -// In a Function block before the Workflow block -const workflowId = ? 'premium-workflow' : 'standard-workflow'; -return { selectedWorkflow: workflowId }; -``` - -### Error Handling and Fallbacks - -Implement robust error handling for child workflows: - -```javascript -// In a Function block after the Workflow block -if (!) { - console.error('Child workflow failed:', ); - // Implement fallback logic - return { fallback: true, error: }; -} -return ; -``` - -### Workflow Chaining - -Chain multiple workflows together: - -```javascript -// Pass output from one workflow to another -Workflow 1 Input: -Workflow 2 Input: -Workflow 3 Input: -``` - ## Inputs and Outputs @@ -158,20 +93,17 @@ Workflow 3 Input:
      -
    • - workflow.response: Complete output from child workflow -
    • -
    • - workflow.name: Name of executed child workflow -
    • workflow.success: Boolean indicating completion status
    • - workflow.error: Error details if workflow failed + workflow.childWorkflowName: Name of executed child workflow
    • - workflow.execution_time: Time taken to execute + workflow.result: Result returned by the child workflow +
    • +
    • + workflow.error: Error details if workflow failed
    @@ -228,32 +160,10 @@ Workflow 3 Input:
    -### Example: Customer Validation Workflow - -```javascript title="validation-workflow.js" -// Main workflow passes customer data to validation workflow -const customerData = ; - -// Validation workflow processes the data -const emailValid = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(customerData.email); -const phoneValid = /^\+?[1-9]\d{1,14}$/.test(customerData.phone); - -return { - customer: customerData, - validation: { - email: emailValid, - phone: phoneValid, - overall: emailValid && phoneValid - } -}; -``` - ## Best Practices - **Keep workflows focused**: Design child workflows to handle specific, well-defined tasks with clear inputs and outputs - **Minimize nesting depth**: Avoid deeply nested workflow hierarchies for better maintainability and performance - **Handle errors gracefully**: Implement proper error handling for child workflow failures and provide fallback mechanisms -- **Document dependencies**: Clearly document which workflows depend on others and maintain dependency maps - **Test independently**: Ensure child workflows can be tested and validated independently from parent workflows -- **Monitor performance**: Be aware that nested workflows can impact overall execution time and resource usage - **Use semantic naming**: Give workflows descriptive names that clearly indicate their purpose and functionality diff --git a/apps/docs/content/docs/connections/accessing-data.mdx b/apps/docs/content/docs/connections/accessing-data.mdx deleted file mode 100644 index db5a058bdf..0000000000 --- a/apps/docs/content/docs/connections/accessing-data.mdx +++ /dev/null @@ -1,190 +0,0 @@ ---- -title: Accessing Connected Data -description: Techniques for accessing and manipulating data from connected blocks ---- - -import { Callout } from 'fumadocs-ui/components/callout' -import { File, Files, Folder } from 'fumadocs-ui/components/files' - -Once blocks are connected, you can access data from source blocks in destination blocks using connection tags and various data access techniques. - -## Basic Data Access - -The simplest way to access data is through direct references using connection tags: - - - - - - - - -## Advanced Data Access Techniques - -### Array Access - -You can access array elements using square bracket notation: - -```javascript -// Access the first item in an array - - -// Access a specific property of an array item - - -// Access the last item in an array (in Function blocks) -const items = input.block.items; -const lastItem = items[items.length - 1]; -``` - -### Object Property Access - -Access object properties using dot notation: - -```javascript -// Access a simple property - - -// Access a nested property - - -// Access a property with special characters (in Function blocks) -const data = input.block.data; -const specialProp = data['property-with-dashes']; -``` - -### Dynamic References - -Connection references are evaluated at runtime, allowing for dynamic data flow through your workflow: - -```javascript -// In a Function block, you can access connected data -const userName = input.userBlock.name; -const orderTotal = input.apiBlock.body.order.total; - -// Process the data -const discount = orderTotal > 100 ? 0.1 : 0; -const finalPrice = orderTotal * (1 - discount); - -// Return the result -return { - userName, - originalTotal: orderTotal, - discount: discount * 100 + '%', - finalPrice -}; -``` - -## Data Transformation - -### Using Function Blocks - -Function blocks are the most powerful way to transform data between connections: - -```javascript -// Example: Transform API response data -const apiResponse = input.apiBlock.data; -const transformedData = { - users: apiResponse.results.map(user => ({ - id: user.id, - fullName: `${user.firstName} ${user.lastName}`, - email: user.email.toLowerCase(), - isActive: user.status === 'active' - })), - totalCount: apiResponse.count, - timestamp: new Date().toISOString() -}; - -return transformedData; -``` - -### String Interpolation - -You can combine connection tags with static text: - -``` -Hello, ! Your order # has been processed. -``` - -### Conditional Content - -In Function blocks, you can create conditional content based on connected data: - -```javascript -const user = input.userBlock; -const orderTotal = input.orderBlock.total; - -let message = `Thank you for your order, ${user.name}!`; - -if (orderTotal > 100) { - message += " You've qualified for free shipping!"; -} else { - message += ` Add $${(100 - orderTotal).toFixed(2)} more to qualify for free shipping.`; -} - -return { message }; -``` - -## Handling Missing Data - -It's important to handle cases where connected data might be missing or null: - - - Always validate connected data before using it, especially when accessing nested properties or - array elements. - - -### Default Values - -In Function blocks, you can provide default values for missing data: - -```javascript -const userName = input.userBlock?.name || 'Guest' -const items = input.orderBlock?.items || [] -const total = input.orderBlock?.total ?? 0 -``` - -### Conditional Checks - -Check if data exists before accessing nested properties: - -```javascript -let userEmail = 'No email provided' -if (input.userBlock && input.userBlock.contact && input.userBlock.contact.email) { - userEmail = input.userBlock.contact.email -} -``` - -### Optional Chaining - -In Function blocks, use optional chaining to safely access nested properties: - -```javascript -const userCity = input.userBlock?.address?.city -const firstItemName = input.orderBlock?.items?.[0]?.name -``` - -## Debugging Connection Data - -When troubleshooting connection issues, these techniques can help: - -1. **Log Data**: In Function blocks, use `console.log()` to inspect connected data -2. **Return Full Objects**: Return the full input object to see all available data -3. **Check Types**: Verify the data types of connected values -4. **Validate Paths**: Ensure you're using the correct path to access nested data - -```javascript -// Example debugging function -function debugConnections() { - console.log('All inputs:', input) - console.log('User data type:', typeof input.userBlock) - console.log('Order items:', input.orderBlock?.items) - - return { - debug: true, - allInputs: input, - userExists: !!input.userBlock, - orderItemCount: input.orderBlock?.items?.length || 0, - } -} -``` diff --git a/apps/docs/content/docs/connections/basics.mdx b/apps/docs/content/docs/connections/basics.mdx index 3ae673f7e2..96ddc6af23 100644 --- a/apps/docs/content/docs/connections/basics.mdx +++ b/apps/docs/content/docs/connections/basics.mdx @@ -1,6 +1,5 @@ --- title: Connection Basics -description: Learn how connections work in Sim --- import { Callout } from 'fumadocs-ui/components/callout' @@ -8,7 +7,7 @@ import { Step, Steps } from 'fumadocs-ui/components/steps' ## How Connections Work -Connections are the pathways that allow data to flow between blocks in your workflow. When you connect two blocks in Sim, you're establishing a data flow relationship that defines how information passes from one block to another. +Connections are the pathways that allow data to flow between blocks in your workflow. In Sim, connections define how information passes from one block to another, enabling data flow throughout your workflow. Each connection represents a directed relationship where data flows from a source block's output @@ -28,9 +27,6 @@ Connections are the pathways that allow data to flow between blocks in your work Confirm Connection: Release to create the connection - - Configure (Optional): Some connections may require additional configuration - ### Connection Flow @@ -42,35 +38,7 @@ The flow of data through connections follows these principles: 3. **Data Transformation**: Data may be transformed as it passes between blocks 4. **Conditional Paths**: Some blocks (like Router and Condition) can direct flow to different paths -### Connection Visualization - -Connections are visually represented in the workflow editor: - -- **Solid Lines**: Active connections that will pass data -- **Animated Flow**: During execution, data flow is visualized along connections -- **Color Coding**: Different connection types may have different colors -- **Connection Tags**: Visual indicators showing what data is available - -### Managing Connections - -You can manage your connections in several ways: - -- **Delete**: Click on a connection and press Delete or use the context menu -- **Reroute**: Drag a connection to change its path -- **Inspect**: Click on a connection to see details about the data being passed -- **Disable**: Temporarily disable a connection without deleting it - Deleting a connection will immediately stop data flow between the blocks. Make sure this is intended before removing connections. - -## Connection Compatibility - -Not all blocks can be connected to each other. Compatibility depends on: - -1. **Data Type Compatibility**: The output type must be compatible with the input type -2. **Block Restrictions**: Some blocks may have restrictions on what they can connect to -3. **Workflow Logic**: Connections must make logical sense in the context of your workflow - -The editor will indicate when connections are invalid or incompatible. diff --git a/apps/docs/content/docs/connections/best-practices.mdx b/apps/docs/content/docs/connections/best-practices.mdx deleted file mode 100644 index a178ea791c..0000000000 --- a/apps/docs/content/docs/connections/best-practices.mdx +++ /dev/null @@ -1,208 +0,0 @@ ---- -title: Connection Best Practices -description: Recommended patterns for effective connection management ---- - -import { Callout } from 'fumadocs-ui/components/callout' -import { Step, Steps } from 'fumadocs-ui/components/steps' - -## Workflow Organization - -### Organize Your Connections - -Keep your workflow clean and understandable by organizing connections logically: - -- **Minimize crossing connections** when possible to reduce visual complexity -- **Group related blocks together** to make data flow more intuitive -- **Use consistent flow direction** (typically left-to-right or top-to-bottom) -- **Label complex connections** with descriptive names - - - A well-organized workflow is easier to understand, debug, and maintain. Take time to arrange your - blocks and connections in a logical manner. - - -### Connection Naming Conventions - -When working with multiple connections, consistent naming helps maintain clarity: - - - - Use descriptive block names: Name blocks based on their function (e.g., - "UserDataFetcher", "ResponseGenerator") - - - Be specific with connection references: Use clear variable names when - referencing connections in code - - - Document complex connections: Add comments explaining non-obvious data - transformations - - - -## Data Validation - -### Validate Data Flow - -Ensure that the data being passed between blocks is compatible: - -- **Check that required fields are available** in the source block -- **Verify data types match expectations** before using them -- **Use Function blocks to transform data** when necessary -- **Handle missing or null values** with default values or conditional logic - -```javascript -// Example: Validating and transforming data in a Function block -function processUserData() { - // Validate required fields - if (!input.userBlock || !input.userBlock.id) { - return { error: 'Missing user data', valid: false } - } - - // Transform and validate data types - const userId = String(input.userBlock.id) - const userName = input.userBlock.name || 'Unknown User' - const userScore = Number(input.userBlock.score) || 0 - - return { - valid: true, - user: { - id: userId, - name: userName, - score: userScore, - isHighScore: userScore > 100, - }, - } -} -``` - -## Documentation - -### Document Connection Purpose - -Add comments or descriptions to clarify the purpose of connections, especially in complex workflows: - -- **What data is being passed**: Document the key fields and their purpose -- **Why this connection exists**: Explain the relationship between blocks -- **Any transformations or conditions applied**: Note any data processing that occurs - -```javascript -// Example: Documenting connection purpose in a Function block -/* - * This function processes user data from the UserFetcher block - * and order history from the OrderHistory block to generate - * personalized product recommendations. - * - * Input: - * - userBlock: User profile data (id, preferences, history) - * - orderBlock: Recent order history (items, dates, amounts) - * - * Output: - * - recommendations: Array of recommended product IDs - * - userSegment: Calculated user segment for marketing - * - conversionProbability: Estimated likelihood of purchase - */ -function generateRecommendations() { - // Implementation... -} -``` - -## Testing and Debugging - -### Test Connection References - -Verify that connection references work as expected: - -- **Test with different input values** to ensure robustness -- **Check edge cases** (empty values, large datasets, special characters) -- **Ensure error handling for missing or invalid data** -- **Use console logging in Function blocks** to debug connection issues - -```javascript -// Example: Testing connection references with edge cases -function testConnections() { - console.log('Testing connections...') - - // Log all inputs for debugging - console.log('All inputs:', JSON.stringify(input, null, 2)) - - // Test for missing data - const hasUserData = !!input.userBlock - console.log('Has user data:', hasUserData) - - // Test edge cases - const items = input.orderBlock?.items || [] - console.log('Item count:', items.length) - console.log('Empty items test:', items.length === 0 ? 'Passed' : 'Failed') - - // Return test results - return { - tests: { - hasUserData, - hasItems: items.length > 0, - hasLargeOrder: items.length > 10, - }, - } -} -``` - -## Performance Considerations - -### Optimize Data Flow - -Keep your workflows efficient by optimizing how data flows through connections: - -- **Pass only necessary data** between blocks to reduce memory usage -- **Use Function blocks to filter large datasets** before passing them on -- **Consider caching results** for expensive operations -- **Break complex workflows into smaller, reusable components** - -```javascript -// Example: Optimizing data flow by filtering -function optimizeUserData() { - const userData = input.userBlock - - // Only pass necessary fields to downstream blocks - return { - id: userData.id, - name: userData.name, - email: userData.email, - // Filter out unnecessary profile data, history, etc. - } -} -``` - -## Security Best Practices - -### Secure Sensitive Data - -Protect sensitive information when using connections: - -- **Never expose API keys or credentials** in connection data -- **Sanitize user input** before processing it -- **Redact sensitive information** when logging connection data -- **Use secure connections** for external API calls - - - Be careful when logging connection data that might contain sensitive information. Always redact or - mask sensitive fields like passwords, API keys, or personal information. - - -## Advanced Patterns - -### Conditional Connections - -Use Condition blocks to create dynamic workflows: - -- **Route data based on content** to different processing paths -- **Implement fallback paths** for error handling -- **Create decision trees** for complex business logic - -### Feedback Loops - -Create more sophisticated workflows with feedback connections: - -- **Implement iterative processing** by connecting later blocks back to earlier ones -- **Use Memory blocks** to store state between iterations -- **Set termination conditions** to prevent infinite loops diff --git a/apps/docs/content/docs/connections/data-structure.mdx b/apps/docs/content/docs/connections/data-structure.mdx index 590b94483e..7876b66364 100644 --- a/apps/docs/content/docs/connections/data-structure.mdx +++ b/apps/docs/content/docs/connections/data-structure.mdx @@ -1,12 +1,11 @@ --- title: Connection Data Structure -description: Understanding the data structure of different block outputs --- import { Callout } from 'fumadocs-ui/components/callout' import { Tab, Tabs } from 'fumadocs-ui/components/tabs' -When you connect blocks, the output data structure from the source block determines what values are available in the destination block. Each block type produces a specific output structure that you can reference in downstream blocks. +When you connect blocks, understanding the data structure of different block outputs is important because the output data structure from the source block determines what values are available in the destination block. Each block type produces a specific output structure that you can reference in downstream blocks. Understanding these data structures is essential for effectively using connection tags and @@ -180,7 +179,7 @@ Some blocks may produce custom output structures based on their configuration: Many block outputs contain nested data structures. You can access these using dot notation in connection tags: ``` - + ``` For example: diff --git a/apps/docs/content/docs/connections/meta.json b/apps/docs/content/docs/connections/meta.json index 81197105cb..b86970f3e1 100644 --- a/apps/docs/content/docs/connections/meta.json +++ b/apps/docs/content/docs/connections/meta.json @@ -1,4 +1,5 @@ { "title": "Connections", - "pages": ["basics", "tags", "data-structure", "accessing-data", "best-practices"] + "pages": ["basics", "tags", "data-structure"], + "defaultOpen": false } diff --git a/apps/docs/content/docs/connections/tags.mdx b/apps/docs/content/docs/connections/tags.mdx index f6f974c40d..5adb7c3c67 100644 --- a/apps/docs/content/docs/connections/tags.mdx +++ b/apps/docs/content/docs/connections/tags.mdx @@ -1,12 +1,11 @@ --- title: Connection Tags -description: Using connection tags to reference data between blocks --- import { Callout } from 'fumadocs-ui/components/callout' import { Video } from '@/components/ui/video' -Connection tags are visual representations of the data available from connected blocks. They provide an easy way to reference outputs from previous blocks in your workflow. +Connection tags are visual representations of the data available from connected blocks, providing an easy way to reference data between blocks and outputs from previous blocks in your workflow.