diff --git a/.gitignore b/.gitignore index 8398d67..c24c0bd 100644 --- a/.gitignore +++ b/.gitignore @@ -47,3 +47,9 @@ tmp/ temp/ auth_info_baileys/ backend/auth_info_baileys/ +whatsapp-session/ +data/autoflow.db +data/*.db +data/*.sqlite +data/*.sqlite3 +backend/autoflow.db diff --git a/README.md b/README.md index cd9d384..cd8f1cb 100644 --- a/README.md +++ b/README.md @@ -1,98 +1,164 @@ -# โšก AutoFlow AI +# โšก AutoFlow AI: The Intelligent Agentic Ecosystem -**The Intelligent AI Agent Builder for Everyone.** +[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) +[![FastAPI](https://img.shields.io/badge/Backend-FastAPI-009688?logo=fastapi&logoColor=white)](https://fastapi.tiangolo.com/) +[![React](https://img.shields.io/badge/Frontend-React-61DAFB?logo=react&logoColor=black)](https://reactjs.org/) +[![WhatsApp](https://img.shields.io/badge/Bridge-WhatsApp-25D366?logo=whatsapp&logoColor=white)](https://github.com/pedroslopez/whatsapp-web.js/) +[![LLM](https://img.shields.io/badge/AI-Gemini%20%2F%20Ollama-blueviolet)](https://ai.google.dev/) -AutoFlow AI is a powerful, low-code platform that allows you to build, visualize, and deploy AI automation agents effortlessly. It combines a state-of-the-art **React-based Visual Builder** with a robust **Node.js + Google Gemini AI Backend**. +**AutoFlow AI** is a professional, low-code platform designed to build, visualize, and deploy autonomous AI agents. By combining a futuristic visual builder with a robust multi-service architecture, AutoFlow enables anyone to create complex automation workflows powered by Google Gemini and local LLMs (via Ollama). -![AutoFlow Builder Screenshot](https://via.placeholder.com/800x450.png?text=AutoFlow+Builder+Preview) +--- -## ๐Ÿš€ Key Features +## ๐ŸŒŸ Key Features -- **๐Ÿง  Google Gemini Pro Integration**: Powered by the latest Gemini 1.5 Flash models for lightning-fast and cost-effective AI reasoning. -- **๐ŸŽจ Professional Visual Builder**: - - **Dark Mode** infinite canvas. - - **Agent-Centric Topology**: All workflows centralized around your "AutoFlow Agent". - - **Dynamic Bezier Curves**: Smooth, professional connection lines. -- **๐Ÿ”Œ 100+ Integration Tools**: Pre-built nodes for WhatsApp, Gmail, Slack, Salesforce, Stripe, and more. -- **๐Ÿ› ๏ธ Customization Mode**: Toggle between simple AI generation and advanced "Tech Mode" for manual fine-tuning. -- **๐Ÿ’ฌ Natural Language to Workflow**: Just type "Create a WhatsApp bot for order tracking" and watch the AI build it for you. +- **๐Ÿง  Hybrid AI Intelligence**: Seamlessly switch between **Google Gemini 1.5 Pro** for cloud power and **Ollama (Qwen3:8B)** for local, private inference. +- **๐ŸŽจ Professional Visual Builder**: An infinite-canvas editor built with React Flow, featuring agent-centric topology and dynamic Bezier connections. +- **๐Ÿ”Œ Multi-Channel Connectivity**: Native bridge for **WhatsApp**, with upcoming support for Slack, Gmail, and Salesforce. +- **๐Ÿ“Š Real-Time Analytics**: Built-in ROI dashboard and audit logs to track agent performance and decision-making history. +- **๐Ÿ› ๏ธ Tech-Mode Customization**: Toggle between simple AI generation and advanced manual editing for granular control over tool nodes. +- **๐Ÿ“ฆ Data-Driven Actions**: Integrated CSV/Spreadsheet support for inventory lookups, payment logging, and automated broadcasting. --- -## ๐Ÿ—๏ธ Project Structure +## ๐Ÿ—๏ธ System Architecture + +AutoFlow is built on a high-performance microservice architecture, ensuring scalability and ease of deployment. + +```mermaid +graph TB + subgraph "Frontend Layer (React + Vite)" + UI[Visual Builder UI] + State[Zustand Store] + Flow[React Flow Canvas] + end + + subgraph "Backend Orchestrator (FastAPI)" + API[REST API Handlers] + Executor[Workflow Executor Engine] + DB[(SQLite / SQLModel)] + end + + subgraph "AI & Intelligence" + Gemini[Google Gemini 1.5] + Ollama[Local Ollama Inference] + end + + subgraph "Communication Bridge" + WA_Bridge[WhatsApp Bridge Node.js] + WA_Web[WhatsApp Web Protocol] + end + + %% Connections + UI <--> API + API <--> Executor + Executor <--> DB + Executor <--> Gemini + Executor <--> Ollama + API <--> WA_Bridge + WA_Bridge <--> WA_Web +``` -This is a monorepo containing both the frontend and backend: +--- -\`\`\` -AutoFlow/ -โ”œโ”€โ”€ backend/ # Node.js Express Server + Gemini AI Logic -โ”‚ โ”œโ”€โ”€ src/ -โ”‚ โ”œโ”€โ”€ server.js -โ”‚ โ””โ”€โ”€ .env (Required) -โ”‚ -โ””โ”€โ”€ autoflow-frontend/ # React + Vite + Tailwind Builder - โ”œโ”€โ”€ src/ - โ””โ”€โ”€ package.json -\`\`\` +## ๐Ÿ”„ Agentic Workflow + +The following diagram illustrates how messages are processed through the AutoFlow ecosystem: + +```mermaid +sequenceDiagram + participant User as ๐Ÿ‘ค Customer (WhatsApp) + participant Bridge as ๐Ÿ”Œ WhatsApp Bridge + participant Backend as โš™๏ธ Backend Executor + participant AI as ๐Ÿง  LLM (Gemini/Ollama) + participant Data as ๐Ÿ“Š Inventory/CSV + + User->>Bridge: Sends Inquiry ("Is sugar in stock?") + Bridge->>Backend: Forward Webhook (JSON) + Backend->>Backend: Match Active Workflow + Backend->>Data: Lookup Resource (inventory.csv) + Data-->>Backend: Return Data (Qty: 50) + Backend->>AI: Contextual Prompt (Data + Inquiry) + AI-->>Backend: Generated Response ("Yes, we have 50 units!") + Backend->>Bridge: Send Message Command + Bridge-->>User: Delivers WhatsApp Message +``` --- -## ๐Ÿ› ๏ธ Installation & Setup +## ๐Ÿ› ๏ธ Technology Stack -### Prerequisites -- Node.js (v18 or higher) -- Google AI Studio API Key (Free Tier supported) +| Component | Technology | +| :--- | :--- | +| **Frontend** | React 18, Vite, TailwindCSS, React Flow, Zustand, Recharts | +| **Backend** | Python 3.11, FastAPI, SQLModel, Uvicorn | +| **Bridges** | Node.js, Express, WhatsApp-Web.js (Puppeteer) | +| **Database** | SQLite (Production-ready via SQLModel) | +| **AI/ML** | Google Gemini API, Ollama (Local LLM) | +| **Deployment** | Docker, Docker Compose | -### 1. Backend Setup - -\`\`\`bash -cd backend -npm install -\`\`\` +--- -Create a `.env` file in the `backend` folder: -\`\`\`env -GEMINI_API_KEY=your_google_ai_studio_key_here -PORT=3000 -\`\`\` +## ๐Ÿ“‚ Project Structure -Start the server: -\`\`\`bash -node server.js -\`\`\` -*> Server runs on http://localhost:3000* +```text +AutoFlow/ +โ”œโ”€โ”€ autoflow-frontend/ # React + Vite Visual Builder +โ”‚ โ”œโ”€โ”€ src/ # UI Components & State Management +โ”‚ โ””โ”€โ”€ public/ # Static Assets +โ”œโ”€โ”€ backend/ # FastAPI Orchestrator +โ”‚ โ”œโ”€โ”€ routers/ # API Endpoints +โ”‚ โ”œโ”€โ”€ executor.py # Workflow Traversal Engine +โ”‚ โ””โ”€โ”€ models.py # Database Schemas +โ”œโ”€โ”€ whatsapp-bridge/ # Node.js WhatsApp WebSocket Bridge +โ”‚ โ”œโ”€โ”€ server.js # Express Webhook Handler +โ”‚ โ””โ”€โ”€ session/ # WhatsApp Auth States +โ”œโ”€โ”€ data/ # Persistent SQLite DB & CSV Resources +โ””โ”€โ”€ docker-compose.yml # Multi-service Orchestration +``` -### 2. Frontend Setup +--- -Open a new terminal: -\`\`\`bash -cd autoflow-frontend -npm install -npm run dev -\`\`\` -*> Builder runs on http://localhost:5173* +## ๐Ÿš€ Quick Start ---- +### 1. Prerequisites +- Docker & Docker Compose +- Google AI Studio API Key (Optional, for Gemini support) -## ๐ŸŽฎ Usage Guide +### 2. Environment Setup +Create a `.env` file in the root directory: +```env +GEMINI_API_KEY=your_key_here +WHATSAPP_PORT=3001 +BACKEND_PORT=8000 +``` -1. Open the **Builder** in your browser. -2. **Chat with AI**: Type a prompt like *"Build a customer support agent that handles refunds via email"*. -3. **Visualize**: The AI will instantly generate a star-topology workflow centered around your **AutoFlow Agent**. -4. **Customize**: - - Click **"Customization Mode"** (top right) to open the toolbox. - - Drag & Drop extra tools (Slack, Sheets, etc.) from the library of 100+ plugins. - - Connect them to the **Agent Node's** special bottom ports. +### 3. Launch the Ecosystem +```bash +docker-compose up --build +``` +- **Builder UI**: `http://localhost:3000` +- **Backend API**: `http://localhost:8000` +- **WhatsApp Bridge**: `http://localhost:3001` --- ## ๐Ÿค Contributing -Contributions are welcome! Please feel free to submit a Pull Request. +We welcome contributions! Please fork the repository and submit a pull request for any features or bug fixes. + +1. Fork the Project +2. Create your Feature Branch (`git checkout -b feature/AmazingFeature`) +3. Commit your Changes (`git commit -m 'Add some AmazingFeature'`) +4. Push to the Branch (`git push origin feature/AmazingFeature`) +5. Open a Pull Request + +--- ## ๐Ÿ“„ License -This project is open-source and available under the [MIT License](LICENSE). +Distributed under the MIT License. See `LICENSE` for more information. ---- -*Built with โค๏ธ by [SIBAM890](https://github.com/SIBAM890)* +

+ Built with โค๏ธ by the AutoFlow Team +

diff --git a/SYSTEM_ARCHITECTURE.md b/SYSTEM_ARCHITECTURE.md new file mode 100644 index 0000000..b364045 --- /dev/null +++ b/SYSTEM_ARCHITECTURE.md @@ -0,0 +1,676 @@ +# ๐Ÿ—๏ธ AutoFlow OSS โ€” System Architecture + +> This document provides a comprehensive technical deep-dive into AutoFlow's system design, data flows, component interactions, and design decisions. + +--- + +## Table of Contents + +1. [High-Level Architecture](#1-high-level-architecture) +2. [Service Topology](#2-service-topology) +3. [Data Flow Diagrams](#3-data-flow-diagrams) +4. [Frontend Architecture](#4-frontend-architecture) +5. [Backend Architecture](#5-backend-architecture) +6. [WhatsApp Bridge Architecture](#6-whatsapp-bridge-architecture) +7. [LLM Integration Layer](#7-llm-integration-layer) +8. [Workflow Executor Engine](#8-workflow-executor-engine) +9. [Database Design](#9-database-design) +10. [Inter-Service Communication](#10-inter-service-communication) +11. [Security Considerations](#11-security-considerations) +12. [Scalability & Future Architecture](#12-scalability--future-architecture) + +--- + +## 1. High-Level Architecture + +AutoFlow is a **4-service microservice architecture** orchestrated via Docker Compose, designed for simplicity and self-hosted deployment on commodity hardware. + +``` +โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” +โ”‚ HOST MACHINE โ”‚ +โ”‚ โ”‚ +โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ +โ”‚ โ”‚ Docker Compose Network โ”‚ โ”‚ +โ”‚ โ”‚ โ”‚ โ”‚ +โ”‚ โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” REST โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” REST โ”Œโ”€โ”€โ”€โ”€โ”€โ” โ”‚ โ”‚ +โ”‚ โ”‚ โ”‚ FRONTEND โ”‚โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ†’โ”‚ BACKEND โ”‚โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ†’โ”‚OLLAMโ”‚ โ”‚ โ”‚ +โ”‚ โ”‚ โ”‚ React+Vite โ”‚ โ”‚ FastAPI โ”‚ โ”‚ A โ”‚ โ”‚ โ”‚ +โ”‚ โ”‚ โ”‚ :3000 โ”‚ โ”‚ :8000 โ”‚ โ”‚:1143โ”‚ โ”‚ โ”‚ +โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ 4 โ”‚ โ”‚ โ”‚ +โ”‚ โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ”‚ +โ”‚ โ”‚ โ”‚ REST โ”‚ โ”‚ +โ”‚ โ”‚ โ–ผ โ”‚ โ”‚ +โ”‚ โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ โ”‚ +โ”‚ โ”‚ โ”‚ WHATSAPP โ”‚ โ”‚ โ”‚ +โ”‚ โ”‚ โ”‚ BRIDGE โ”‚ โ”‚ โ”‚ +โ”‚ โ”‚ โ”‚ Node.js โ”‚ โ”‚ โ”‚ +โ”‚ โ”‚ โ”‚ :3001 โ”‚ โ”‚ โ”‚ +โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ”‚ +โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ +โ”‚ โ”‚ โ–ผ โ”‚ โ”‚ +โ”‚ โ”‚ WhatsApp Web โ”‚ โ”‚ +โ”‚ โ”‚ Protocol โ”‚ โ”‚ +โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ +โ”‚ โ”‚ +โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ +โ”‚ โ”‚ ./data/ โ”‚ โ”‚ Docker โ”‚ โ”‚ +โ”‚ โ”‚ SQLite โ”‚ โ”‚ Volumes โ”‚ โ”‚ +โ”‚ โ”‚ CSVs โ”‚ โ”‚ (ollama, โ”‚ โ”‚ +โ”‚ โ”‚ โ”‚ โ”‚ whatsapp) โ”‚ โ”‚ +โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ +โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ +``` + +### Design Principles + +| Principle | Implementation | +|-----------|---------------| +| **Self-Hosted First** | No external APIs. LLM runs locally via Ollama. | +| **Zero Configuration** | Single `docker-compose up` starts everything. | +| **Offline Capable** | Works without internet after initial setup. | +| **SMB-Friendly** | SQLite (no Postgres setup), CSV imports (no fancy integrations). | +| **Developer Experience** | Hot-reload for both frontend and backend via volume mounts. | + +--- + +## 2. Service Topology + +### 2.1 Frontend Service + +```yaml +Image: node:18-alpine +Port: 3000 +Framework: React 18 + Vite 5 +Styling: TailwindCSS 3 +State: Zustand +Flow: React Flow v11 +Charts: Recharts +``` + +**Responsibilities:** +- Render visual workflow builder with drag-and-drop nodes +- Accept natural language input and call backend `/api/workflow/generate` +- Display AI-generated explanations +- Show analytics dashboard with performance metrics +- Handle WhatsApp deployment flow with QR code display + +### 2.2 Backend Service + +```yaml +Image: python:3.11-slim +Port: 8000 +Framework: FastAPI (async) +ORM: SQLModel + SQLAlchemy +Database: SQLite +LLM: Ollama (via httpx) +``` + +**Responsibilities:** +- REST API for all CRUD operations +- Natural language โ†’ workflow JSON conversion via Ollama +- Workflow execution engine (graph traversal) +- WhatsApp webhook listener (`/api/whatsapp/incoming`) +- Audit logging for every execution +- Database seeding with templates and demo workflows + +### 2.3 WhatsApp Bridge Service + +```yaml +Image: node:18-alpine + Chromium +Port: 3001 +Framework: Express.js +Library: whatsapp-web.js (Puppeteer-based) +``` + +**Responsibilities:** +- Manage WhatsApp Web session via headless Chromium +- Generate QR codes for phone linking +- Forward incoming messages to backend webhook +- Send individual and broadcast messages +- Persist session data across container restarts + +### 2.4 Ollama Service + +```yaml +Image: ollama/ollama (official) +Port: 11434 +Model: qwen3:8b +``` + +**Responsibilities:** +- Serve the Qwen3:8B model for inference +- Auto-pull the model on first startup +- Provide `/api/chat` endpoint for structured JSON generation + +--- + +## 3. Data Flow Diagrams + +### 3.1 Workflow Generation Flow + +``` +User types: "When customer asks about stock, check inventory and reply" + โ”‚ + โ–ผ +โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” POST /api/workflow/generate +โ”‚ Frontend โ”‚โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ†’โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” +โ”‚ NLInputPanelโ”‚ โ”‚ Backend โ”‚ +โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ main.py โ”‚ + โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ + โ”‚ + POST /api/chat โ”‚ + (system + user โ”‚ + prompts) โ–ผ + โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” + โ”‚ Ollama โ”‚ + โ”‚ qwen3:8b โ”‚ + โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ + โ”‚ + JSON response โ”‚ + { nodes, edges } โ”‚ + โ–ผ + โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” + โ”‚ Backend โ”‚ + โ”‚ validates โ”‚ + โ”‚ against โ”‚ + โ”‚ WorkflowSchemaโ”‚ + โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ + โ”‚ + explanation text โ”‚ + + workflow JSON โ”‚ + โ–ผ +โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” { workflow, explanation } โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” +โ”‚ Frontend โ”‚โ†โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”‚ Backend โ”‚ +โ”‚ WorkflowGraphโ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ +โ”‚ renders nodesโ”‚ +โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ +``` + +### 3.2 Message Processing Flow (Runtime) + +``` +Customer sends WhatsApp message: "Do you have sugar?" + โ”‚ + โ–ผ +โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” POST WEBHOOK +โ”‚ WhatsApp โ”‚โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ†’โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” +โ”‚ Bridge โ”‚ โ”‚ Backend โ”‚ +โ”‚ server.js โ”‚ โ”‚ /api/whatsappโ”‚ +โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ /incoming โ”‚ + โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ + โ”‚ + For each active + workflow, check + keyword match + โ”‚ + Match found! + "sugar" โˆˆ keywords + โ”‚ + โ–ผ + โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” + โ”‚ Executor โ”‚ + โ”‚ engine โ”‚ + โ”‚ traverses โ”‚ + โ”‚ node graph โ”‚ + โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ + โ”‚ + โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” + โ”‚ โ”‚ โ”‚ + โ–ผ โ–ผ โ–ผ + Inventory Condition WhatsApp + Lookup (qty > 0?) Send Reply + (CSV search) โ”œโ”€ True โ”€โ”€โ†’ "Sugar available" + โ””โ”€ False โ”€โ”€โ†’ "Out of stock" + โ”‚ + โ–ผ + โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” POST /send + โ”‚ Backend โ”‚โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ†’โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” + โ”‚ โ”‚ โ”‚ Bridge โ”‚ + โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”˜ + โ”‚ โ”‚ + Audit Log WhatsApp + saved to reply sent + SQLite to customer +``` + +### 3.3 Deploy Agent Flow + +``` +User clicks "Deploy Agent" on frontend + โ”‚ + โ–ผ +โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” GET /status (poll every 2s) +โ”‚ DeployPage โ”‚โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ†’โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” +โ”‚ frontend โ”‚ โ”‚ WhatsApp โ”‚ +โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ Bridge โ”‚ + โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ + โ”‚ โ”‚ + โ”‚โ—€โ”€โ”€โ”€โ”€ { qr: "data:..." } โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ + โ”‚ + โ–ผ + Display QR Code + (QRCodeSVG component) + โ”‚ + User scans with phone + โ”‚ + โ–ผ +โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” GET /status โ†’ { connected: true } +โ”‚ DeployPage โ”‚โ†โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” +โ”‚ shows โœ… โ”‚ โ”‚ +โ”‚ "Agent Live"โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” +โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ Bridge โ”‚ + โ”‚ emits โ”‚ + โ”‚ "ready" โ”‚ + โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ +``` + +--- + +## 4. Frontend Architecture + +### 4.1 Component Hierarchy + +``` +App.jsx (Router) +โ”œโ”€โ”€ LandingPage.jsx +โ”œโ”€โ”€ Dashboard.jsx +โ”‚ โ””โ”€โ”€ ROIDashboard.jsx (Recharts metrics) +โ”œโ”€โ”€ Builder.jsx +โ”‚ โ”œโ”€โ”€ TopBar.jsx (Save / Activate) +โ”‚ โ”œโ”€โ”€ WorkflowGraph.jsx (React Flow canvas) +โ”‚ โ”‚ โ”œโ”€โ”€ CustomNode.jsx (base renderer) +โ”‚ โ”‚ โ”œโ”€โ”€ TriggerNode.jsx +โ”‚ โ”‚ โ”œโ”€โ”€ ActionNode.jsx +โ”‚ โ”‚ โ”œโ”€โ”€ ConditionNode.jsx +โ”‚ โ”‚ โ”œโ”€โ”€ WhatsAppNode.jsx +โ”‚ โ”‚ โ”œโ”€โ”€ InventoryNode.jsx +โ”‚ โ”‚ โ””โ”€โ”€ DelayNode.jsx +โ”‚ โ”œโ”€โ”€ NodeConfigPanel.jsx (side panel) +โ”‚ โ”œโ”€โ”€ NLInputPanel.jsx (bottom bar) +โ”‚ โ””โ”€โ”€ AIExplainerPanel.jsx +โ”œโ”€โ”€ Templates.jsx +โ”œโ”€โ”€ DeployPage.jsx (QR + Chat simulator) +โ””โ”€โ”€ NotFound.jsx +``` + +### 4.2 State Management (Zustand) + +```javascript +workflowStore = { + nodes: [], // React Flow node objects + edges: [], // React Flow edge objects + currentWorkflow: {}, // Metadata (id, name, description) + isActive: false, // Workflow activation status + explanation: null, // AI-generated explanation text + selectedNode: null, // Currently selected node for config panel + + // Actions + setNodes, setEdges, + onNodesChange, onEdgesChange, // React Flow change handlers + setCurrentWorkflow, setIsActive, + setExplanation, setSelectedNode, + updateNodeData(id, newData) // Granular node data update +} +``` + +### 4.3 Custom Node System + +Each node type is a React component that wraps React Flow's `Handle` components: + +| Node | Color | Icon | Handles | +|------|-------|------|---------| +| TriggerNode | Dark green | โšก Lightning | Output only (right) | +| ActionNode | Dark blue | โš™๏ธ Gear | Input (left) + Output (right) | +| ConditionNode | Amber | ๐Ÿ”ท Diamond | Input (left) + True (green right) + False (red right) | +| WhatsAppNode | Emerald | ๐Ÿ’ฌ WhatsApp | Input (left) + Output (right) | +| InventoryNode | Orange | ๐Ÿ“ฆ Box | Input (left) + Output (right) | +| DelayNode | Purple | โฐ Clock | Input (left) + Output (right) | + +### 4.4 Auto-Layout Algorithm + +The `getLayoutedElements()` function in `WorkflowGraph.jsx` implements a **horizontal directed graph layout**: + +1. **Depth Calculation** โ€” Uses edge relaxation (similar to Bellman-Ford) to compute the longest path depth for each node +2. **Column Grouping** โ€” Nodes at the same depth are placed in the same vertical column +3. **Position Assignment** โ€” X position = `depth ร— 350 + 100`, Y position = centered within column + +This ensures AI-generated workflows are automatically arranged left-to-right. + +--- + +## 5. Backend Architecture + +### 5.1 Module Dependency Graph + +``` +main.py (FastAPI app) +โ”œโ”€โ”€ database.py (SQLite engine + sessions) +โ”œโ”€โ”€ models.py (SQLModel ORM: Workflow, Template, AuditLog, InventorySource) +โ”œโ”€โ”€ schemas.py (Pydantic: WorkflowSchema, WorkflowGenerateRequest) +โ”œโ”€โ”€ ollama_client.py (LLM: generate_workflow, explain_workflow) +โ”œโ”€โ”€ executor.py (WorkflowExecutor class) +โ”œโ”€โ”€ seeder.py (Database seeding) +โ””โ”€โ”€ routers/ + โ”œโ”€โ”€ inventory.py (CSV upload + search) + โ”œโ”€โ”€ templates.py (CRUD + fork) + โ””โ”€โ”€ audit.py (Query logs) +``` + +### 5.2 Request Processing Pipeline + +``` +HTTP Request โ†’ CORSMiddleware โ†’ FastAPI Router โ†’ Handler โ†’ Response + โ”‚ + โ”Œโ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ” + โ”‚ SQLModel โ”‚ + โ”‚ Session โ”‚ + โ”‚ (dep inj) โ”‚ + โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ +``` + +### 5.3 Middleware Stack + +| Order | Middleware | Purpose | +|-------|-----------|---------| +| 1 | CORSMiddleware | Allow cross-origin requests from frontend (:3000) | +| 2 | FastAPI default | Request parsing, validation, response serialization | + +### 5.4 API Router Structure + +``` +/api/ +โ”œโ”€โ”€ workflow/ +โ”‚ โ”œโ”€โ”€ POST /generate โ†’ ollama_client.generate_workflow() +โ”‚ โ”œโ”€โ”€ POST /save โ†’ Workflow.create() +โ”‚ โ”œโ”€โ”€ GET /list โ†’ Workflow.select_all() +โ”‚ โ”œโ”€โ”€ GET /{id} โ†’ Workflow.get() +โ”‚ โ”œโ”€โ”€ POST /{id}/activate โ†’ Workflow.update(is_active=True) +โ”‚ โ”œโ”€โ”€ POST /{id}/deactivate โ†’ Workflow.update(is_active=False) +โ”‚ โ””โ”€โ”€ POST /{id}/execute โ†’ WorkflowExecutor.execute() +โ”œโ”€โ”€ templates/ +โ”‚ โ”œโ”€โ”€ GET / โ†’ Template.select_all() +โ”‚ โ”œโ”€โ”€ GET /{id} โ†’ Template.get() +โ”‚ โ””โ”€โ”€ POST /{id}/fork โ†’ Template โ†’ Workflow copy +โ”œโ”€โ”€ inventory/ +โ”‚ โ”œโ”€โ”€ POST /upload โ†’ Save CSV to data/ +โ”‚ โ”œโ”€โ”€ GET /list โ†’ InventorySource.select_all() +โ”‚ โ””โ”€โ”€ GET /{id}/data โ†’ Parse CSV โ†’ JSON +โ”œโ”€โ”€ audit/ +โ”‚ โ”œโ”€โ”€ GET / โ†’ AuditLog.select_all() +โ”‚ โ””โ”€โ”€ GET /{workflow_id} โ†’ AuditLog.filter(workflow_id) +โ””โ”€โ”€ whatsapp/ + โ””โ”€โ”€ POST /incoming โ†’ Webhook from Bridge โ†’ Executor +``` + +--- + +## 6. WhatsApp Bridge Architecture + +### 6.1 Session Lifecycle + +``` +Container Start + โ”‚ + โ”œโ”€โ”€ Clean stale SingletonLock files + โ”œโ”€โ”€ Initialize whatsapp-web.js Client + โ”‚ โ””โ”€โ”€ Puppeteer launches headless Chromium + โ”‚ + โ”œโ”€โ”€ Event: 'qr' โ†’ Store QR string, log to terminal + โ”œโ”€โ”€ Event: 'ready' โ†’ Set connected=true, clear QR + โ”œโ”€โ”€ Event: 'message' โ†’ Forward to backend webhook + โ””โ”€โ”€ Event: 'disconnected' โ†’ Reset state +``` + +### 6.2 Message Flow + +``` +Incoming WhatsApp Message + โ”‚ + โ–ผ +whatsapp-web.js client.on('message') + โ”‚ + โ”œโ”€โ”€ Filter: Ignore status@broadcast + โ”‚ + โ–ผ +POST http://backend:8000/api/whatsapp/incoming + { + from: "919876543210@c.us", + message: "do you have sugar?", + timestamp: 1710518400 + } +``` + +### 6.3 Session Persistence + +WhatsApp session data is stored in a Docker named volume `whatsapp_session` mapped to `/app/.wwebjs_auth`. This ensures the session survives container restarts without needing to re-scan the QR code. + +--- + +## 7. LLM Integration Layer + +### 7.1 Prompt Architecture + +``` +โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” +โ”‚ SYSTEM PROMPT โ”‚ +โ”‚ - Available node types โ”‚ +โ”‚ - Response format rules โ”‚ +โ”‚ - {{variable}} syntax requirement โ”‚ +โ”‚ - "Return ONLY valid JSON" โ”‚ +โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ + + +โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” +โ”‚ USER PROMPT โ”‚ +โ”‚ Business automation request: "{nl_input}" โ”‚ +โ”‚ Generate complete workflow JSON โ”‚ +โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ + โ”‚ + โ–ผ + Ollama /api/chat + (qwen3:8b, temp=0.2) + โ”‚ + โ–ผ +โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” +โ”‚ JSON CLEANING โ”‚ +โ”‚ - Strip ```json``` markers โ”‚ +โ”‚ - Trim whitespace โ”‚ +โ”‚ - json.loads() parse โ”‚ +โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ + โ”‚ + On failure + โ–ผ +โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” +โ”‚ STRICT RETRY PROMPT โ”‚ +โ”‚ "You failed to generate valid JSON" โ”‚ +โ”‚ "Start with { and end with }" โ”‚ +โ”‚ Temperature lowered to 0.1 โ”‚ +โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ +``` + +### 7.2 Error Handling Strategy + +| Error | Handling | Max Retries | +|-------|----------|-------------| +| Ollama connection timeout | Wait 2s, retry | 3 | +| Invalid JSON from LLM | Retry with stricter prompt | 1 (strict mode) | +| Schema validation failure | Return 500 with error | 0 | + +--- + +## 8. Workflow Executor Engine + +### 8.1 Execution Algorithm + +```python +def execute(workflow_json, trigger_data): + # 1. Build node lookup map: { node_id โ†’ node } + # 2. Build adjacency map: { source_id โ†’ [{ target, label }] } + # 3. Initialize context: { trigger: trigger_data, results: {} } + # 4. Find trigger node + # 5. DFS traversal starting from trigger: + # - For each node: + # a. Record in actions_taken + # b. Execute node-type-specific logic + # c. Store result in context.results[node_id] + # d. Follow outgoing edges: + # - Unconditional โ†’ always follow + # - Conditional โ†’ only follow matching "true"/"false" branch + # 6. Log audit entry (success or failure) +``` + +### 8.2 Supported Action Types + +| Action Type | Input | Output | Effect | +|-------------|-------|--------|--------| +| `inventory_lookup` | CSV file, search query from trigger message | `{ found, product, quantity, price }` | Searches CSV for matching product | +| `send_whatsapp` | `{ to, message }` with template vars | `{ status: "sent" }` | Sends WhatsApp via bridge | +| `send_broadcast` | Customer list from CSV + message | `{ status: "broadcast_sent" }` | Mass message via bridge | +| `load_udhaar_list` | Udhaar CSV file | `{ status: "reminders_sent" }` | Sends reminders to overdue customers | +| `load_customers` | Customers CSV file | Phone number list | Loads broadcast recipient list | +| `log_payment` | Payment data | `{ status: "logged" }` | Records payment | + +### 8.3 Template Variable Resolution + +The `_resolve_template()` method uses regex to replace `{{path.to.value}}` placeholders: + +```python +# Input: "Hello {{trigger.from}}, {{results.inventory_1.product}} has {{results.inventory_1.quantity}} units" +# Context: { trigger: { from: "John" }, results: { inventory_1: { product: "Sugar", quantity: 50 } } } +# Output: "Hello John, Sugar has 50 units" +``` + +--- + +## 9. Database Design + +### 9.1 Entity-Relationship Diagram + +``` +โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” +โ”‚ Workflow โ”‚ โ”‚ Template โ”‚ +โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค +โ”‚ id (PK) โ”‚ โ”‚ id (PK) โ”‚ +โ”‚ name โ”‚ โ”‚ name โ”‚ +โ”‚ description โ”‚ โ”‚ category โ”‚ +โ”‚ nl_input โ”‚ โ”‚ nodes (JSON) โ”‚ +โ”‚ nodes (JSON) โ”‚ โ”‚ edges (JSON) โ”‚ +โ”‚ edges (JSON) โ”‚ โ”‚ use_count โ”‚ +โ”‚ is_active โ”‚ โ”‚ created_at โ”‚ +โ”‚ created_at โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ +โ”‚ updated_at โ”‚ +โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ + โ”‚ 1:N + โ–ผ +โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” +โ”‚ AuditLog โ”‚ โ”‚ InventorySource โ”‚ +โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค +โ”‚ id (PK) โ”‚ โ”‚ id (PK) โ”‚ +โ”‚ workflow_id โ”‚โ†FK โ”‚ name โ”‚ +โ”‚ workflow_nameโ”‚ โ”‚ type โ”‚ +โ”‚ trigger_type โ”‚ โ”‚ file_path โ”‚ +โ”‚ trigger_data โ”‚ โ”‚ sheet_url โ”‚ +โ”‚ actions_takenโ”‚ โ”‚ last_synced โ”‚ +โ”‚ result โ”‚ โ”‚ created_at โ”‚ +โ”‚ error_messageโ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ +โ”‚ executed_at โ”‚ +โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ +``` + +### 9.2 Design Decisions + +| Decision | Rationale | +|----------|-----------| +| **SQLite over Postgres** | Zero-config, single file, perfect for single-machine deployment | +| **JSON columns for nodes/edges** | Avoids complex relational modeling of graph structures | +| **Separate Template table** | Templates are read-only references, workflows are user-editable forks | +| **Audit table per-execution** | Full traceability; every trigger โ†’ result is recorded | + +--- + +## 10. Inter-Service Communication + +### 10.1 Communication Matrix + +| From | To | Protocol | Endpoint | Purpose | +|------|-----|----------|----------|---------| +| Frontend | Backend | HTTP REST | `:8000/api/*` | All CRUD + AI generation | +| Backend | Ollama | HTTP REST | `:11434/api/chat` | LLM inference | +| Backend | Bridge | HTTP REST | `:3001/send`, `/broadcast` | Send WhatsApp messages | +| Bridge | Backend | HTTP POST | `:8000/api/whatsapp/incoming` | Forward incoming messages | +| Frontend | Bridge | HTTP GET | `:3001/status`, `/qr` | Check connection, get QR | + +### 10.2 Docker Networking + +All services communicate via Docker Compose's default bridge network. Service names (`backend`, `frontend`, `whatsapp-bridge`, `ollama`) resolve to container IPs automatically. + +--- + +## 11. Security Considerations + +| Area | Current State | Recommendation | +|------|--------------|----------------| +| **Authentication** | None (dev mode) | Add JWT-based auth for production | +| **CORS** | `allow_origins=["*"]` | Restrict to specific frontend origin | +| **WhatsApp Session** | Persisted in Docker volume | Encrypt session data at rest | +| **Database** | SQLite file on host | Use file permissions, consider encryption | +| **LLM Prompt Injection** | Basic input cleaning | Add input sanitization layer | +| **API Rate Limiting** | None | Add FastAPI rate limiter middleware | + +--- + +## 12. Scalability & Future Architecture + +### Current Limitations +- Single-instance SQLite (no concurrent writes) +- Single WhatsApp session per bridge +- CPU-only LLM inference (slow on large models) + +### Proposed Future Architecture + +``` + โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” + โ”‚ Nginx โ”‚ + โ”‚ Reverse โ”‚ + โ”‚ Proxy โ”‚ + โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ + โ”‚ + โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” + โ–ผ โ–ผ โ–ผ + โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” + โ”‚ Frontend โ”‚ โ”‚ Backend โ”‚ โ”‚ Backend โ”‚ + โ”‚ (CDN) โ”‚ โ”‚ Worker 1 โ”‚ โ”‚ Worker 2 โ”‚ + โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”˜ + โ”‚ โ”‚ + โ”Œโ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ” + โ”‚ PostgreSQL โ”‚ + โ”‚ + Redis Cache โ”‚ + โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ + โ”‚ + โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” + โ”‚ Message Queue โ”‚ + โ”‚ (RabbitMQ/Redis) โ”‚ + โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ + โ”‚ + โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” + โ”‚ Executor Workers โ”‚ + โ”‚ (async processing) โ”‚ + โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ +``` + +### Roadmap Items +- [ ] PostgreSQL migration for multi-user support +- [ ] Redis caching for LLM responses +- [ ] Message queue for async workflow execution +- [ ] GPU acceleration for Ollama (CUDA/ROCm) +- [ ] Multi-phone WhatsApp session management +- [ ] Scheduled trigger support (cron-based) +- [ ] Google Sheets inventory connector +- [ ] Multi-language UI (Hindi, Tamil, Telugu) +- [ ] Mobile-responsive workflow builder +- [ ] Workflow versioning and rollback + +--- + +

+ Architecture designed for simplicity today, scalability tomorrow. +

diff --git a/TEST_CHECKLIST.md b/TEST_CHECKLIST.md new file mode 100644 index 0000000..2a9f9a5 --- /dev/null +++ b/TEST_CHECKLIST.md @@ -0,0 +1,29 @@ +# AutoFlow OSS Testing Checklist + +## ๐Ÿ—๏ธ Start up +- [ ] `docker-compose up --build` runs without throwing terminal errors. +- [ ] Container `ollama` successfully pulls the `qwen3:8b` model implicitly. (Wait ~1min) +- [ ] Container `whatsapp-bridge` logs `WhatsApp Bridge running on port 3001` and generates a QR code. + +## ๐ŸŸข Endpoints & Health +- [ ] Navigate to `http://localhost:8000/docs` to see the FastAPI Swagger UI. +- [ ] Navigate to `http://localhost:3000` to see the React Frontend wrapper. +- [ ] Run `curl http://localhost:3001/status` and receive JSON `{ "connected": false }` (or true if registered). + +## ๐Ÿ› ๏ธ Feature Testing +- [ ] **AI Generation**: On Frontend Builder, type "When user asks about order, check tracking" and see valid ReactFlow nodes render in UI. +- [ ] **SQLite Seeding**: `backend/data/autoflow.db` exists. +- [ ] **Data Read**: Ensure hitting `GET /api/templates` on Swagger returns the 5 default demo templates. + +## ๐Ÿ“ฑ Demo 1: Stock Query E2E +- [ ] Go to WhatsApp and scan the QR printed by docker-compose logs for `whatsapp-bridge`. +- [ ] Turn ON the `Stock Query Auto-Reply` inside `Builder` top bar (Set to Active). +- [ ] Send message from another phone: *"Do you have any sugar left?"* +- [ ] Backends should log standard trigger matching keywords: `sugar`. +- [ ] `executor.py` runs `inventory_lookup`. It loads `inventory.csv` mapped locally. +- [ ] Automated reply is sent back: *"Sorry, sugar is out of stock right now."* (Qty is 0 in CSV). +- [ ] Message *"What about rice?"* -> Returns *"Yes! rice is available. Stock: 50 units."* +- [ ] Verify execution is logged in SQLite `audit_logs` table (Viewable via `GET /api/audit`). + +## โœ… Conclusion +If all above pass, AutoFlow OSS offline core architecture is completely functional. diff --git a/WORKFLOW.md b/WORKFLOW.md new file mode 100644 index 0000000..0f51dc1 --- /dev/null +++ b/WORKFLOW.md @@ -0,0 +1,97 @@ +# ๐Ÿ”„ AutoFlow: Message Processing Workflow + +This document visualizes the complete lifecycle of a message within the AutoFlow system, from the user's phone to the final response. + +## ๐Ÿงฉ High-Level Flow + +1. **User** sends a message via WhatsApp. +2. **Baileys** (via WebSocket) receives and decrypts the payload. +3. **Logic Engine** sanitizes the input and detects intent. +4. **Routing**: + * **Simple Intents** (Greetings, Menu) are handled locally. + * **Data Intents** (Price, Stock) query **Google Sheets**. + * **Complex Intents** are forwarded to **Gemini AI**. +5. **Response** is formatted and sent back to the user. + +--- + +## ๐Ÿ“ Detailed Workflow Diagram + +```mermaid +graph TD + %% STYLES + classDef user fill:#E5F4FD,stroke:#3B82F6,stroke-width:2px,color:#1e3a8a; + classDef whatsapp fill:#DCFCE7,stroke:#22C55E,stroke-width:2px,color:#14532d; + classDef engine fill:#F3E8FF,stroke:#A855F7,stroke-width:2px,color:#581c87; + classDef sheets fill:#FEF3C7,stroke:#F59E0B,stroke-width:2px,color:#78350f; + classDef ai fill:#FCE7F3,stroke:#EC4899,stroke-width:2px,color:#831843; + + %% EXTERNAL + User((๐Ÿ‘ค User Phone)):::user + WAServer[โ˜๏ธ WhatsApp Cloud]:::whatsapp + + %% BACKEND CONTEXT + subgraph Processing_System ["โšก AutoFlow Processing System"] + direction TB + + Baileys[๐Ÿ”Œ Baileys Socket Service]:::whatsapp + + subgraph Engine_Core ["โš™๏ธ Logic Engine Core"] + Decrypt[๐Ÿ”“ Decrypt & Parse]:::engine + PreProcess[๐Ÿงน Sanitize & Normalization]:::engine + Router{๐Ÿšฆ Intent Router}:::engine + end + + subgraph Handlers ["๐Ÿ› ๏ธ Action Handlers"] + H_Static[๐Ÿ“ Static Response]:::engine + H_Sheet[๐Ÿ“Š Sheet Service]:::sheets + H_AI[๐Ÿง  AI Service]:::ai + end + + ResponseBuilder[โœ‰๏ธ Response Formatter]:::engine + end + + %% EXTERNAL DATA + GSheets[(Google Sheets DB)]:::sheets + GeminiAPI[โœจ Gemini Pro API]:::ai + + %% CONNECTIONS & LOGIC FLOW + User -->|1. Sends Msg| WAServer + WAServer -->|2. WebSocket Push| Baileys + Baileys -->|3. Event: messages.upsert| Decrypt + Decrypt -->|4. Clean Text| PreProcess + PreProcess -->|5. Analyzed Text| Router + + %% ROUTING LOGIC + Router -->|'Hi', 'Menu'| H_Static + Router -->|'Price', 'Stock'| H_Sheet + Router -->|'Order', 'Buy'| H_Sheet + Router -->|Unmatched/Complex| H_AI + + %% HANDLER EXECUTION + H_Static -->|Get Template| ResponseBuilder + + H_Sheet -->|6a. Read/Write| GSheets + GSheets -->|6b. Data Return| H_Sheet + H_Sheet -->|Format Data| ResponseBuilder + + H_AI -->|7a. Prompt + Context| GeminiAPI + GeminiAPI -->|7b. Generated Text| H_AI + H_AI -->|Natural Response| ResponseBuilder + + %% FINAL REPLY + ResponseBuilder -->|8. Final Payload| Baileys + Baileys -->|9. Send Message| WAServer + WAServer -->|10. Delivers| User +``` + +--- + +## ๐Ÿ“Œ Key Components + +| Component | Responsibility | Tech Stack | +| :--- | :--- | :--- | +| **Baileys Socket** | Manages the persistent WebSocket connection, auth, and encryption. | `@whiskeysockets/baileys` | +| **Intent Router** | Regex-based classification for high-speed routing (0ms latency). | JavaScript `RegExp` | +| **Sheet Service** | Acts as a pseudo-database for inventory and logging. | `google-spreadsheet` | +| **AI Service** | Handles fallback and complex conversational queries. | `@google/generative-ai` | diff --git a/autoflow-frontend/.eslintrc.cjs b/autoflow-frontend/.eslintrc.cjs deleted file mode 100644 index 3e212e1..0000000 --- a/autoflow-frontend/.eslintrc.cjs +++ /dev/null @@ -1,21 +0,0 @@ -module.exports = { - root: true, - env: { browser: true, es2020: true }, - extends: [ - 'eslint:recommended', - 'plugin:react/recommended', - 'plugin:react/jsx-runtime', - 'plugin:react-hooks/recommended', - ], - ignorePatterns: ['dist', '.eslintrc.cjs'], - parserOptions: { ecmaVersion: 'latest', sourceType: 'module' }, - settings: { react: { version: '18.2' } }, - plugins: ['react-refresh'], - rules: { - 'react/jsx-no-target-blank': 'off', - 'react-refresh/only-export-components': [ - 'warn', - { allowConstantExport: true }, - ], - }, -} diff --git a/autoflow-frontend/Dockerfile b/autoflow-frontend/Dockerfile new file mode 100644 index 0000000..fad0419 --- /dev/null +++ b/autoflow-frontend/Dockerfile @@ -0,0 +1,20 @@ +# Use node for frontend build +FROM node:18-alpine + +WORKDIR /app + +# Copy package files +COPY package*.json ./ + +# Install dependencies +RUN npm install + +# Copy source code +COPY . . + +# Expose port (Vite default is 5173, but compose uses 3000) +EXPOSE 3000 + +# Start dev server (Vite) +# We use --host to allow external access +CMD ["npm", "run", "dev", "--", "--host", "0.0.0.0", "--port", "3000"] diff --git a/autoflow-frontend/README.md b/autoflow-frontend/README.md index f768e33..74872fd 100644 --- a/autoflow-frontend/README.md +++ b/autoflow-frontend/README.md @@ -1,4 +1,4 @@ -# React + Vite +# React + TypeScript + Vite This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules. @@ -6,3 +6,45 @@ Currently, two official plugins are available: - [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh - [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh + +## Expanding the ESLint configuration + +If you are developing a production application, we recommend updating the configuration to enable type aware lint rules: + +- Configure the top-level `parserOptions` property like this: + +```js +export default tseslint.config({ + languageOptions: { + // other options... + parserOptions: { + project: ['./tsconfig.node.json', './tsconfig.app.json'], + tsconfigRootDir: import.meta.dirname, + }, + }, +}) +``` + +- Replace `tseslint.configs.recommended` to `tseslint.configs.recommendedTypeChecked` or `tseslint.configs.strictTypeChecked` +- Optionally add `...tseslint.configs.stylisticTypeChecked` +- Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and update the config: + +```js +// eslint.config.js +import react from 'eslint-plugin-react' + +export default tseslint.config({ + // Set the react version + settings: { react: { version: '18.3' } }, + plugins: { + // Add the react plugin + react, + }, + rules: { + // other rules... + // Enable its recommended rules + ...react.configs.recommended.rules, + ...react.configs['jsx-runtime'].rules, + }, +}) +``` diff --git a/autoflow-frontend/build.txt b/autoflow-frontend/build.txt new file mode 100644 index 0000000..617f23c Binary files /dev/null and b/autoflow-frontend/build.txt differ diff --git a/autoflow-frontend/eslint.config.js b/autoflow-frontend/eslint.config.js new file mode 100644 index 0000000..092408a --- /dev/null +++ b/autoflow-frontend/eslint.config.js @@ -0,0 +1,28 @@ +import js from '@eslint/js' +import globals from 'globals' +import reactHooks from 'eslint-plugin-react-hooks' +import reactRefresh from 'eslint-plugin-react-refresh' +import tseslint from 'typescript-eslint' + +export default tseslint.config( + { ignores: ['dist'] }, + { + extends: [js.configs.recommended, ...tseslint.configs.recommended], + files: ['**/*.{ts,tsx}'], + languageOptions: { + ecmaVersion: 2020, + globals: globals.browser, + }, + plugins: { + 'react-hooks': reactHooks, + 'react-refresh': reactRefresh, + }, + rules: { + ...reactHooks.configs.recommended.rules, + 'react-refresh/only-export-components': [ + 'warn', + { allowConstantExport: true }, + ], + }, + }, +) diff --git a/autoflow-frontend/index.html b/autoflow-frontend/index.html index 0c589ec..f2883c8 100644 --- a/autoflow-frontend/index.html +++ b/autoflow-frontend/index.html @@ -2,12 +2,12 @@ - + - Vite + React + AutoFlow OS
- + diff --git a/autoflow-frontend/package.json b/autoflow-frontend/package.json index f4dabb0..d8ff4b1 100644 --- a/autoflow-frontend/package.json +++ b/autoflow-frontend/package.json @@ -1,37 +1,44 @@ { - "name": "autoflow-frontend", + "name": "unified-frontend", "private": true, "version": "0.0.0", "type": "module", "scripts": { "dev": "vite", - "build": "vite build", - "lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0", + "build": "tsc -b && vite build", + "lint": "eslint .", "preview": "vite preview" }, "dependencies": { - "axios": "^1.13.2", + "axios": "^1.13.6", "clsx": "^2.1.1", - "framer-motion": "^12.29.0", - "lucide-react": "^0.563.0", - "react": "^18.2.0", - "react-dom": "^18.2.0", - "react-router-dom": "^7.13.0", + "framer-motion": "^12.38.0", + "googleapis": "^171.4.0", + "lucide-react": "^0.577.0", + "qrcode.react": "^4.2.0", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "react-is": "^19.2.4", + "react-router-dom": "^7.13.1", "reactflow": "^11.11.4", - "recharts": "^3.7.0", - "tailwind-merge": "^3.4.0" + "recharts": "^3.8.0", + "tailwind-merge": "^3.5.0", + "uuid": "^13.0.0" }, "devDependencies": { - "@types/react": "^18.2.55", - "@types/react-dom": "^18.2.19", - "@vitejs/plugin-react": "^4.2.1", - "autoprefixer": "^10.4.23", - "eslint": "^8.56.0", - "eslint-plugin-react": "^7.33.2", - "eslint-plugin-react-hooks": "^4.6.0", - "eslint-plugin-react-refresh": "^0.4.5", - "postcss": "^8.5.6", - "tailwindcss": "^3.4.17", - "vite": "^5.1.0" + "@eslint/js": "^9.13.0", + "@types/react": "^18.3.12", + "@types/react-dom": "^18.3.1", + "@vitejs/plugin-react": "^4.3.3", + "autoprefixer": "^10.4.27", + "eslint": "^9.13.0", + "eslint-plugin-react-hooks": "^5.0.0", + "eslint-plugin-react-refresh": "^0.4.14", + "globals": "^15.11.0", + "postcss": "^8.5.8", + "tailwindcss": "^3.4.19", + "typescript": "~5.6.2", + "typescript-eslint": "^8.11.0", + "vite": "^5.4.10" } } diff --git a/autoflow-frontend/postcss.config.js b/autoflow-frontend/postcss.config.js index d41ad63..2e7af2b 100644 --- a/autoflow-frontend/postcss.config.js +++ b/autoflow-frontend/postcss.config.js @@ -1,6 +1,6 @@ export default { - plugins: { - tailwindcss: {}, - autoprefixer: {}, - }, + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, } diff --git a/autoflow-frontend/public/favicon.png b/autoflow-frontend/public/favicon.png new file mode 100644 index 0000000..793308d Binary files /dev/null and b/autoflow-frontend/public/favicon.png differ diff --git a/autoflow-frontend/src/App.jsx b/autoflow-frontend/src/App.jsx deleted file mode 100644 index 4dce77c..0000000 --- a/autoflow-frontend/src/App.jsx +++ /dev/null @@ -1,20 +0,0 @@ -import { BrowserRouter as Router, Routes, Route } from 'react-router-dom'; -import Dashboard from './pages/Dashboard'; -import Builder from './pages/Builder'; -import NotFound from './pages/NotFound'; - -function App() { - return ( - -
- - } /> - } /> - } /> - -
-
- ); -} - -export default App; diff --git a/autoflow-frontend/src/App.tsx b/autoflow-frontend/src/App.tsx new file mode 100644 index 0000000..2c07433 --- /dev/null +++ b/autoflow-frontend/src/App.tsx @@ -0,0 +1,24 @@ +import { BrowserRouter, Routes, Route } from "react-router-dom"; +import Landing from "./pages/Landing"; +import PlatformLayout from "./components/layout/PlatformLayout"; +import Dashboard from "./pages/Dashboard"; +import Studio from "./pages/Studio"; +import DeployPage from "./pages/DeployPage"; + +export default function App() { + return ( + + + {/* Public Landing Page */} + } /> + + {/* Private Platform View */} + }> + } /> + } /> + } /> + + + + ); +} diff --git a/autoflow-frontend/src/api/client.js b/autoflow-frontend/src/api/client.js new file mode 100644 index 0000000..ac022a0 --- /dev/null +++ b/autoflow-frontend/src/api/client.js @@ -0,0 +1,50 @@ +import axios from 'axios'; + +const api = axios.create({ + baseURL: 'http://localhost:8000/api', // FastAPI Backend + headers: { + 'Content-Type': 'application/json', + }, +}); + +export const workflowAPI = { + generate: (nl_input) => api.post('/workflow/generate', { nl_input }), + explain: (workflow_json) => api.post('/workflow/explain', workflow_json), + save: (id, workflow) => api.post('/workflow/save', { id, ...workflow }), + list: () => api.get('/workflow/list'), + get: (id) => api.get(`/workflow/${id}`), + update: (id, workflow) => api.put(`/workflow/${id}`, workflow), + delete: (id) => api.delete(`/workflow/${id}`), + activate: (id) => api.post(`/workflow/${id}/activate`), + deactivate: (id) => api.post(`/workflow/${id}/deactivate`), + execute: (id, trigger_data) => api.post(`/workflow/${id}/execute`, { trigger_data }), +}; + +export const templatesAPI = { + list: () => api.get('/templates'), + get: (id) => api.get(`/templates/${id}`), + fork: (id) => api.post(`/templates/${id}/fork`), +}; + +export const auditAPI = { + list: () => api.get('/audit'), + getByWorkflow: (workflow_id) => api.get(`/audit/${workflow_id}`), +}; + +export const inventoryAPI = { + upload: (file) => { + const formData = new FormData(); + formData.append('file', file); + return api.post('/inventory/upload', formData, { + headers: { 'Content-Type': 'multipart/form-data' }, + }); + }, + list: () => api.get('/inventory/list'), + getData: (id) => api.get(`/inventory/${id}/data`), +}; + +export const whatsappAPI = { + status: () => api.get('/whatsapp/status'), + qr: () => api.get('/whatsapp/qr'), + send: (to, message) => api.post('/whatsapp/send', { to, message }), +}; diff --git a/autoflow-frontend/src/components/builder/AIExplanation.jsx b/autoflow-frontend/src/components/builder/AIExplanation.jsx index fb90e06..f1539e9 100644 --- a/autoflow-frontend/src/components/builder/AIExplanation.jsx +++ b/autoflow-frontend/src/components/builder/AIExplanation.jsx @@ -18,8 +18,27 @@ export const AIExplanation = ({ workflow }) => { setIsLoading(true); try { const data = await workflowApi.explain(workflow); - setExplanation(data.explanation || "No explanation available."); + // Handle structured response + let explanationText = "No explanation available."; + + if (typeof data === 'string') { + explanationText = data; + } else if (typeof data === 'object') { + if (data.summary) { + const stepsText = data.steps?.map(s => `โ€ข ${s.title}: ${s.description}`).join('\n') || ''; + explanationText = `${data.summary}\n\n${stepsText}`; + } else if (data.explanation) { + explanationText = typeof data.explanation === 'string' + ? data.explanation + : JSON.stringify(data.explanation); + } else { + explanationText = JSON.stringify(data, null, 2); + } + } + + setExplanation(explanationText); } catch (error) { + console.error(error); setExplanation("Failed to generate explanation."); } finally { setIsLoading(false); @@ -57,12 +76,12 @@ export const AIExplanation = ({ workflow }) => { ) : (
- {explanation} + {typeof explanation === 'object' ? JSON.stringify(explanation) : explanation}
)}
- Auto-generated by AutoFlow Brain ๐Ÿง  + AI Generated Logic
)} diff --git a/autoflow-frontend/src/components/builder/ChatInput.jsx b/autoflow-frontend/src/components/builder/ChatInput.jsx index 3883dba..6a39184 100644 --- a/autoflow-frontend/src/components/builder/ChatInput.jsx +++ b/autoflow-frontend/src/components/builder/ChatInput.jsx @@ -7,16 +7,16 @@ export const ChatInput = ({ onSend, disabled }) => { const [text, setText] = useState(''); const { isListening, transcript, startListening, stopListening, error } = useVoiceInput(); - // Effect to update text when voice transcript changes + // Track previous listening state to detect stop + const [wasListening, setWasListening] = useState(false); + useEffect(() => { - if (transcript) { - setText(prev => { - // If appending, add space. For now, let's just replace or append smart. - // Simple approach: if text exists, append. - return prev ? `${prev} ${transcript}` : transcript; - }); + if (wasListening && !isListening && transcript) { + // Commit transcript when tracking stops + setText(prev => (prev ? `${prev} ${transcript}` : transcript)); } - }, [transcript]); + setWasListening(isListening); + }, [isListening, transcript, wasListening]); const handleSubmit = (e) => { e.preventDefault(); @@ -54,11 +54,11 @@ export const ChatInput = ({ onSend, disabled }) => { setText(e.target.value)} placeholder={isListening ? "Listening..." : "Describe your workflow..."} className="flex-1 bg-transparent border-none focus:ring-0 text-gray-900 placeholder-gray-400" - disabled={disabled} + disabled={disabled || isListening} // Disable typing while listening to avoid conflicts /> + + )} + + {/* Input bar */} +
+
+ {/* File attach */} + + + + {/* Textarea */} +