diff --git a/.gitignore b/.gitignore index 2fb783ef..2e0165e9 100644 --- a/.gitignore +++ b/.gitignore @@ -21,3 +21,4 @@ scratch_pad.py *.html usecases/ compare_gemini_outputs_v1.py +node_modules/ diff --git a/README.md b/README.md index 542365e1..8f1b5ed4 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,51 @@ Flo AI is a Python framework for building structured AI agents with support for Flo AI is a Python framework that makes building production-ready AI agents and teams as easy as writing YAML. Think "Kubernetes for AI Agents" - compose complex AI architectures using pre-built components while maintaining the flexibility to create your own. +## 🎨 Flo AI Studio - Visual Workflow Designer + +**Create AI workflows visually with our powerful React-based studio!** + +

+ Flo AI Studio - Visual Workflow Designer +

+ +Flo AI Studio is a modern, intuitive visual editor that allows you to design complex multi-agent workflows through a drag-and-drop interface. Build sophisticated AI systems without writing code, then export them as production-ready YAML configurations. + +### πŸš€ Studio Features + +- **🎯 Visual Design**: Drag-and-drop interface for creating agent workflows +- **πŸ€– Agent Management**: Configure AI agents with different roles, models, and tools +- **πŸ”€ Smart Routing**: Visual router configuration for intelligent workflow decisions +- **πŸ“€ YAML Export**: Export workflows as Flo AI-compatible YAML configurations +- **πŸ“₯ YAML Import**: Import existing workflows for further editing +- **βœ… Workflow Validation**: Real-time validation and error checking +- **πŸ”§ Tool Integration**: Connect agents to external tools and APIs +- **πŸ“‹ Template System**: Quick start with pre-built agent and router templates + +### πŸƒβ€β™‚οΈ Quick Start with Studio + +1. **Start the Studio**: + ```bash + cd studio + pnpm install + pnpm dev + ``` + +2. **Design Your Workflow**: + - Add agents, routers, and tools to the canvas + - Configure their properties and connections + - Test with the built-in validation + +3. **Export & Run**: + ```bash + # Export YAML from the studio, then run with Flo AI + python -c " + from flo_ai.arium import AriumBuilder + builder = AriumBuilder.from_yaml(yaml_file='your_workflow.yaml') + result = await builder.build_and_run(['Your input here']) + " + ``` + ## ✨ Features - πŸ”Œ **Truly Composable**: Build complex AI systems by combining smaller, reusable components diff --git a/flo_ai/examples/example.py b/flo_ai/examples/example.py new file mode 100644 index 00000000..60976ff0 --- /dev/null +++ b/flo_ai/examples/example.py @@ -0,0 +1,143 @@ +""" +Example of running a Flo AI workflow with snake_case agent names +Generated from Flo AI Studio +""" + +import asyncio +from flo_ai.arium import AriumBuilder +from flo_ai.tool.base_tool import Tool + +# Set your OpenAI API key +# os.environ["OPENAI_API_KEY"] = "your-api-key-here" + + +# Create a simple web search tool +async def web_search_function(query: str) -> str: + """Simple web search simulation - replace with actual search API""" + return f"Web search results for '{query}': Found relevant articles about the topic including latest developments, applications, and ethical considerations. [This is a mock search - integrate with real search API like Google, Bing, or DuckDuckGo]" + + +# Create the tool instance +web_search_tool = Tool( + name='web_search', + description='Search the web for information on a given topic', + function=web_search_function, + parameters={ + 'query': { + 'type': 'string', + 'description': 'The search query to look up information about', + } + }, +) + +# YAML workflow definition (exported from Flo AI Studio) +workflow_yaml = """ +metadata: + name: New Workflow + version: 1.0.0 + description: Generated with Flo AI Studio + tags: + - flo-ai + - studio-generated +arium: + agents: + - name: content_analyzer + role: Content Analyst + job: Analyze content and extract key insights, themes, and important information. + model: + provider: openai + name: gpt-4o-mini + settings: + temperature: 0.7 + max_retries: 3 + reasoning_pattern: DIRECT + - name: researcher + role: Research Specialist + job: Research topics and gather comprehensive information using available tools. + model: + provider: openai + name: gpt-4o + tools: + - web_search + - name: summarizer + role: Summary Generator + job: Create concise, actionable summaries from analysis and content. + model: + provider: openai + name: gpt-4o-mini + routers: + - name: smart_router + type: smart + routing_options: + researcher: If there is not enough information & deep research needs to be done + summarizer: If we have enough information and its time to summarize + model: + provider: openai + name: gpt-4o-mini + settings: + temperature: 0.3 + fallback_strategy: first + workflow: + start: content_analyzer + edges: + - from: content_analyzer + to: [researcher, summarizer] + router: smart_router + - from: researcher + to: [summarizer] + end: + - summarizer +""" + + +async def main(): + """Run the workflow""" + print('πŸš€ Starting Flo AI Workflow...') + print('πŸ“‹ Workflow: Content Analysis with Smart Routing') + print('-' * 50) + + try: + # Create tools dictionary (required format for AriumBuilder) + tools = {'web_search': web_search_tool} + + # Create Arium builder from YAML + builder = AriumBuilder.from_yaml(yaml_str=workflow_yaml, tools=tools) + + # Example input for the workflow + user_input = [ + """I need to understand the current trends in artificial intelligence and machine learning. + Specifically, I'm interested in: + 1. Latest developments in large language models + 2. Applications in healthcare and finance + 3. Ethical considerations and regulations + + Please provide a comprehensive analysis and summary.""" + ] + + print('πŸ“ Input:') + print(user_input[0]) + print('\n' + '=' * 50) + print('πŸ”„ Processing workflow...') + print('=' * 50 + '\n') + + # Build and run the workflow + result = await builder.build_and_run(user_input) + + print('βœ… Workflow Result:') + print('-' * 30) + if isinstance(result, list): + for i, message in enumerate(result): + print(f'{i+1}. {message}') + else: + print(result) + + except Exception as e: + print(f'❌ Error running workflow: {str(e)}') + print('\nπŸ’‘ Make sure you have:') + print('1. Set your OPENAI_API_KEY environment variable') + print('2. Installed flo-ai: pip install flo-ai') + print('3. All required dependencies') + + +if __name__ == '__main__': + asyncio.run(main()) diff --git a/images/flo-studio-preview.png b/images/flo-studio-preview.png new file mode 100644 index 00000000..0a43992d Binary files /dev/null and b/images/flo-studio-preview.png differ diff --git a/index.html b/index.html deleted file mode 100644 index 473eabe9..00000000 --- a/index.html +++ /dev/null @@ -1,225 +0,0 @@ - - - - - - - - - - -flo-ai | πŸ”₯πŸ”₯πŸ”₯ Simple way to create composable AI agents - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -

flo-ai

- - -

- Rootflo -

- -

Composable AI Agentic Workflow

- -

-Rootflo is an alternative to Langgraph, and CrewAI. It lets you easily build composable agentic workflows from using simple components to any size, unlocking the full potential of LLMs. -

- -

- GitHub stars - - GitHub release (latest) - - GitHub commit activity - - License - -
-

- -

-
- Checkout the docs Β» -
-
- Github - β€’ - Website - β€’ - Roadmap -

- -
- -

Flo AI 🌊

- -
-

Build production-ready AI agents and teams with minimal code

-
- -

Flo AI is a Python framework that makes building production-ready AI agents and teams as easy as writing YAML. Think β€œKubernetes for AI Agents” - compose complex AI architectures using pre-built components while maintaining the flexibility to create your own.

- -

✨ Features

- - - -

πŸš€ Quick Start

- -

Installation

- -
pip install flo-ai
-# or using poetry
-poetry add flo-ai
-
- -

Create Your First AI Team in 30 Seconds

- -
from flo_ai import Flo, FloSession
-from langchain_openai import ChatOpenAI
-
-# Define your team in YAML
-yaml_config = """
-apiVersion: flo/alpha-v1
-kind: FloRoutedTeam
-name: research-team
-team:
-    name: ResearchTeam
-    router:
-        name: TeamLead
-        kind: supervisor
-    agents:
-      - name: Researcher
-        role: Research Specialist
-        job: Research latest information on given topics
-        tools:
-          - name: TavilySearchResults
-      - name: Writer
-        role: Content Creator
-        job: Create engaging content from research
-"""
-
-# Set up and run
-llm = ChatOpenAI(temperature=0)
-session = FloSession(llm).register_tool(name="TavilySearchResults", tool=TavilySearchResults())
-flo = Flo.build(session, yaml=yaml_config)
-
-# Start streaming results
-for response in flo.stream("Write about recent AI developments"):
-    print(response)
-
- -

πŸ“– Documentation

- -

Visit our comprehensive documentation for:

- - -

🌟 Why Flo AI?

- -

For AI Engineers

- - -

For Teams

- - -

🎯 Use Cases

- - - -

🀝 Contributing

- -

We love your input! Check out our Contributing Guide to get started. Ways to contribute:

- - - -

πŸ“œ License

- -

Flo AI is MIT Licensed.

- -

πŸ™ Acknowledgments

- -

Built with ❀️ using:

- - -
- -
- Built with ❀️ by the Rootflo team -
Community β€’ - Documentation -
- - - - - -
- - - - diff --git a/studio/README.md b/studio/README.md new file mode 100644 index 00000000..69ee426c --- /dev/null +++ b/studio/README.md @@ -0,0 +1,354 @@ +# Flo AI Studio + +A powerful visual designer for creating YAML-based AI agent workflows. Build complex multi-agent workflows with an intuitive drag-and-drop interface, configure agents with comprehensive forms, set up routing logic, and export everything as production-ready YAML. + +## 🌟 Overview + +Flo AI Studio is a React-based visual editor that makes it easy to design and configure AI workflows for the Flo AI framework. It provides a user-friendly interface for creating complex agent orchestrations without writing code. + +## ✨ Features + +- **🎨 Visual Workflow Design**: Drag-and-drop interface using React Flow +- **πŸ€– Agent Management**: Create and edit agents with comprehensive configuration forms +- **πŸ”§ Tool Integration**: Add and configure tools for your agents +- **πŸ”€ Router Configuration**: Define custom routing logic between workflow nodes +- **πŸ“„ YAML Export**: Generate production-ready YAML configurations +- **πŸ“‹ Template System**: Quick agent templates for common use cases +- **βš™οΈ Configuration Management**: Manage available tools, LLMs, and routers +- **πŸ’Ύ State Management**: Robust state management with Zustand +- **🎯 TypeScript**: Fully typed for better development experience + +## πŸš€ Quick Start + +### Installation + +```bash +# Navigate to flo_studio directory +cd flo_studio + +# Install dependencies +pnpm install + +# Start development server +pnpm dev +``` + +### Building for Production + +```bash +# Build the application +pnpm build + +# Preview the build +pnpm preview +``` + +## πŸ—οΈ Architecture + +### Project Structure + +``` +flo_studio/ +β”œβ”€β”€ src/ +β”‚ β”œβ”€β”€ components/ # React components +β”‚ β”‚ β”œβ”€β”€ editors/ # Modal editors (Agent, Edge, Config) +β”‚ β”‚ β”œβ”€β”€ flow/ # React Flow components +β”‚ β”‚ β”œβ”€β”€ sidebar/ # Sidebar components +β”‚ β”‚ β”œβ”€β”€ toolbar/ # Toolbar components +β”‚ β”‚ └── ui/ # Reusable UI components +β”‚ β”œβ”€β”€ store/ # Zustand store +β”‚ β”œβ”€β”€ types/ # TypeScript definitions +β”‚ β”œβ”€β”€ utils/ # Utility functions +β”‚ └── lib/ # Shared utilities +β”œβ”€β”€ public/ # Static assets +└── dist/ # Build output +``` + +### Key Technologies + +- **React 18** - Modern React with hooks and concurrent features +- **TypeScript** - Type safety and better developer experience +- **React Flow** - Graph visualization and interaction +- **Zustand** - Lightweight state management +- **Tailwind CSS** - Utility-first CSS framework +- **Radix UI** - Accessible component primitives +- **React Hook Form** - Form handling with validation +- **js-yaml** - YAML parsing and generation +- **Vite** - Fast build tool and dev server + +## 🎯 Usage Guide + +### Creating Your First Workflow + +1. **Start the Application** + ```bash + pnpm dev + ``` + +2. **Create an Agent** + - Click the "Agent" button in the toolbar + - Fill in the agent configuration form: + - Name and role + - Job description + - LLM model selection + - Tools (optional) + - Output parser (optional) + +3. **Build the Workflow** + - Drag nodes from the sidebar onto the canvas + - Connect nodes by dragging from output handles to input handles + - Configure edge routers by clicking on connections + +4. **Export Configuration** + - Click "Export" in the toolbar + - Review the generated YAML + - Download or copy the configuration + +### Agent Configuration + +Agents can be configured with: + +- **Basic Information**: Name, role, job description +- **Model Settings**: Provider (OpenAI, Anthropic, etc.), model name, temperature +- **Tools**: Select from available tools or add custom ones +- **Output Parser**: Define structured output schemas +- **Reasoning Pattern**: DIRECT, COT (Chain of Thought), or REACT + +### Workflow Features + +- **Visual Connections**: Drag to connect agents and tools +- **Router Functions**: Configure conditional routing between nodes +- **Start/End Nodes**: Automatically detected based on connections +- **Validation**: Real-time validation of workflow structure + +## πŸ”§ Configuration + +### Available LLMs + +The studio comes pre-configured with popular LLM providers: + +- **OpenAI**: GPT-4o, GPT-4o-mini +- **Anthropic**: Claude-3.5-Sonnet, Claude-3.5-Haiku +- **Google**: Gemini-2.5-Flash, Gemini-2.5-Pro +- **Ollama**: Llama2, Llama3 (local models) + +### Available Tools + +Default tools include: + +- **calculator** - Mathematical calculations +- **web_search** - Web search functionality +- **file_reader** - File reading and analysis +- **email_sender** - Email sending capabilities +- **text_processor** - Text processing and analysis +- **image_analyzer** - Image analysis and processing + +### Router Functions + +Pre-configured router functions: + +- **default_router** - Simple pass-through routing +- **content_router** - Routes based on content analysis +- **classification_router** - Routes based on classification results +- **sentiment_router** - Routes based on sentiment analysis + +## πŸ“Š YAML Export Format + +The studio generates YAML compatible with the Flo AI framework: + +```yaml +metadata: + name: "My Workflow" + version: "1.0.0" + description: "Generated with Flo AI Studio" + tags: ["flo-ai", "studio-generated"] + +arium: + agents: + - name: "content_analyzer" + role: "Content Analyst" + job: "Analyze content and extract insights" + model: + provider: "openai" + name: "gpt-4o-mini" + settings: + temperature: 0.3 + reasoning_pattern: "COT" + + workflow: + start: "content_analyzer" + edges: + - from: "content_analyzer" + to: ["summarizer"] + end: ["summarizer"] +``` + +## πŸ”Œ Integration with Flo AI + +Use the exported YAML with the Flo AI framework: + +```python +from flo_ai.arium.builder import AriumBuilder + +# Load your exported workflow +builder = AriumBuilder.from_yaml(yaml_file="my-workflow.yaml") + +# Run the workflow +result = await builder.build_and_run(["Your input here"]) +``` + +## πŸ› οΈ Development + +### Adding New Components + +1. **Create Component** + ```typescript + // src/components/MyComponent.tsx + import React from 'react'; + + export const MyComponent: React.FC = () => { + return
My Component
; + }; + ``` + +2. **Add to Store** (if needed) + ```typescript + // src/store/designerStore.ts + interface DesignerState { + // Add new state properties + myNewFeature: boolean; + setMyNewFeature: (value: boolean) => void; + } + ``` + +### Adding New Tool Templates + +Edit the store configuration: + +```typescript +// src/store/designerStore.ts +const defaultConfig: DesignerConfig = { + availableTools: [ + // Add new tools + { name: 'my_tool', description: 'My custom tool' }, + ], + // ... +}; +``` + +### Customizing Themes + +Update CSS variables in `src/index.css`: + +```css +:root { + --primary: 222.2 47.4% 11.2%; + --primary-foreground: 210 40% 98%; + /* Add custom colors */ +} +``` + +## πŸ› Troubleshooting + +### Common Issues + +1. **Build Errors** + - Ensure all dependencies are installed: `pnpm install` + - Clear node_modules and reinstall if needed + +2. **TypeScript Errors** + - Check type definitions in `src/types/` + - Ensure proper imports and exports + +3. **React Flow Issues** + - Verify React Flow version compatibility + - Check node and edge data structures + +### Performance Optimization + +- Use React.memo for heavy components +- Implement virtual scrolling for large workflows +- Optimize store subscriptions with selectors + +## πŸš€ Deployment + +### Building for Production + +```bash +# Build the application +pnpm build + +# The dist/ folder contains the built application +``` + +### Deployment Options + +- **Static Hosting**: Deploy `dist/` to Netlify, Vercel, or GitHub Pages +- **Docker**: Create a Docker container with nginx +- **CDN**: Upload to S3 + CloudFront or similar + +### Environment Variables + +Create `.env` files for different environments: + +```bash +# .env.development +VITE_API_URL=http://localhost:3000 + +# .env.production +VITE_API_URL=https://api.myapp.com +``` + +## πŸ“ˆ Roadmap + +### Phase 1 (Current) +- βœ… Basic visual editor +- βœ… Agent configuration +- βœ… YAML export +- βœ… TypeScript support + +### Phase 2 (Planned) +- [ ] YAML import functionality +- [ ] Workflow validation +- [ ] Advanced routing configuration +- [ ] Template library + +### Phase 3 (Future) +- [ ] Real-time collaboration +- [ ] Workflow simulation +- [ ] Plugin system +- [ ] Cloud deployment + +## 🀝 Contributing + +1. Fork the repository +2. Create a feature branch: `git checkout -b feature/my-feature` +3. Make changes and add tests +4. Commit: `git commit -am 'Add my feature'` +5. Push: `git push origin feature/my-feature` +6. Create a Pull Request + +### Development Guidelines + +- Use TypeScript for all new code +- Follow the existing component structure +- Add proper error handling +- Write meaningful commit messages +- Update documentation as needed + +## πŸ“„ License + +This project is part of the Flo AI framework and follows the same licensing terms. + +## πŸ™ Acknowledgments + +- Built for the [Flo AI framework](../flo_ai/) +- Powered by React Flow for graph visualization +- UI components from Radix UI +- Icons from Lucide React + +--- + +**Happy Building! πŸš€** + +For more information about the Flo AI framework, check out the [main documentation](../flo_ai/README.md). diff --git a/studio/package.json b/studio/package.json new file mode 100644 index 00000000..c72e4a1a --- /dev/null +++ b/studio/package.json @@ -0,0 +1,54 @@ +{ + "name": "flo-ai-studio", + "version": "1.0.0", + "description": "Visual designer for Flo AI workflows", + "private": true, + "scripts": { + "dev": "vite", + "build": "tsc && vite build", + "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0", + "preview": "vite preview" + }, + "dependencies": { + "@hookform/resolvers": "^3.3.2", + "@radix-ui/react-dialog": "^1.0.5", + "@radix-ui/react-dropdown-menu": "^2.0.6", + "@radix-ui/react-form": "^0.0.3", + "@radix-ui/react-label": "^2.0.2", + "@radix-ui/react-select": "^2.0.0", + "@radix-ui/react-separator": "^1.0.3", + "@radix-ui/react-slot": "^1.0.2", + "@radix-ui/react-switch": "^1.0.3", + "@radix-ui/react-tabs": "^1.0.4", + "@radix-ui/react-tooltip": "^1.0.7", + "class-variance-authority": "^0.7.0", + "clsx": "^2.0.0", + "js-yaml": "^4.1.0", + "lucide-react": "^0.294.0", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-hook-form": "^7.48.2", + "reactflow": "^11.10.4", + "tailwind-merge": "^2.0.0", + "tailwindcss-animate": "^1.0.7", + "zod": "^3.22.4", + "zustand": "^4.4.7" + }, + "devDependencies": { + "@types/js-yaml": "^4.0.9", + "@types/node": "^20.10.4", + "@types/react": "^18.2.43", + "@types/react-dom": "^18.2.17", + "@typescript-eslint/eslint-plugin": "^6.14.0", + "@typescript-eslint/parser": "^6.14.0", + "@vitejs/plugin-react": "^4.2.1", + "autoprefixer": "^10.4.16", + "eslint": "^8.55.0", + "eslint-plugin-react-hooks": "^4.6.0", + "eslint-plugin-react-refresh": "^0.4.5", + "postcss": "^8.4.32", + "tailwindcss": "^3.3.6", + "typescript": "^5.2.2", + "vite": "^5.0.8" + } +} diff --git a/studio/postcss.config.js b/studio/postcss.config.js new file mode 100644 index 00000000..2e7af2b7 --- /dev/null +++ b/studio/postcss.config.js @@ -0,0 +1,6 @@ +export default { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +} diff --git a/studio/src/App.css b/studio/src/App.css new file mode 100644 index 00000000..3baff915 --- /dev/null +++ b/studio/src/App.css @@ -0,0 +1,157 @@ +@import 'tailwindcss/base'; +@import 'tailwindcss/components'; +@import 'tailwindcss/utilities'; + +/* React Flow Customizations */ +.react-flow__node { + font-family: inherit; +} + +.react-flow__edge { + stroke-width: 2px; +} + +.react-flow__edge.selected { + stroke: #3b82f6; + stroke-width: 3px; +} + +.react-flow__edge-path { + stroke-width: inherit; +} + +.react-flow__connection-line { + stroke: #3b82f6; + stroke-width: 3px; + stroke-dasharray: 5, 5; + animation: dash 1s linear infinite; +} + +@keyframes dash { + to { + stroke-dashoffset: -10; + } +} + +/* Edge arrows */ +.react-flow__edge .react-flow__edge-path { + stroke-width: inherit; +} + +.react-flow__edge-path { + stroke-linecap: round; +} + +.react-flow__handle { + width: 12px; + height: 12px; + border: 2px solid white; + border-radius: 50%; + transition: all 0.2s ease; +} + +.react-flow__handle:hover { + transform: scale(1.2); + box-shadow: 0 0 0 4px rgba(59, 130, 246, 0.2); +} + +.react-flow__handle-connecting { + background: #3b82f6; + transform: scale(1.3); + box-shadow: 0 0 0 6px rgba(59, 130, 246, 0.3); +} + +.react-flow__handle-valid { + background: #10b981; + transform: scale(1.2); + box-shadow: 0 0 0 4px rgba(16, 185, 129, 0.3); +} + +/* Custom Edge Label Styles */ +.edge-label { + background: white; + border: 1px solid #e5e7eb; + border-radius: 6px; + box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1); + font-size: 12px; + padding: 4px 8px; +} + +.edge-label.selected { + border-color: #3b82f6; + background: #eff6ff; +} + +/* Focus styles for better accessibility */ +.react-flow__node:focus, +.react-flow__node:focus-visible { + outline: 2px solid #3b82f6; + outline-offset: 2px; +} + +/* Animation for node hover */ +.react-flow__node { + transition: transform 0.1s ease, box-shadow 0.1s ease; +} + +.react-flow__node:hover { + transform: scale(1.02); + box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.1); +} + +/* Utility Classes */ +.line-clamp-2 { + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + overflow: hidden; +} + +.line-clamp-3 { + display: -webkit-box; + -webkit-line-clamp: 3; + -webkit-box-orient: vertical; + overflow: hidden; +} + +/* YAML Preview Drawer Styles */ +.yaml-drawer { + transition: width 0.3s ease-in-out; +} + +.yaml-drawer-content { + transition: opacity 0.3s ease-in-out; +} + +/* Floating YAML Widget */ +.yaml-widget { + transition: all 0.2s ease-in-out; + animation: float 3s ease-in-out infinite; +} + +.yaml-widget:hover { + transform: translateY(-50%) scale(1.05); +} + +@keyframes float { + 0%, 100% { transform: translateY(-50%) translateX(0); } + 50% { transform: translateY(-50%) translateX(-2px); } +} + +/* Custom Scrollbar for YAML content */ +.yaml-content::-webkit-scrollbar { + width: 8px; +} + +.yaml-content::-webkit-scrollbar-track { + background: #374151; +} + +.yaml-content::-webkit-scrollbar-thumb { + background: #6b7280; + border-radius: 4px; +} + +.yaml-content::-webkit-scrollbar-thumb:hover { + background: #9ca3af; +} diff --git a/studio/src/App.tsx b/studio/src/App.tsx new file mode 100644 index 00000000..a362ad4f --- /dev/null +++ b/studio/src/App.tsx @@ -0,0 +1,110 @@ +import React, { useState } from 'react'; +import { ReactFlowProvider } from 'reactflow'; +import { useDesignerStore } from '@/store/designerStore'; +import { Button } from '@/components/ui/button'; +import { Plus, Settings, Route, Upload, CheckCircle } from 'lucide-react'; +import FlowCanvas from '@/components/flow/FlowCanvas'; +import Sidebar from '@/components/sidebar/Sidebar'; +import AgentEditor from '@/components/editors/AgentEditor'; +import RouterEditor from '@/components/editors/RouterEditor'; +import EdgeEditor from '@/components/editors/EdgeEditor'; +import YamlPreviewDrawer from '@/components/drawer/YamlPreviewDrawer'; +import ImportDialog from '@/components/dialogs/ImportDialog'; +import ValidationPanel from '@/components/panels/ValidationPanel'; +import './App.css'; + +// Simplified Config Editor Modal +const ConfigEditorModal: React.FC<{ isOpen: boolean; onClose: () => void }> = ({ isOpen, onClose }) => { + if (!isOpen) return null; + + return ( +
+
+

Configuration

+

+ Configuration editor coming soon! For now, tools and LLMs are pre-configured. +

+ +
+
+ ); +}; + +const ToolbarComponent: React.FC<{ + showValidation: boolean; + setShowValidation: (show: boolean) => void; +}> = ({ showValidation, setShowValidation }) => { + const { openAgentEditor, openRouterEditor } = useDesignerStore(); + const [isConfigOpen, setIsConfigOpen] = useState(false); + const [isImportOpen, setIsImportOpen] = useState(false); + + return ( + <> +
+
+

Flo AI Studio

+
Visual Workflow Designer
+
+
+ + + + + + +
+
+ setIsConfigOpen(false)} /> + setIsImportOpen(false)} /> + + ); +}; + +function App() { + const [showValidation, setShowValidation] = useState(true); + + return ( +
+ +
+ +
+ + + +
+ {showValidation && } +
+ + {/* Modals */} + + + + + {/* YAML Preview Drawer */} + +
+ ); +} + +export default App; \ No newline at end of file diff --git a/studio/src/components/dialogs/ImportDialog.tsx b/studio/src/components/dialogs/ImportDialog.tsx new file mode 100644 index 00000000..320f4e24 --- /dev/null +++ b/studio/src/components/dialogs/ImportDialog.tsx @@ -0,0 +1,203 @@ +import React, { useState, useRef } from 'react'; +import { + Dialog, + DialogContent, + DialogHeader, + DialogTitle, + DialogFooter, +} from '@/components/ui/dialog'; +import { Button } from '@/components/ui/button'; +import { Textarea } from '@/components/ui/textarea'; +import { Label } from '@/components/ui/label'; +import { Upload, FileText, AlertCircle, CheckCircle } from 'lucide-react'; +import { useDesignerStore } from '@/store/designerStore'; +import { validateAriumYAML, readFileAsText } from '@/utils/yamlImport'; + +interface ImportDialogProps { + isOpen: boolean; + onClose: () => void; +} + +const ImportDialog: React.FC = ({ isOpen, onClose }) => { + const { importFromYAML } = useDesignerStore(); + const [yamlContent, setYamlContent] = useState(''); + const [validationResult, setValidationResult] = useState<{ isValid: boolean; error?: string } | null>(null); + const [isImporting, setIsImporting] = useState(false); + const [importError, setImportError] = useState(null); + const fileInputRef = useRef(null); + + const handleFileUpload = async (event: React.ChangeEvent) => { + const file = event.target.files?.[0]; + if (!file) return; + + try { + const content = await readFileAsText(file); + setYamlContent(content); + setImportError(null); + + // Validate the content + const validation = validateAriumYAML(content); + setValidationResult(validation); + } catch (error) { + setImportError(`Failed to read file: ${error instanceof Error ? error.message : 'Unknown error'}`); + } + }; + + const handleYamlChange = (content: string) => { + setYamlContent(content); + setImportError(null); + + if (content.trim()) { + const validation = validateAriumYAML(content); + setValidationResult(validation); + } else { + setValidationResult(null); + } + }; + + const handleImport = async () => { + if (!yamlContent.trim()) { + setImportError('Please provide YAML content to import'); + return; + } + + setIsImporting(true); + setImportError(null); + + try { + await importFromYAML(yamlContent); + onClose(); + resetDialog(); + } catch (error) { + setImportError(`Import failed: ${error instanceof Error ? error.message : 'Unknown error'}`); + } finally { + setIsImporting(false); + } + }; + + const resetDialog = () => { + setYamlContent(''); + setValidationResult(null); + setImportError(null); + if (fileInputRef.current) { + fileInputRef.current.value = ''; + } + }; + + const handleClose = () => { + resetDialog(); + onClose(); + }; + + return ( + + + + + + Import Workflow from YAML + + + +
+ {/* File Upload */} +
+ +
+ + or paste YAML content below +
+ +
+ + {/* YAML Content */} +
+ +