From eb5f643c13ccd99a3dfc160b9a666a40a7bb760a Mon Sep 17 00:00:00 2001 From: vizsatiz Date: Sat, 13 Dec 2025 22:44:59 +0530 Subject: [PATCH 1/9] Fixing up the parent readme --- README.md | 170 +++++++++++------------------------------- flo_ai/pyproject.toml | 2 +- flo_ai/setup.py | 2 +- flo_ai/uv.lock | 2 +- 4 files changed, 48 insertions(+), 128 deletions(-) diff --git a/README.md b/README.md index 4c4f5781..7386334d 100644 --- a/README.md +++ b/README.md @@ -42,33 +42,40 @@
-# ๐Ÿš€ Wavefront AI Middleware +# What is Wavefront ? -Wavefront AI is an open-source middleware platform designed to seamlessly build AI-driven agents, workflows, and automations across enterprise environments. It acts as a connective layer that bridges frontend applications and AI automations with backend databases, data-warehouses, data-lakes, third-party services, ensuring secure access, observability, and compatibility with modern AI +Wavefront AI is an open-source middleware platform designed to: +- Seamlessly connect to any API, database or file storage system +- Connect to any LLM or SLMs +- Build AI-driven agents, workflows, and automations across enterprise by connecting to multiple data sources, knowledge bases, and services +- Provide authentication, authorization, observability, monitoring & evaluation for to all agents & workflows + +# What people build with Wavefront ? +- To build AI agents & workflows to audit, underwrite, supervise contact center, and automate business processes +- To build knowledge bases & RAG ready applications for internal enterprise use +- To build voice & conversational agents collections and sales usecases +- To build AI workflows to connect multiple data sources, knowledge bases, and services -**Status**: Beta Release -**Beta release**: Dec 2025 -**Wavefront License**: GNU AFFERO GENERAL PUBLIC LICENSE 3.0 -**FloAI License**: MIT LICENSE -**Contributing**: We welcome early feedback! See [CONTRIBUTING.md](CONTRIBUTING.md). -**Community**: Join our discord at https://discord.gg/BPXsNwfuRU

Rootflo

---- -## โœจ Key Capabilities +|**Release Status** | Beta Release| +|-----------|------------| +|**Wavefront License** | GNU AFFERO GENERAL PUBLIC LICENSE 3.0 | +|**FloAI License** | MIT LICENSE | +|**Contributing** | We welcome early feedback! See [CONTRIBUTING.md](CONTRIBUTING.md). | +|**Community** | Join our discord at https://discord.gg/BPXsNwfuRU or post a message at https://github.com/rootflo/wavefront/discussions| -- **๐ŸŽฏ Modular AI Application Integration** - Deploy diverse AI agents for auditing, underwriting, contact center supervision, and business process automation without rebuilding infrastructure. +## โœจ Key Capabilities - **๐Ÿ”Œ Unified API Layer** - Standardized APIs for developing, deploying, and managing AI workflows across multiple use cases and frameworks. + Standardized APIs for developing, deploying, and managing AI workflows & agents across multiple use cases and frameworks. - **๐Ÿ” Enterprise-Grade Authentication & Authorization** - Native integrations with Google Auth, LDAP, Auth0, Okta, and Microsoft AD/Entra for seamless SSO and access controls. + Native integrations with Google Auth and Microsoft AD/Entra for seamless SSO and access controls for client applications - **๐ŸŒ Comprehensive Data Connectivity** Ingest data from OLAP/OLTP systems (BigQuery, Redshift), HDFS, cloud storage (S3, GCS), databases (PostgreSQL, MongoDB), and enterprise APIs (Salesforce, SAP). @@ -91,128 +98,37 @@ Wavefront AI is an open-source middleware platform designed to seamlessly build - **๐Ÿง  Knowledge Bases & RAG Ready** Native support for Retrieval-Augmented Generation with MCP connectors and external knowledge bases. ---- +- **๐ŸŽฏ Modular AI Application Integration (Coming Soon)** +Deploy diverse AI agents for auditing, underwriting, contact center supervision, and business process automation without rebuilding infrastructure. -## ๐Ÿ—๏ธ Architecture Overview +# Quick Start -

- Rootflo -

+**Option 1**: [Contact us](mailto:vishnu@rootflo.ai) for a demo and we help you build immediately. -### Layer Descriptions +**Option 2**: Self-host for maximum control and customization. Please find the self-hosting instructions in the [Wavefront Documentation](https://github.com/rootflo/wavefront/tree/develop/wavefront). -| Layer | Purpose | Components | -|-------|---------|------------| -| **Frontend Applications** | User-facing AI interfaces | Supervisors, Audit Agents, Underwriters, Copilots | -| **API Layer** | Standardized communication | Frontend SDK, REST/GraphQL APIs | -| **Authentication** | Identity verification & SSO | Google Auth, LDAP, Auth0, Okta, Microsoft AD | -| **Authorization (Agents)** | Agent-level access policies | Role definitions, permission mapping | -| **AI Workflows** | Intelligent automation | Agentic flows, Voice agents, LLM integrations, RAG | -| **Data Processing** | ETL and API management | Pipelines, transformations, HTTP endpoints | -| **Authorization (Data)** | Data source access control | Fine-grained permissions, audit logging | -| **Data Sources** | Enterprise data systems/Services | Databases, APIs, Cloud storage, Data warehouses, Servics like Salesforce, SAP etc. | - -## Platform Components +# Platform Components As part of the project, we are building the following components -- [FloAI](https://github.com/rootflo/flo-ai/tree/develop/flo_ai) library for Agent Building & A2A Orchestration -- **Wavefront Core** Middleware Service, which connects multiple frontend applications with complex backend ai pipelines, provides authentication, authorization, observability, monitoring & evaluation -- **Wavefront Control Panel** Unified frontend for configuring agents, workflows, AI models, Guardrails developer-friendly, RBAC etc. -- **Wavefront cli** for configuring through cli (Yet to Build), for full developer-friendly control - -## ๐Ÿ›ฃ๏ธ Current Support & Roadmap - -### Data Adapters - -| Adapter | Status | Notes | -|---------|--------|-------| -| BigQuery | โœ… Available | Full read/write support | -| Redshift | โœ… Available | Production-ready | -| PostgreSQL | ๐Ÿ”„ In Progress | Optimized for large datasets | -| MySQL | ๐Ÿ“‹ Roadmap | Compatible with MySQL 5.7+ | - -### API Adapters - -| Adapter | Status | Notes | -|---------|--------|-------| -| Custom API Configuration | ๐Ÿ”„ In Progress | Flexible HTTP endpoint support | -| Salesforce | ๐Ÿ”„ In Progress | Native API integration | - -### LLM Connectors - -| Model/Service | Status | Notes | -|---------------|--------|-------| -| OpenAI | โœ… Available | GPT-3.5, GPT-4 support | -| Anthropic | โœ… Available | Claude models supported | -| vLLM (Open-Source) | โœ… Available | Self-hosted inference | -| Ollama | โœ… Available | Local model deployment | -| GroqAI | ๐Ÿ”„ In Progress | Fast inference support | -| Vertex AI | โœ… Available | Google Cloud integration | -| Bedrock | ๐Ÿ”„ In Progress | AWS integration coming soon | - -### Authentication Providers - -| Provider | Status | Notes | -|----------|--------|-------| -| Google Auth | โœ… Available | OAuth 2.0 support | -| Microsoft AD/Entra | โœ… Available | Enterprise SSO ready | -| Okta | ๐Ÿ“‹ Roadmap | Q1 2026 | -| SAML 2.0 | ๐Ÿ“‹ Roadmap | Q1 2026 | +| Component | Description | +|---------|-------------| +| **flo-ai** | [FloAI](https://github.com/rootflo/flo-ai/tree/develop/flo_ai) library for Agent Building & A2A Orchestration. Detailed documentation is available [here](https://wavefront.rootflo.ai/flo-ai). | +| **wavefront-server** | Core Middleware Service, which connects everything and orchestrates the flows. Detailed documentation is available [here](https://github.com/rootflo/wavefront/tree/develop/wavefront). | +| **wavefront-client** | Unified frontend for configuring agents, workflows, AI models, Guardrails developer-friendly, RBAC etc. Details [here](https://github.com/rootflo/wavefront/tree/develop/wavefront). | +| **wavefront-cli** | for configuring through cli, for full developer-friendly control [Coming Soon] -### Audit & Observability - -| Feature | Status | Notes | -|---------|--------|-------| -| Application Metrics | โœ… Available | Prometheus-compatible | -| Application Logs | โœ… Available | Structured logging | -| AI Token Tracking | โœ… Available | Token tracking per agent | -| Open Telemetry | โœ… Available | Full OTel support | -| AI Audit Logging | ๐Ÿ”„ In Progress | Detailed decision trails (Q4 2025) | -| AI Guardrails | ๐Ÿ“‹ Roadmap | Policy enforcement (Q1 2026) | - -### Frontend SDK - -| Feature | Status | Notes | -|---------|--------|-------| -| Component Library | โœ… Available | React components ready | -| AI-Based No-Code Builder | ๐Ÿ“‹ Roadmap | Visual agent creation (Q1 2026) | -| Low Code AI Agent Builder | โœ… Available | YAML-based builder available | - -### Release Timeline +# Release Timeline | Quarter | Milestone | Features | |---------|-----------|----------| | **Nov 2025** | Public README.md | Publish readme and take in community feedback | -| **Dec 2025** | Open-source community edition | Community edition release with working MVP | -| **Q1 2026** | Enterprise Edition | Advanced RBAC, More Data source Integrations| -| **Q1 2026** | Rootflo Wavefront Cloud | One-click deployable Wavefront Cloud +| **Dec 2025** | Open-source Beta Release | Beta with basic features | +| **Q1 2026** | GA Release | Advanced RBAC, More Data source Integrations| +| **Q1 2026** | Rootflo Wavefront Cloud | Multi-tenant Cloud offering | See [ROADMAP.md](ROADMAP.md) for detailed feature plans and contribution opportunities. ---- - -## ๐Ÿค Contributing - -We welcome contributions from the community! Whether it's bug reports, feature requests, or code contributions: - -1. Fork the repository -2. Create a feature branch (`git checkout -b feature/amazing-feature`) -3. Commit your changes (`git commit -m 'Add amazing feature'`) -4. Push to the branch (`git push origin feature/amazing-feature`) -5. Open a Pull Request - -See [CONTRIBUTING.md](CONTRIBUTING.md) for detailed guidelines. - ---- - - -## ๐Ÿ™ Acknowledgments - -Wavefront AI was built with inspiration from leading open-source projects in the AI infrastructure space. Special thanks to our early adopters and community contributors. - ---- - ## โญ Show Your Support If you find Wavefront AI useful, please consider: @@ -224,10 +140,14 @@ If you find Wavefront AI useful, please consider: --- -**Ready to transform your enterprise AI infrastructure?** +# Next Steps -Get in touch for production-grade support and SLA-driven deployments that ensure uptime, stability, and performance at scale. +## Next Steps -๐Ÿ“ง sales@rootflo.ai +- [Join our Discord](https://discord.gg/BPXsNwfuRU) +- [Read our docs](https://wavefront.rootflo.ai/) +- [Talk to us](mailto:sales@rootflo.ai) -**Join our discord at https://discord.gg/BPXsNwfuRU** \ No newline at end of file +Text us!
+[![Twitter Vishnu](https://img.shields.io/twitter/follow/viz_satiz?style=flat-square&logo=X)](https://x.com/viz_satiz) +[![Twitter Nitin](https://img.shields.io/twitter/follow/ntinkster?style=flat-square&logo=X)](https://x.com/ntinkster) diff --git a/flo_ai/pyproject.toml b/flo_ai/pyproject.toml index db609896..7bafc5a1 100644 --- a/flo_ai/pyproject.toml +++ b/flo_ai/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "flo_ai" -version = "1.1.0-rc5" +version = "1.1.0-rc6" description = "A easy way to create structured AI agents" authors = [{ name = "rootflo", email = "*@rootflo.ai" }] requires-python = ">=3.10,<4.0" diff --git a/flo_ai/setup.py b/flo_ai/setup.py index 91d27742..021f320e 100644 --- a/flo_ai/setup.py +++ b/flo_ai/setup.py @@ -5,7 +5,7 @@ setuptools.setup( name='flo-ai', - version='1.0.7-rc5', + version='1.0.7-rc6', author='Rootflo', description='Create composable AI agents', long_description=long_description, diff --git a/flo_ai/uv.lock b/flo_ai/uv.lock index f3dc7384..076ab59e 100644 --- a/flo_ai/uv.lock +++ b/flo_ai/uv.lock @@ -897,7 +897,7 @@ wheels = [ [[package]] name = "flo-ai" -version = "1.1.0rc5" +version = "1.1.0rc6" source = { editable = "." } dependencies = [ { name = "aiohttp" }, From 2e107ddc8ea8344b84c0d0ba4143795c60c13036 Mon Sep 17 00:00:00 2001 From: vizsatiz Date: Sat, 13 Dec 2025 22:51:32 +0530 Subject: [PATCH 2/9] Cleaning up docs --- README.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 7386334d..1ca0670a 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,6 @@

-


GitHub @@ -30,6 +29,8 @@ Website โ€ข Documentation + โ€ข + Discord

@@ -42,15 +43,15 @@


-# What is Wavefront ? +## What is Wavefront ? Wavefront AI is an open-source middleware platform designed to: - Seamlessly connect to any API, database or file storage system - Connect to any LLM or SLMs - Build AI-driven agents, workflows, and automations across enterprise by connecting to multiple data sources, knowledge bases, and services -- Provide authentication, authorization, observability, monitoring & evaluation for to all agents & workflows +- Provide authentication, authorization, observability, monitoring & evaluation for all agents & workflows -# What people build with Wavefront ? +## What people build with Wavefront ? - To build AI agents & workflows to audit, underwrite, supervise contact center, and automate business processes - To build knowledge bases & RAG ready applications for internal enterprise use - To build voice & conversational agents collections and sales usecases @@ -61,13 +62,11 @@ Wavefront AI is an open-source middleware platform designed to: Rootflo

- -|**Release Status** | Beta Release| +| Project Information | Details | |-----------|------------| +|**Release Status** | Beta Release| |**Wavefront License** | GNU AFFERO GENERAL PUBLIC LICENSE 3.0 | |**FloAI License** | MIT LICENSE | -|**Contributing** | We welcome early feedback! See [CONTRIBUTING.md](CONTRIBUTING.md). | -|**Community** | Join our discord at https://discord.gg/BPXsNwfuRU or post a message at https://github.com/rootflo/wavefront/discussions| ## โœจ Key Capabilities @@ -146,6 +145,7 @@ If you find Wavefront AI useful, please consider: - [Join our Discord](https://discord.gg/BPXsNwfuRU) - [Read our docs](https://wavefront.rootflo.ai/) +- [Submit an issue](https://github.com/rootflo/wavefront/issues/new/choose) - [Talk to us](mailto:sales@rootflo.ai) Text us!
From 8dcceb7464fcbc4e9c9039fc7b356b12b67ee27f Mon Sep 17 00:00:00 2001 From: vizsatiz Date: Sat, 13 Dec 2025 22:53:19 +0530 Subject: [PATCH 3/9] Fix for header size --- README.md | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 1ca0670a..6ed8d384 100644 --- a/README.md +++ b/README.md @@ -100,13 +100,13 @@ Wavefront AI is an open-source middleware platform designed to: - **๐ŸŽฏ Modular AI Application Integration (Coming Soon)** Deploy diverse AI agents for auditing, underwriting, contact center supervision, and business process automation without rebuilding infrastructure. -# Quick Start +## Quick Start **Option 1**: [Contact us](mailto:vishnu@rootflo.ai) for a demo and we help you build immediately. **Option 2**: Self-host for maximum control and customization. Please find the self-hosting instructions in the [Wavefront Documentation](https://github.com/rootflo/wavefront/tree/develop/wavefront). -# Platform Components +## Platform Components As part of the project, we are building the following components @@ -117,7 +117,7 @@ As part of the project, we are building the following components | **wavefront-client** | Unified frontend for configuring agents, workflows, AI models, Guardrails developer-friendly, RBAC etc. Details [here](https://github.com/rootflo/wavefront/tree/develop/wavefront). | | **wavefront-cli** | for configuring through cli, for full developer-friendly control [Coming Soon] -# Release Timeline +## Release Timeline | Quarter | Milestone | Features | |---------|-----------|----------| @@ -139,8 +139,6 @@ If you find Wavefront AI useful, please consider: --- -# Next Steps - ## Next Steps - [Join our Discord](https://discord.gg/BPXsNwfuRU) From 3f3f328f3e24a509976f52ddfe7ea69f7f71ab5f Mon Sep 17 00:00:00 2001 From: vizsatiz Date: Sun, 14 Dec 2025 10:43:10 +0530 Subject: [PATCH 4/9] fix small doc issues --- README.md | 8 ++++---- flo_ai/pyproject.toml | 2 +- flo_ai/setup.py | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 6ed8d384..cbf43320 100644 --- a/README.md +++ b/README.md @@ -47,14 +47,14 @@ Wavefront AI is an open-source middleware platform designed to: - Seamlessly connect to any API, database or file storage system -- Connect to any LLM or SLMs +- Connect to any LLM or SLM - Build AI-driven agents, workflows, and automations across enterprise by connecting to multiple data sources, knowledge bases, and services - Provide authentication, authorization, observability, monitoring & evaluation for all agents & workflows ## What people build with Wavefront ? - To build AI agents & workflows to audit, underwrite, supervise contact center, and automate business processes - To build knowledge bases & RAG ready applications for internal enterprise use -- To build voice & conversational agents collections and sales usecases +- To build voice & conversational agents collections and sales use-cases - To build AI workflows to connect multiple data sources, knowledge bases, and services @@ -89,7 +89,7 @@ Wavefront AI is an open-source middleware platform designed to: Built-in telemetry with Grafana and Prometheus support. Track agent performance, audit trails, and guardrail enforcement in real-time. - **๐Ÿค– No Code Agent & Workflow Builder** - Built-in capabilities to build and customer AI agents, and AI Workflows, connecting Data Sources, Knowledge Bases, in minutes + Built-in capabilities to build and customize AI agents, and AI Workflows, connecting Data Sources, Knowledge Bases, in minutes - **๐Ÿ”Š Voice & Conversational Agents** Integrated Voice-to-Voice Bots, ASR models, and agentic flows for contact center and conversational use cases. @@ -115,7 +115,7 @@ As part of the project, we are building the following components | **flo-ai** | [FloAI](https://github.com/rootflo/flo-ai/tree/develop/flo_ai) library for Agent Building & A2A Orchestration. Detailed documentation is available [here](https://wavefront.rootflo.ai/flo-ai). | | **wavefront-server** | Core Middleware Service, which connects everything and orchestrates the flows. Detailed documentation is available [here](https://github.com/rootflo/wavefront/tree/develop/wavefront). | | **wavefront-client** | Unified frontend for configuring agents, workflows, AI models, Guardrails developer-friendly, RBAC etc. Details [here](https://github.com/rootflo/wavefront/tree/develop/wavefront). | -| **wavefront-cli** | for configuring through cli, for full developer-friendly control [Coming Soon] +| **wavefront-cli** | for configuring through cli, for full developer-friendly control (**Coming Soon**) | ## Release Timeline diff --git a/flo_ai/pyproject.toml b/flo_ai/pyproject.toml index 7bafc5a1..8f6daf94 100644 --- a/flo_ai/pyproject.toml +++ b/flo_ai/pyproject.toml @@ -2,7 +2,7 @@ name = "flo_ai" version = "1.1.0-rc6" description = "A easy way to create structured AI agents" -authors = [{ name = "rootflo", email = "*@rootflo.ai" }] +authors = [{ name = "rootflo", email = "engineering.tools@rootflo.ai" }] requires-python = ">=3.10,<4.0" readme = "README.md" license = "MIT" diff --git a/flo_ai/setup.py b/flo_ai/setup.py index 021f320e..6e2e613e 100644 --- a/flo_ai/setup.py +++ b/flo_ai/setup.py @@ -5,7 +5,7 @@ setuptools.setup( name='flo-ai', - version='1.0.7-rc6', + version='1.1.0-rc1', author='Rootflo', description='Create composable AI agents', long_description=long_description, From e85956bb887cb83a43c425ab854181e5e10d4cf8 Mon Sep 17 00:00:00 2001 From: vizsatiz Date: Sun, 14 Dec 2025 15:49:41 +0530 Subject: [PATCH 5/9] Doc update for Main and Wavefront README --- README.md | 10 +- images/wavefront-middleware.png | Bin 0 -> 24796 bytes images/wavefront-service-mesh.png | Bin 0 -> 65896 bytes wavefront/README.md | 92 +++++++- wavefront/docker_setup.md | 361 +++++++++++++++++------------- 5 files changed, 303 insertions(+), 160 deletions(-) create mode 100644 images/wavefront-middleware.png create mode 100644 images/wavefront-service-mesh.png diff --git a/README.md b/README.md index cbf43320..a0a8e78e 100644 --- a/README.md +++ b/README.md @@ -102,10 +102,11 @@ Deploy diverse AI agents for auditing, underwriting, contact center supervision, ## Quick Start -**Option 1**: [Contact us](mailto:vishnu@rootflo.ai) for a demo and we help you build immediately. +**Option 1**: [Schedule a demo](https://calendly.com/meetings-rootflo/30min) and we help you build immediately. **Option 2**: Self-host for maximum control and customization. Please find the self-hosting instructions in the [Wavefront Documentation](https://github.com/rootflo/wavefront/tree/develop/wavefront). + ## Platform Components As part of the project, we are building the following components @@ -128,6 +129,11 @@ As part of the project, we are building the following components See [ROADMAP.md](ROADMAP.md) for detailed feature plans and contribution opportunities. +> [!WARNING] +> +> - This project is under active development and APIs may change without notice. Please checkout the [platform docs](https://wavefront.rootflo.ai) for the latest information. +> - The platform is not in the GA state, and there are unimplemented feature. Checkout [ROADMAP.md](../ROADMAP.md) for the list of features, and whats missing. + ## โญ Show Your Support If you find Wavefront AI useful, please consider: @@ -144,7 +150,7 @@ If you find Wavefront AI useful, please consider: - [Join our Discord](https://discord.gg/BPXsNwfuRU) - [Read our docs](https://wavefront.rootflo.ai/) - [Submit an issue](https://github.com/rootflo/wavefront/issues/new/choose) -- [Talk to us](mailto:sales@rootflo.ai) +- [Talk to us](https://calendly.com/meetings-rootflo/30min) Text us!
[![Twitter Vishnu](https://img.shields.io/twitter/follow/viz_satiz?style=flat-square&logo=X)](https://x.com/viz_satiz) diff --git a/images/wavefront-middleware.png b/images/wavefront-middleware.png new file mode 100644 index 0000000000000000000000000000000000000000..eb60cac512552c336047cd0f5cccb3b0a84cebb8 GIT binary patch literal 24796 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 GfBrueSpc&D literal 0 HcmV?d00001 diff --git a/images/wavefront-service-mesh.png b/images/wavefront-service-mesh.png new file mode 100644 index 0000000000000000000000000000000000000000..1ba952e9e33b83111a63d41d631525c0b5760dfc GIT binary patch literal 65896 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 pd@?4 z<6N0;1hRJ|bhbG#iRxG{T~xS}xpbTA8ouC=zAc2Lo<1AW-FmoG^qA5_v@1GpTfbY6 zol1Cz-zW+mk9Cqzte&5>#HHbv%&KS=Z)}Zp^}hdlG>u5Cr@9AKdwnF z%dOa5>1y=Yjq1%OEYUF0i)4&gJ3A(c{%uXQTkQ1tjR;b|;|ky+OBf6{siV+4sxH9T zzo=2d+_^2OX?ba!^f38F*n|lrjUV(?K&KNWHcsR=K})^AL1}r8*YZUlh(bvRV<4f` zt7Wi_S6>jiL3=%ZY{&xVndC#S>Ol3~_(ZDfThJLyIiQX zOAa$u)>|frz|!#3WGOoF#?Jz?(#8S{&L`^f->_y6w^mzn`l8tN(wnDAo_FrnPn_MVZ2avUKuopvl}vSEp>eTZ0% z{1$ob{VhPuHoW*z|R=KBR(kP$A#K1zC@kPLcxQ- z+c}-*9rFyO0^0ySP!4aKM75b!ewLZMmT#LaOO9f&uWr{(iEB7VmvxivNFukd7=P7Z z=QwPrtb|8e#SZxSZ46*ah9m-TcuQqC9-Zepmi{Fxq}8jO`;)pTa{4DC^_&b_ccYsv z`e#}p2Sbj)FTPB};+4jm+)fNwO*<=CKq}R?GR;JUL1)m%Vz?TeYNevD9&G+jz4FuK z_*sI|GXk9eJkPo3EOn893Xr2os*rAyvH~Jc+0s)k z4Y#-EIp%weSx+9d2Hd5#@$q8K;`J?|O4Q@gv<0yThxL4*fPR8!HOGIOcCB6hk3_vv zVGHxOwonU~afu4uQw{zoArP77e}w8m%$y;u&}&}0yoUWxHAfzFS<9<47WrIzuwijX zVsv_349k)(f}MsPkNf}!zD}8S&4?P~U`=&jCGQyzmRI#`&&yjy>6`^Waym+%Tq?C6 zR%NyK zNRD)aNY~Je)SyxV!bmrRbaxFYAUVKD#}E=jcMlBkZN0ARe(vYb?|qNs{eNcfwO8%6 z*E-MN86{sVS{9A#TE4~UKhdiLIMc!P2D#l~r|f%X7Fs_H1owMuVrp~*ew)(+aDJg{ zL{-c^6O6d_g8yYs|JZ$~4~P%i)E1U5PO+?92P4R)i#^QwEU3wo+P7ls`DAygEh&Gs zi@N$_MVqnig~U(tt8>;09v$s_tNc%-#%FpsnD!g8wfZNbPm+Uh{yhIbOREKJn5O z(PIeC;(+DU(hcDL>KL8aS59F8`#b>>!j5D(z-S8d+s=5KxtE;I)47R+D^y~}yS9{9 zKv+$ePDMGA`?0f{@LL+!@2&=eVly2)g?(z=pZu>bn*zjuosatL?y0}5nbsvNf$v@j zdr(IX^<428Uc>1jX+IKc(4(<9%cheJh0LK-&J7zWXEr^OVJ2I=G5EoaTeMsusy~d~ zo79u13fusZ0!U9YpN9-7T_$Ya3~ZxL~>Ku1~4 zE_b@lIBRzuZNv4E-b!4@;%Ml8*?^3PGxBqo) zzcBOU0_MCq*4@2}Q_Oj*5j;ilLveM%1>pb*Y9iivXJ@^7z8X{Ol}33h7_(th)MvpP z`7(h^M#S7*Ve-}9*`O0hL()?tZ-|L6fjuUZG%xmPPbYQ#XMBIdYyZlUH}IHSd4}rw z+(Xmmn}!wM+U88`ChmzDPVegUTsqEoE$qrS{t`Q{S93*k2lh`K!p>?A{pETfdQR6- zjJZo*V`%$VY60{|UD^GWigY9)9zfLJ?`CcX&ab?m^WT@;_Uqr+5-QP8DZ!P}c*3>z zN;zl7UmEI@cCp_FhtX}02+?cVwl=u*vMHB=5D>%dxBoVEcFR9cX5D0{`RaR z{^MES=B@X4_*Gum?Rm0_91p&p*N11cqUX(E4Lw~gp0WqxcIXzdwN&PLUn*)sM-hdD zn(%|Fj>l2RUt*$(_1Q5W)dTXH|JzNc;`-czY(=4YW${SUl2!TlycX`V8&b8yIwao-(#esry-7U}|_Qwg+t7C|UX? z45yi_+S3I1{;=MlV=pc%^?KpXwHxp9kbmTGV{RRZf3Oq$r0tt?yrMKBGfM{1p?yqWxTbDl+11>e4(KXtjzi)$*cU@HbLnP z(GFa6w>3JZbc6jH;rI$FIC0ASZYN|Z>-E#Y*|(vpoZ#h^nQ^4KWliJiQ$!JF>)nIe z{>l)@#FxWWJHE@wyhDthGl!FbqL=HMr`8zCFTcsVz`;P346kc{(_b!lF(tA? z7u3oI)`jNK)+uWQx!rI3Cm{9>oS+_Jw=S&q2(0lnwg*aCrD7q>e5N4yqe6NkACk@2 zyx>mNdJ>owBg4TBmMWJ4cMQ_t?%gOmHAdUj%YkOrMBOE;M`zCLVv>u=4VLgk$O>0- zWe>9pBCHtAW;aXAIL4}kHU77aojj0d(>ql$kYNne`v;Y=^MzJz?3b(qnQY?sCg7#^ zyWJ2GAPb3cvW38?kBP5r*|pL90uVQS1vDbuu#_nT7pTM-1F~nG3~&h~ym@_>o)V2% zkKeM}_0iC89hb>97q(Kqi14L;7%wmqPPo_XDB4y$6&;YLe&4BEc#JRhvQ=HR5KPy_ zWiieIpfPQ^R>`~kwy-|~EbR3Y=MseI$Aj*QF`JMis~~i5Um8rWdx0bR`{j$N z0gfv?Bq6~oe~SPY+(1GYP^SZMuyl z6cU!-HWPct614N@xbok?Z^0fR>_7%^*P)I32h8I;C+YXYa7HV$WshZTp1!W`oxfk> zE_+yYS=vn(sRW@lzGAsIRce@|cz-Iv)BW!t!9wz>SWwebw8K162%0qpG|$iUA1`|j z)qlL~^Q?mHVJj@U6#|n#7OJGrSO)_E{o*fo+|EsW(2|fCfybUe^S@`u8>S8Em#-N+QW|`D|2OpPaza;>Z zbGH82<2gXk^JUc8wSkN+_J3Yrc1Ev|_9I?_3Yic^cG@npyRJ1l66yJbn}4DeJDj14 zV_%7(+kVP`vhp&}VE|aqMNP8cGOcsh!ugvcKKERjns<&WB+z(vtSF0y@}^hmvVhbS ze#TJ!dkK?mUKY>hR~!{{qVJOsTt{+8AGW+M{>D7KHvByKen*~wn?F-RmM*V&8xOc4 zzcInuuzV1u<5NK!0}(|Dm#i&EiCmcu1^`32DU;)={UdOt{or%4@@QRIHp+34p+@nkmaV@ZC=#kzl#d*K ziF~0Ww((fneX_Z{d;SQw^eG**=lW1j4~DK5_AeRBYYl5y<)g)~)X{XO_WRhDH-`HH zq063(t3fiMXt6q-?Q?U97s8#_Es1qFz*RxA1LNaS;_L|-?l(v7WLkH-y>&2Av!GGQiy6@&QOeuNk+yH%w&CL5UL zA!>>L*xfrMj5DkJl`|Xn{79a+Msm(gV)_9VfVV`gS6TSB4W3MLK?GxK1|~U(g7H$B zm$;V+9Q=uQoOc&&U--oYIqysrYy4$}b9{*>3gG1L2I<#Md>`R(>zn*FT9xnNVKMCZ z0zF~1Fr9tvk$?t;dmr6`u1Cxm#S^^aZMB{q^9OtLMlPeO!Tv)x7J{jIfc?vv*e(Z2T&A*n9Q&IM1DYaA`W4uNy%|n_2mAp{-xexAaQou%(y( zV4;TZx9Ds7f&Kmj4ms?R0w^`ye+!G8v+-x(t_4kn6CCKZ)-21d%ih3wrOxV-3mjLZ zRL%-s=$Nd1w+6uG8*2iHgZg+}AiJO-7?GUmUYgge`SD;KVx`yJ-G5-Ylfrh7PEPiv zkB6(v98o92K^h(-n4`{It+o$0bjZFh-jdlf)({R#m_%^}IM@}lL?+p?byaO z2&~;TBH_fMtUEEIlhK2-iCa9jYWV10iXCO#;n3P^T>GW%-wdwF6S7~Woj*$%UcmdB z&4qpp%H(@7q+3PN{x(?(WfJz6LJVGq+xL9Fffv5i=U%l$CMmektE>OZ z`yTDwO(w(&1YQ1D7$qQ&_`gNB|38qd&(kktkCr+0r*czz3IdvmSPF66(;0~nqnmC6 zUe&!r5^o*H0O6(sL>G?FIDmKzr0l)&IkoO7&1U0_6jrcEk??6!ql{9D&yKiQ-lvNk zjdJ(=pwaR^(024o3vKe0*rq^&MC|b*8x~Ds-RP_@z@lZt?Q@V6!In645$sKY9~ZNt zsGi?9>V`2M&FH5G^=y~C4`e6EV^yLeIhKjv)z-E>sTxvsW+ zoA(`Yt@XRoccJ2n@Uo!3!6{b$nJ8rMFx^`x@Iq#EfoA&bmltr`QWW#Xp)vYOdoRsK zUyAe4-NR@2uB@Po#v{2?!^@b#YEr#2L7(}A>ECMQpq=Z0xVeqLZtJ|ZdwwC%9SAn1 zgEFG0$UHj{I758AdY8}fW^wlP=WQAgCm1ugj`tk@hpC#v4IXeFTJq1^B{X%>W+sTi z8s6f~UVW@;W~bCEO`JRu8*dts;4?7-1nA1k);`fYrw8thS+p6=!(YWQU$ydT2IQ8E zGSo-%@{d+%YhMSw>}v&0Z~k!NuQ2&~u_kWkiwVIvqqH%Pj)wetU&LIf4BZ)`%G~9-);`QCaXjSa zLyi0EgKnj*2$q_S_E-K?)=Et8#EsKFm*8aNK%{s9-Hlk$F76FEo>nvC_k&E6j+(HP z{QCJHy>t)DGpvebd({m%+|z9}m=a@S72y1|EW<_722MpSIBa8#_;+CN+BV-0T^^S#H8xY0QP`0gpTkCnKK= zQ524z4>zA%EXLB-trXRBuJk)4qNX@3@Vd{uitxO$gqv==8Ls`(D(1_%T{!ADqbbkR z6}XmDxZb)n%k7tNQJFqH`iu|OIH5QG`n`>f)o8dJV6FP4oosP6-MVe)>vX85z z_#+C5-#dR*Dt#cQX+Z1{Z#(?<0&GgPJ2)!QRlLvL}$)el;e`NIW9BrfOHtv)i}Xc(Ocp z6prkkSwOLCjJsZx>KU%qj!z?N7hvqHpSr}~rV+V>$cz$cV$Ym>>Xv_g5?moFW93&d z*2EHzFEy4i<1F`I!<~e!^>NvH!6l7!on{4!Yuk#+_e#K}T?>(>Azp^cdUZYH1tXPF znSj0Zhy^NUb*OJvDPi>$sm65t%22b*t!ucc>DHer0cjAM=Lr|NQ0$q^6lV7{+BD7R z9fhv@LQtpdOSgbjkA+{jIIgYSWPia}qq?kIR8f4o%axeb)NVe$op^y=leN&G-PJ$# z^$A657?Bgx!_snfngjtx((EMS%4Puf<2+oe&S7R#R+Z(z#0^HBGFEnW!ty=fD2Q(*paohTo&`L_&VDP*X@Ol=`2l& zuaj?3-UA+|pUn?HYINNGpKc}Vr&*Mt)g^H|3eA(k0Uny?bcR`J6Z^MSt!&Z4rRd? zqQ&E1b2vs_zGbS~dTRhSIg{dE`5RPNP580_dzVYPyNx^P0-4n#^dT7EZ!M3mr2*WuRmSb3>75)voDv^S0ZSu%e4B zm+tKC)ZArOMluOU7KS7C6^uC6$YJJ1Lkq;~)U|$kN zH_s?FRR=JTqCXUS28E!sJWj|r8I@y652N?j1yB& zy{Ii8RvEnMe8oBc?$c8xbMU7X8b(e@7@Tnwr_P_O+++{3T@1| z|IFksa$ue(!&|Tm4+OqF1teC$;UDzYx;A`7MsA{aEU$3) zB0CH*%S$_cC?nrO=3@v2zk=;V6FSe9)2SvA^9tav{wvb$hepEv40a_z73R|LH~O1g#je(PyvQ>PISy7$&Eu_Y-foANJ`m0Xy#rS_4Fej zyUJ zq579jQ}x4uJn7l0L#7i$mR6M3q=FLn{iwCWU3zI1v#q|>&_{;C3VRQdd(dQzyfwEn zTmy{|_#hL6*m&SftprueV=*{wYh-;KwwQ{4BcvfpZLC+@_&7H4muQp2{O~7I zmLeXSMlKlBXeR$&mf{=(>~T&6QxOvuz!K;ke4`yyFfpa?M%XZ7`}Wj2U;?+Z0%sWx z%bKhGxP}nza5a3qck$b{&S)BU0d+78iuZ{ieO!WQ>ep&f!X* zBfJJ+-ZLp%qYATBj8_&^e%AFeK+N9UXpz8E-)48Z2m3OG?OSHJR?iN$MQ>)D?v`tS zYI*1mH^5Y1k&(bMiz`qao16LN6kS}wXXIz%^qB!dk~ZoVjO*G(--TKap{&&Mt&vPN*3bHE?@ov7l0E%%qS)nFp$U&lo%@sOtvWo0$$Kg@ zY?{Ud`4)A95@H44kMa6{08}q2@nJMp(~}3HO}Lq9w@#-wvf2%fj*nfk%G{z0leE

-hVux&3`X-cyn9MZi=WjHShP+q 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 Iw|eov06HG96951J literal 0 HcmV?d00001 diff --git a/wavefront/README.md b/wavefront/README.md index 22476f36..58e14c03 100644 --- a/wavefront/README.md +++ b/wavefront/README.md @@ -1 +1,91 @@ -# To be updated \ No newline at end of file +## Wavefront AI Platform + +The platform consist of following components, which create a microservice mesh to provide scalable, secure, and reliable AI services. We have not used a fully microservice architecture as it is not necessary for our use case. + +The platform consists of following components: + +| Service | Port | Description | Release Status | +|---------|------|-------------|----------------| +| **floware** | 8001 | Core AI middleware service. This service connects wavefront to multiple backends, databases, AI models and more. This is the core control center of the platform. | Beta | +| **floconsole** | 8002 | Management console service, this module is multi-app control centre for configuriong multiple apps on the wavefront middleware. | Beta | +| **inference_app** | 8003 | Inference App service. A simple service for running pytorch models. We right now support all models which works on pytorch version 0.16.0. | Experimental | +| **call_processing** | 8004 | Voice call processing service (Pipecat) | Beta | + +#### Middleware High Level Architecture: + +

+ Wavefront +

+ +#### Console High Level Architecture: + +

+ Wavefront +

+ +## Prerequisites + +The project has its backend services written in python and frontend in reactjs. It has the following dependencies: + +- Python >=3.11 +- Node.js >=22.12 +- uv >=0.7.15 +- pnpm >=10.13.1 + +The project is ready for production use only in Google Cloud Console and Amazon Web Services. +In the current state of the project, it requires following cloud services to run locally (We are working on removing this dependencies for local runs): + +- Google Cloud Storage or Amazon S3 +- Google Cloud Pub/Sub or AWS SQS + +## Quick Start + +> [!WARNING] +> +> - This project is under active development and APIs may change without notice. Please checkout the [platform docs](https://wavefront.rootflo.ai) for the latest information. +> - The platform is not in the GA state, and there are unimplemented feature. Checkout [ROADMAP.md](../ROADMAP.md) for the list of features, and whats missing. + +### Docker Setup + +You can use docker compose to setup the platform locally. Details on setting up using docker can be found in [DOCKER_SETUP.md](DOCKER_SETUP.md) + +### Dev/Local Setup + +**Step 1**: You can use the local setup to setup the platform locally. Start by cloning the repo and running the following commands: + +```bash +chmod +x install-dep-local.sh +./install-dep-local.sh +``` + +This will install all the dependencies required to run the platform locally. + +**Step 2**: Wavefront uses vscode (or its clone like cursor or anti-gravity) as the primary editor. We have provided a vscode workspace file to make it easier to work with the project. Open the workspace file in vscode and it will open the project in vscode. + +Once you open the vscode you will be seeing three workspaces: + +- `wavefront-root-dir`: This is the root directory of the project. With all the root-dir files +- `wavefront`: This is the backend & frontend service of the platform. +- `flo_ai`: The A2A orchestration library developed by RootFlo AI. + +**Step 3**: Go to `wavefront` workspace and open the server directory. In the directory go to `apps`, where you can find all the services mentioned in the table above. Open each of the setup `.env` files with environment variables as mentioned in the [DOCKER_SETUP.md](DOCKER_SETUP.md). + +**Step 4**: Run all the backend services services. Check the floware health at http://localhost:8001/floware/v1/health. + +**Step 5**: Go to `wavefront` workspace and open the client directory. Add the neccessary environment variables in the `.env` file. Run the following commands to start the frontend services: + +```bash +pnpm install +pnpm run dev +``` + +Now open http://localhost:5173 in your browser to see the frontend & login with the credentials set in environment variables. + +**Step 6**: Go to the console, add your first app by clicking on the `Add App` button. Use the details of the floware service you started on Step 4 + +## Next Steps + +Connect your datasources, and create your first agent & workflow or go ahead an try out the voice bot feature. + +- Checkout the platform docs here [https://wavefront.rootflo.ai](https://wavefront.rootflo.ai/). +- Incase you face any issues, dont hesitate to reach out to schedule a call with us [here](https://calendly.com/meetings-rootflo/30min) \ No newline at end of file diff --git a/wavefront/docker_setup.md b/wavefront/docker_setup.md index a8aab192..ee12e92d 100644 --- a/wavefront/docker_setup.md +++ b/wavefront/docker_setup.md @@ -2,6 +2,11 @@ This guide explains how to configure and run the RootFlo AI platform using Docker Compose. +> [!WARNING] +> +> - This project is under active development and APIs may change without notice. Please checkout the [platform docs](https://wavefront.rootflo.ai) for the latest information. +> - The platform is not in the GA state, and there are unimplemented feature. Checkout [ROADMAP.md](../ROADMAP.md) for the list of features, and whats missing. + ## Quick Start 1. **Generate JWT Keys** @@ -74,14 +79,14 @@ Some services require credential files (JSON files for GCP, OAuth, etc.). Follow | Service | Port | Description | |---------|------|-------------| -| **floware** | 8001 | Core AI middleware platform | -| **floconsole** | 8002 | Management console | -| **inference_app** | 8003 | Inference App | -| **call_processing** | 8004 | Voice call processing (Pipecat) | -| **postgres-floware** | 5432 | Floware database (pgvector) | +| **floware** | 8001 | Core AI middleware service | +| **floconsole** | 8002 | Management console service | +| **inference_app** | 8003 | Inference App service (Alpha) | +| **call_processing** | 8004 | Voice call processing service (Pipecat) | +| **postgres-floware** | 5432 | Floware database (with pgvector extension) | | **postgres-console** | 5433 | Console database | | **redis-floware** | 6379 | Floware cache | -| **redis-call-processing** | 6380 | Call processing cache | +| **redis-call-processing** | 6380 | Call processing service cache | ## Environment Variables Reference @@ -90,172 +95,216 @@ Some services require credential files (JSON files for GCP, OAuth, etc.). Follow #### Required Variables **Database**: -- `DB_USERNAME`: PostgreSQL username (default: `postgres`) -- `DB_PASSWORD`: PostgreSQL password (default: `postgres`) -- `DB_HOST`: Database host (default: `postgres-floware`) -- `DB_PORT`: Database port (default: `5432`) -- `DB_NAME`: Database name (default: `floware`) + +| Variable | Description | +|----------|-------------| +| `DB_USERNAME` | PostgreSQL username (default: `postgres`) | +| `DB_PASSWORD` | PostgreSQL password (default: `postgres`) | +| `DB_HOST` | Database host (default: `postgres-floware`) | +| `DB_PORT` | Database port (default: `5432`) | +| `DB_NAME` | Database name (default: `floware`) | **Redis**: -- `REDIS_PROTOCOL`: Protocol (default: `redis`) -- `REDIS_HOST`: Redis host (default: `redis-floware`) -- `REDIS_PORT`: Redis port (default: `6379`) + +| Variable | Description | +|----------|-------------| +| `REDIS_PROTOCOL` | Protocol (default: `redis`) | +| `REDIS_HOST` | Redis host (default: `redis-floware`) | +| `REDIS_PORT` | Redis port (default: `6379`) | **Application Settings**: -- `APP_ENV`: Application environment (e.g., `dev`, `staging`, `production`) -- `APP_NAME`: Application name (default: `floware`) -- `ALLOWED_ORIGINS`: Comma-separated list of allowed CORS origins -- `PASSTHROUGH_SECRET`: Secret for service-to-service authentication (**IMPORTANT**: Must be the same in floware, floconsole, and call_processing services) + +| Variable | Description | +|----------|-------------| +| `APP_ENV` | Application environment (e.g., `dev`, `staging`, `production`) | +| `APP_NAME` | Application name (default: `floware`) | +| `ALLOWED_ORIGINS` | Comma-separated list of allowed CORS origins | +| `PASSTHROUGH_SECRET` | Secret for service-to-service authentication (when `APP_ENV` is local, dev, staging)| + +**IMPORTANT**: `PASSTHROUGH_SECRET` must be the same in floware, floconsole, and call_processing services. This is used only in non-production environments (`APP_NAME` being local, dev, staging), for production, you should configure service mesh or API gateway to handle service-to-service authentication. **JWT Authentication**: -- `PRIVATE_KEY`: Base64-encoded RSA private key (generate using `./scripts/generate-keys.sh`) -- `PUBLIC_KEY`: Base64-encoded RSA public key (generate using `./scripts/generate-keys.sh`) -- `TOKEN_EXPIRY`: Token expiration in seconds (default: `3600`) -- `TEMPORARY_TOKEN_EXPIRY`: Temporary token expiration (default: `600`) -- `ENABLE_CLOUD_KMS`: Enable cloud KMS for key management (`true` or `false`) -- `CONSOLE_TOKEN_PREFIX`: Token prefix for console tokens (default: `fc_`) -- `FLOWARE_JWT_ISSUER`: JWT issuer URL for floware -- `FLOWARE_JWT_AUDIENCE`: JWT audience URL for floware -- `FLOWARE_JWT_VALIDATION_ISSUER`: Comma-separated list of valid issuers + +| Variable | Description | +|----------|-------------| +| `PRIVATE_KEY` | Base64-encoded RSA private key (generate using `./scripts/generate-keys.sh`) | +| `PUBLIC_KEY` | Base64-encoded RSA public key (generate using `./scripts/generate-keys.sh`) | +| `TOKEN_EXPIRY` | Token expiration in seconds (default: `3600`) | +| `TEMPORARY_TOKEN_EXPIRY` | Temporary token expiration (default: `600`) | +| `ENABLE_CLOUD_KMS` | Enable cloud KMS for key management (`true` or `false`) | +| `CONSOLE_TOKEN_PREFIX` | Token prefix for console tokens (default: `fc_`) | +| `FLOWARE_JWT_ISSUER` | JWT issuer URL for floware | +| `FLOWARE_JWT_AUDIENCE` | JWT audience URL for floware | +| `FLOWARE_JWT_VALIDATION_ISSUER` | Comma-separated list of valid issuers | **Initial User configuration**: -- `EMAIL`: User Email -- `PASSWORD`: User Password -- `FIRST_NAME`: User first name -- `LAST_NAME`: User last name + +| Variable | Description | +|----------|-------------| +| `EMAIL` | User Email | +| `PASSWORD` | User Password | +| `FIRST_NAME` | User first name | +| `LAST_NAME` | User last name | **Cloud Provider** (Choose one: `aws` or `gcp`): -- `CLOUD_PROVIDER`: Set to `aws` or `gcp` + +| Variable | Description | +|----------|-------------| +| `CLOUD_PROVIDER` | Set to `aws` or `gcp` | #### AWS Configuration (if CLOUD_PROVIDER=aws) -```yaml -AWS_ACCESS_KEY_ID: Your AWS access key -AWS_SECRET_ACCESS_KEY: Your AWS secret key -AWS_REGION: AWS region (e.g., ap-south-1) -AWS_KMS_ARN: KMS key ARN for encryption -AWS_QUEUE_URL: SQS queue URL - -# S3 Buckets -TRANSCRIPT_BUCKET_NAME: Bucket for audio transcripts -AUDIO_BUCKET_NAME: Bucket for audio files -AWS_GOLD_ASSET_BUCKET_NAME: Bucket for gold/insights assets -MODEL_STORAGE_BUCKET: Bucket for ML models -AGENT_YAML_BUCKET: Bucket for agent YAML configs -VOICE_AGENT_BUCKET: Bucket for voice agent configs -IMAGE_SEARCH_REFERENCE_IMAGES_BUCKET: Bucket for reference images -APPLICATION_BUCKET: Bucket for API service applications -``` +| Variable | Description | +|----------|-------------| +| `AWS_ACCESS_KEY_ID` | Your AWS access key | +| `AWS_SECRET_ACCESS_KEY` | Your AWS secret key | +| `AWS_REGION` | AWS region (e.g., ap-south-1) | +| `AWS_KMS_ARN` | KMS key ARN for encryption | +| `AWS_QUEUE_URL` | SQS queue URL | +| `TRANSCRIPT_BUCKET_NAME` | Bucket for audio transcripts | +| `AUDIO_BUCKET_NAME` | Bucket for audio files | +| `AWS_GOLD_ASSET_BUCKET_NAME` | Bucket for gold/insights assets | +| `MODEL_STORAGE_BUCKET` | Bucket for ML models | +| `AGENT_YAML_BUCKET` | Bucket for agent YAML configs | +| `VOICE_AGENT_BUCKET` | Bucket for voice agent configs | +| `IMAGE_SEARCH_REFERENCE_IMAGES_BUCKET` | Bucket for reference images | +| `APPLICATION_BUCKET` | Bucket for API service applications | #### GCP Configuration (if CLOUD_PROVIDER=gcp) -```yaml -GCP_PROJECT_ID: Your GCP project ID -GCP_LOCATION: GCP region (e.g., asia-south1) -GOOGLE_APPLICATION_CREDENTIALS: Path to service account JSON file -GCP_KMS_KEY_RING: KMS key ring name -GCP_KMS_CRYPTO_KEY: KMS crypto key name -GCP_KMS_CRYPTO_KEY_VERSION: KMS key version (usually 1) - -# GCS Buckets -GCP_ASSET_STORAGE_BUCKET: Bucket for assets -GCP_GOLD_TOPIC_ID: Gold/insights Pub/Sub topic -GCP_EMAIL_TOPIC_ID: Email processing Pub/Sub topic -WORKFLOW_WORKER_TOPIC: Workflow Pub/Sub topic -``` - -#### LLM/AI Configuration - -**OpenAI**: -- `OPENAI_API_KEY`: Your OpenAI API key -- `OPENAI_MODEL_NAME`: Model to use (default: `gpt-4o`) - -**Other APIs**: -- `GOOGLE_API_KEY`: Google API key +| Variable | Description | +|----------|-------------| +| `GCP_PROJECT_ID` | Your GCP project ID | +| `GCP_LOCATION` | GCP region (e.g., asia-south1) | +| `GOOGLE_APPLICATION_CREDENTIALS` | Path to service account JSON file | +| `GCP_KMS_KEY_RING` | KMS key ring name | +| `GCP_KMS_CRYPTO_KEY` | KMS crypto key name | +| `GCP_KMS_CRYPTO_KEY_VERSION` | KMS key version (usually 1) | +| `GCP_ASSET_STORAGE_BUCKET` | Bucket for assets | +| `WORKFLOW_WORKER_TOPIC` | Workflow Pub/Sub topic | +| `APPLICATION_BUCKET` | Bucket for API service applications | #### Optional Configurations **External Services**: -- `INFERENCE_SERVICE_URL`: URL for the inference service (default: `http://inference_app:8003`) -- `EMBEDDING_SERVICE_URL`: URL for the embedding service -- `CALL_PROCESSING_BASE_URL`: URL for call processing service (default: `http://call_processing:8004`) -- `HERMES_URL`: URL for Hermes service -**OAuth Integration**: -- Azure: `AZURE_CLIENT_ID`, `AZURE_TENANT_ID`, `AZURE_CLIENT_SECRET`, `AZURE_SCOPES`, `AZURE_REDIRECT_URI` +| Variable | Description | +|----------|-------------| +| `INFERENCE_SERVICE_URL` | URL for the inference service (default: `http://inference_app:8003`) | +| `EMBEDDING_SERVICE_URL` | URL for the embedding service | +| `CALL_PROCESSING_BASE_URL` | URL for call processing service (default: `http://call_processing:8004`) | +| `HERMES_URL` | URL for Hermes service | + + **Email Integration**: -- `EMAIL_PROVIDER`: `gmail` or `outlook` -- Gmail: `GMAIL_SERVICE_ACCOUNT_FILE`, `GMAIL_SENDER_EMAILID`, `GMAIL_DELEGATE_USER` -- Outlook: `OUTLOOK_CLIENT_ID`, `OUTLOOK_CLIENT_SECRET`, `OUTLOOK_TENANT_ID`, `OUTLOOK_SENDER_EMAILID` - -**Analytics**: -- Superset: `SUPERSET_URL`, `SUPERSET_USERNAME`, `SUPERSET_PASSWORD` -- BigQuery: `BQ_PROJECT_ID`, `BQ_DATASET_ID` -- Redshift: `REDSHIFT_DB`, `REDSHIFT_USERNAME`, `REDSHIFT_PASSWORD`, `REDSHIFT_HOST`, `REDSHIFT_PORT` - -**Security Settings**: -- `MAX_FAILED_ATTEMPTS`: Maximum failed login attempts before lockout (default: `3`) -- `LOCKOUT_DURATION_HOURS`: Hours to lock account after max failed attempts (default: `24`) -- `INACTIVE_DAYS_THRESHOLD`: Days of inactivity before account is disabled (default: `60`) - -**Feature Flags** (set to `true` or `false`): -- `AZURE_FLAG`: Enable Azure integration -- `AZURE_OPENAI_FLAG`: Enable Azure OpenAI -- `CELERY_FLAG`: Enable Celery for async tasks -- `EMAIL_SYNC_FLAG`: Enable email synchronization -- `GOOGLE_FLAG`: Enable Google integration -- `INACTIVE_ACCOUNT_DISABLE_FLAG`: Enable automatic account disabling for inactive users -- `SAML_FLAG`: Enable SAML authentication -- `SLACK_FLAG`: Enable Slack integration -- `SUPERSET_FLAG`: Enable Superset analytics -- `VECTOR_DB_FLAG`: Enable vector database features + +| Variable | Description | +|----------|-------------| +| `EMAIL_PROVIDER` | `gmail` or `outlook` | +| `GMAIL_SERVICE_ACCOUNT_FILE` | Gmail service account JSON file path | +| `GMAIL_SENDER_EMAILID` | Gmail sender email address | +| `GMAIL_DELEGATE_USER` | Gmail delegate user | +| `OUTLOOK_CLIENT_ID` | Outlook OAuth client ID | +| `OUTLOOK_CLIENT_SECRET` | Outlook OAuth client secret | +| `OUTLOOK_TENANT_ID` | Outlook OAuth tenant ID | +| `OUTLOOK_SENDER_EMAILID` | Outlook sender email address | + + + +**Auth Security Settings**: + +| Variable | Description | +|----------|-------------| +| `MAX_FAILED_ATTEMPTS` | Maximum failed login attempts before lockout (default: `3`) | +| `LOCKOUT_DURATION_HOURS` | Hours to lock account after max failed attempts (default: `24`) | +| `INACTIVE_DAYS_THRESHOLD` | Days of inactivity before account is disabled (default: `60`) | + + ### FloConsole Service #### Required Variables -- `ALLOWED_ORIGINS`: Allowed origins (http://wavefront:3000) -- `CONSOLE_DB_HOST`: Database host (default: `postgres-console`) -- `CONSOLE_DB_PORT`: Database port (default: `5432`) -- `CONSOLE_DB_USERNAME`: Database username (default: `postgres`) -- `CONSOLE_DB_PASSWORD`: Database password (default: `postgres`) -- `CONSOLE_DB_NAME`: Database name (default: `console`) -- `CONSOLE_EMAIL`: Admin email address -- `CONSOLE_PASSWORD`: Admin password -- `CONSOLE_FIRST_NAME`: Admin first name -- `CONSOLE_LAST_NAME`: Admin last name -- `CONSOLE_JWT_ISSUER`: JWT issuer URL for console -- `CONSOLE_JWT_AUDIENCE`: JWT audience URL for console -- `CONSOLE_TOKEN_PREFIX`: Token prefix for console tokens (default: `fc_`) -- `SUPER_ADMIN_EMAIL`: Super admin email (usually same as `CONSOLE_EMAIL`) -- `TOKEN_EXPIRY`: Token expiration in seconds (default: `3600`) -- `TEMPORARY_TOKEN_EXPIRY`: Temporary token expiration (default: `600`) -- `PRIVATE_KEY`: Base64-encoded RSA private key (can be different from floware) -- `PUBLIC_KEY`: Base64-encoded RSA public key (can be different from floware) -- `APP_ENV`: Application environment -- `ENABLE_CLOUD_KMS`: Enable cloud KMS for key management (`true` or `false`) -- `PASSTHROUGH_SECRET`: Secret for service-to-service authentication (**IMPORTANT**: Must be the same as floware and call_processing) -- `DEFAULT_APP_NAME`: Name for the default app created automatically (e.g., `floware-dev`) -- `DEFAULT_APP_PUBLIC_URL`: Public URL for the default app (e.g., `http://floware:8001`) -- `DEFAULT_APP_PRIVATE_URL`: Private URL for the default app (e.g., `http://floware:8001`) +| Variable | Description | +|----------|-------------| +| `ALLOWED_ORIGINS` | Allowed origins (http://wavefront:3000) | +| `CONSOLE_DB_HOST` | Database host (default: `postgres-console`) | +| `CONSOLE_DB_PORT` | Database port (default: `5432`) | +| `CONSOLE_DB_USERNAME` | Database username (default: `postgres`) | +| `CONSOLE_DB_PASSWORD` | Database password (default: `postgres`) | +| `CONSOLE_DB_NAME` | Database name (default: `console`) | +| `CONSOLE_EMAIL` | Admin email address | +| `CONSOLE_PASSWORD` | Admin password | +| `CONSOLE_FIRST_NAME` | Admin first name | +| `CONSOLE_LAST_NAME` | Admin last name | +| `CONSOLE_JWT_ISSUER` | JWT issuer URL for console | +| `CONSOLE_JWT_AUDIENCE` | JWT audience URL for console | +| `CONSOLE_TOKEN_PREFIX` | Token prefix for console tokens (default: `fc_`) | +| `SUPER_ADMIN_EMAIL` | Super admin email (usually same as `CONSOLE_EMAIL`) | +| `TOKEN_EXPIRY` | Token expiration in seconds (default: `3600`) | +| `TEMPORARY_TOKEN_EXPIRY` | Temporary token expiration (default: `600`) | +| `PRIVATE_KEY` | Base64-encoded RSA private key (can be different from floware) | +| `PUBLIC_KEY` | Base64-encoded RSA public key (can be different from floware) | +| `APP_ENV` | Application environment | +| `ENABLE_CLOUD_KMS` | Enable cloud KMS for key management (`true` or `false`) | +| `PASSTHROUGH_SECRET` | Secret for service-to-service authentication (**IMPORTANT**: Must be the same as floware and call_processing) | +| `DEFAULT_APP_NAME` | Name for the default app created automatically (e.g., `floware-dev`) | +| `DEFAULT_APP_PUBLIC_URL` | Public URL for the default app (e.g., `http://floware:8001`) | +| `DEFAULT_APP_PRIVATE_URL` | Private URL for the default app (e.g., `http://floware:8001`) | ### Call Processing Service #### Required Variables -- `REDIS_HOST`: Redis host (default: `redis-call-processing`) -- `REDIS_PORT`: Redis port (default: `6379`) -- `REDIS_DB`: Redis database number (default: `0`) -- `APP_ENV`: Application environment -- `APP_NAME`: Application name (default: `call_processing`) -- `APP_NAME_FLOWARE`: Floware app name reference (default: `floware`) -- `FLOWARE_BASE_URL`: Floware URL (default: `http://floware:8001`) -- `PASSTHROUGH_SECRET`: Secret for service-to-service authentication -- `TOKEN_EXPIRY`: Token expiration in seconds (default: `3600`) -- `TEMPORARY_TOKEN_EXPIRY`: Temporary token expiration (default: `600`) -- `CALL_PROCESSING_TOKEN_PREFIX`: Token prefix (default: `fc_`) -- `CALL_PROCESSING_JWT_ISSUER`: JWT issuer URL for call processing +| Variable | Description | +|----------|-------------| +| `REDIS_HOST` | Redis host (default: `redis-call-processing`) | +| `REDIS_PORT` | Redis port (default: `6379`) | +| `REDIS_DB` | Redis database number (default: `0`) | +| `APP_ENV` | Application environment | +| `APP_NAME` | Application name (default: `call_processing`) | +| `APP_NAME_FLOWARE` | Floware app name reference (default: `floware`) | +| `FLOWARE_BASE_URL` | Floware URL (default: `http://floware:8001`) | +| `PASSTHROUGH_SECRET` | Secret for service-to-service authentication | +| `TOKEN_EXPIRY` | Token expiration in seconds (default: `3600`) | +| `TEMPORARY_TOKEN_EXPIRY` | Temporary token expiration (default: `600`) | +| `CALL_PROCESSING_TOKEN_PREFIX` | Token prefix (default: `fc_`) | +| `CALL_PROCESSING_JWT_ISSUER` | JWT issuer URL for call processing | ### Inference App Service (Optional) @@ -263,18 +312,26 @@ Uncomment the `inference_app` service in `docker-compose.yml` to enable. #### Required Variables -- `APP_ENV`: Application environment -- `CLOUD_PROVIDER`: `aws` or `gcp` -- `MODEL_STORAGE_BUCKET`: Bucket for ML models +| Variable | Description | +|----------|-------------| +| `APP_ENV` | Application environment | +| `CLOUD_PROVIDER` | `aws` or `gcp` | +| `MODEL_STORAGE_BUCKET` | Bucket for ML models | **If AWS**: -- `AWS_ACCESS_KEY_ID`: AWS access key -- `AWS_SECRET_ACCESS_KEY`: AWS secret key -- `AWS_REGION`: AWS region (e.g., `ap-south-1`) + +| Variable | Description | +|----------|-------------| +| `AWS_ACCESS_KEY_ID` | AWS access key | +| `AWS_SECRET_ACCESS_KEY` | AWS secret key | +| `AWS_REGION` | AWS region (e.g., `ap-south-1`) | **If GCP**: -- `GCP_PROJECT_ID`: GCP project ID -- `GOOGLE_APPLICATION_CREDENTIALS`: Path to service account JSON file (default: `/app/credentials/gcp-service-account.json`) + +| Variable | Description | +|----------|-------------| +| `GCP_PROJECT_ID` | GCP project ID | +| `GOOGLE_APPLICATION_CREDENTIALS` | Path to service account JSON file (default: `/app/credentials/gcp-service-account.json`) | ## Cloud Provider Setup @@ -503,16 +560,6 @@ ports: Increase Docker memory limit in Docker Desktop settings (recommended: 8GB minimum). -## Security Best Practices - -1. **Never commit docker-compose.yml with real credentials** -2. **Use strong passwords** for database and admin accounts -3. **Rotate JWT keys** regularly -4. **Use environment-specific configurations** (don't use dev credentials in production) -5. **Enable KMS encryption** for production deployments (`ENABLE_CLOUD_KMS=true`) -6. **Use HTTPS** for production deployments (add reverse proxy like Nginx) -7. **Restrict network access** using Docker networks and firewall rules - ## Initial Setup After starting all services, you need to configure floconsole to connect to floware: From 753df4ecb5d0b370e68ec9fd46813a42fc96f860 Mon Sep 17 00:00:00 2001 From: vizsatiz Date: Sun, 14 Dec 2025 15:53:15 +0530 Subject: [PATCH 6/9] fixing wavefront readme --- wavefront/README.md | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/wavefront/README.md b/wavefront/README.md index 58e14c03..3e164ce0 100644 --- a/wavefront/README.md +++ b/wavefront/README.md @@ -1,4 +1,19 @@ -## Wavefront AI Platform +

+ + Wavefront + +

+ +## Prerequisites + +The project has its backend services written in python and frontend in reactjs. It has the following dependencies: + +- Python >=3.11 +- Node.js >=22.12 +- uv >=0.7.15 +- pnpm >=10.13.1 + +## Wavefront Overview The platform consist of following components, which create a microservice mesh to provide scalable, secure, and reliable AI services. We have not used a fully microservice architecture as it is not necessary for our use case. @@ -23,15 +38,6 @@ The platform consists of following components: Wavefront

-## Prerequisites - -The project has its backend services written in python and frontend in reactjs. It has the following dependencies: - -- Python >=3.11 -- Node.js >=22.12 -- uv >=0.7.15 -- pnpm >=10.13.1 - The project is ready for production use only in Google Cloud Console and Amazon Web Services. In the current state of the project, it requires following cloud services to run locally (We are working on removing this dependencies for local runs): From 23c518339a76ff8293b4460114f322b72f684001 Mon Sep 17 00:00:00 2001 From: vizsatiz Date: Sun, 14 Dec 2025 15:57:46 +0530 Subject: [PATCH 7/9] Renaming to DOCKER_SETUP2 --- wavefront/{docker_setup.md => DOCKER_SETUP2.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename wavefront/{docker_setup.md => DOCKER_SETUP2.md} (100%) diff --git a/wavefront/docker_setup.md b/wavefront/DOCKER_SETUP2.md similarity index 100% rename from wavefront/docker_setup.md rename to wavefront/DOCKER_SETUP2.md From d3222b7022ddef0075cfc0e39159580343bde810 Mon Sep 17 00:00:00 2001 From: vizsatiz Date: Sun, 14 Dec 2025 15:58:08 +0530 Subject: [PATCH 8/9] Renaming to DOcker_Setup.md --- wavefront/{DOCKER_SETUP2.md => DOCKER_SETUP.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename wavefront/{DOCKER_SETUP2.md => DOCKER_SETUP.md} (100%) diff --git a/wavefront/DOCKER_SETUP2.md b/wavefront/DOCKER_SETUP.md similarity index 100% rename from wavefront/DOCKER_SETUP2.md rename to wavefront/DOCKER_SETUP.md From fbabec59dd4bac2945cd2e44328b6a50ba7b701f Mon Sep 17 00:00:00 2001 From: vizsatiz Date: Sun, 14 Dec 2025 17:03:41 +0530 Subject: [PATCH 9/9] Completed contributions md and roadmap --- CONTRIBUTING.md | 172 +++--------------------------------------------- ROADMAP.md | 126 ++++++----------------------------- 2 files changed, 29 insertions(+), 269 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 320f35ac..5b97d913 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,27 +1,8 @@ -# Contributing to Flo AI +# Contributing to Wavefront -Thank you for your interest in contributing to Flo AI! We welcome contributions from the community and are excited to work with you. +Thank you for your interest in contributing to Wavefront! We welcome contributions from the community and are excited to work with you. -This guide will help you get started with contributing to the Flo AI project. Please read it carefully before making your first contribution. - -> **Note**: This contributing guide currently focuses on **Flo AI**, the core agent building and orchestration library. **Wavefront AI** (the enterprise middleware platform) is currently in development and will be open-sourced in the future. When Wavefront AI is released, we will update this guide with additional contribution guidelines for the middleware platform. - ---- - -## ๐Ÿ“‹ Table of Contents - -- [Code of Conduct](#code-of-conduct) -- [Getting Started](#getting-started) -- [Development Environment Setup](#development-environment-setup) -- [Project Structure](#project-structure) -- [Development Workflow](#development-workflow) -- [Code Style and Standards](#code-style-and-standards) -- [Testing Guidelines](#testing-guidelines) -- [Documentation Guidelines](#documentation-guidelines) -- [Commit Message Guidelines](#commit-message-guidelines) -- [Pull Request Process](#pull-request-process) -- [Types of Contributions](#types-of-contributions) -- [Questions and Support](#questions-and-support) +This guide will help you get started with contributing to the Wavefront project. Please read it carefully before making your first contribution. --- @@ -116,27 +97,11 @@ source .venv/bin/activate # On macOS/Linux ### Environment Variables -Set up your API keys for testing (create a `.env` file or export them): - -[Documentation to be added soon] - -### Verify Installation - -Test your installation: +Set up your API keys for testing (create a `.env` file or export them). Please find the documentation on environment variables [here](DOCKER_SETUP.md). -```bash -# Run the test suite -pytest tests/unit-tests/ - -# Run a specific test -pytest tests/unit-tests/test_agent_builder_tools.py -``` +## ๐Ÿ“ Setting up the project Locally -## ๐Ÿ“ Project Structure - -Understanding the project structure will help you navigate the codebase: - -[To be added] +For local development, you can use the following instructions in quick start mentioned [here](/wavefront/README.md#quick-start). --- @@ -232,91 +197,12 @@ git push origin feature/your-feature-name --- -## ๐Ÿ’ป Code Style and Standards - -### Python Code Style - -We use **pre-commit hooks** to ensure code quality. Set it up: - -```bash -# Install pre-commit -pip install pre-commit - -# Install hooks -pre-commit install - -# Run on all files (optional, but recommended) -pre-commit run --all-files -``` - -**Key style guidelines:** - -1. **Follow PEP 8** - Python style guide -2. **Type hints** - Use type hints for function signatures: - ```python - from typing import Optional, List - - async def process_data( - items: List[str], - limit: Optional[int] = None - ) -> dict: - ... - ``` -3. **Docstrings** - Use Google-style docstrings: - ```python - def my_function(param1: str, param2: int) -> bool: - """Brief description of the function. - - Args: - param1: Description of param1 - param2: Description of param2 - - Returns: - Description of return value - - Raises: - ValueError: When something goes wrong - """ - ``` -4. **Async/Await** - Use async/await for I/O operations -5. **Error Handling** - Use appropriate exception types and provide clear error messages - -## ๐Ÿงช Testing Guidelines - -### Writing Tests - -1. **Test Coverage** - Aim for high test coverage, especially for new features -2. **Test Organization**: - - Unit tests in `tests/unit-tests/` - - Integration tests in `tests/integration-tests/` - - Mark integration tests with `@pytest.mark.integration` - -3. **Test Naming**: - ```python - def test_function_name_with_condition_returns_expected(): - """Test that function_name returns expected when condition is met.""" - ``` - -4. **Async Tests**: - ```python - import pytest - - @pytest.mark.asyncio - async def test_async_function(): - result = await my_async_function() - assert result == expected - ``` - -5. **Fixtures** - Use pytest fixtures for common setup: - ```python - @pytest.fixture - def sample_agent(): - return AgentBuilder().with_name('test').build() - ``` - ### Running Tests ```bash +# Run all tests +cd wavefront + # Run all unit tests pytest tests/unit-tests/ @@ -345,32 +231,6 @@ pytest -m "not integration" --- -## ๐Ÿ“š Documentation Guidelines - -### Code Documentation - -- **Docstrings** - All public functions, classes, and methods should have docstrings -- **Type hints** - Use type hints for better IDE support and documentation -- **Comments** - Add comments for complex logic, but prefer self-documenting code - -### Documentation Updates - -When adding new features, update: - -1. **README.md** - If the feature is user-facing -2. **API Documentation** - If adding new APIs -3. **Examples** - Add examples in `flo_ai/examples/` if applicable -4. **Docstrings** - Update docstrings for any changed functions - -### Documentation Format - -- Use Markdown for documentation files -- Use MDX for the documentation site -- Include code examples where helpful -- Keep documentation up-to-date with code changes - ---- - ## ๐Ÿ“ Commit Message Guidelines We follow [Conventional Commits](https://www.conventionalcommits.org/) specification: @@ -572,18 +432,6 @@ Contributors will be recognized in: --- -## ๐Ÿ“„ License - -By contributing, you agree that your contributions will be licensed under the same license as the project (MIT License for Flo AI). - ---- - ## ๐Ÿ™ Thank You! -Thank you for taking the time to contribute to Flo AI! Your contributions help make this project better for everyone. - -**Happy Contributing! ๐Ÿš€** - ---- - -**Questions?** Feel free to open an issue or reach out to vishnu@rootflo.ai +Thank you for taking the time to contribute to Wavefront! Your contributions help make this project better for everyone. \ No newline at end of file diff --git a/ROADMAP.md b/ROADMAP.md index 5ffbb6d1..20f8173d 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -2,23 +2,7 @@ This roadmap provides a comprehensive overview of the direction Wavefront AI is heading. It covers all major components of the platform: the Flo AI library, Wavefront Core middleware, Control Panel, CLI, and ecosystem tools. -The roadmap is organized by component and priority, with clear timelines and status indicators. We welcome community feedback and contributions! - ---- - -## ๐Ÿ“‹ Table of Contents - -- [Release Timeline](#release-timeline) -- [Flo AI Library](#flo-ai-library) -- [Wavefront Core Middleware](#wavefront-core-middleware) -- [Wavefront Control Panel](#wavefront-control-panel) -- [Wavefront CLI](#wavefront-cli) -- [Data & Integration Layer](#data--integration-layer) -- [Developer Experience](#developer-experience) -- [Enterprise Features](#enterprise-features) -- [Observability & Monitoring](#observability--monitoring) - ---- +The roadmap is organized by component and priority. We welcome community feedback and contributions! ## ๐Ÿ—“๏ธ Release Timeline @@ -31,9 +15,22 @@ The roadmap is organized by component and priority, with clear timelines and sta --- +## ๐Ÿ“Š Beta Release Scope + +Current release has the following features implemented: + +| Feature | Limitation | +|---------|------------| +| **Datasource** | You can connect to multiple data sources. Current support is for Google Bigquery and AWS redshift. | +| **Agent** | You can create agents using the console and run them using the middleware. | +| **Workflow** | You can create workflows using the console and run them using the middleware. | +| **Voice Bots** | You can process voice calls using the middleware. But currently only outgoing calls are supported. Only supported telephony service is Twilio | +| **Inference App** | You can create inference pytorch models using the middleware, but the support is limited to certain pytorch models. This feature is fully `experimental`, and APIs are bound to change. | +| **API Service** | You can create API services to connect to any backend service. We have provided support for JSON and non JSON payload. Authenticate is limited to API Key, Basic Auth & Bearer Token. | + ## ๐Ÿค– Flo AI Library -The core agent building and orchestration framework. +The core agent building and orchestration framework. The following are that is going to be implemented in the coming releases ### Core Features @@ -70,7 +67,7 @@ The core agent building and orchestration framework. --- -## ๐Ÿ—๏ธ Wavefront Core Middleware +## ๐Ÿ—๏ธ Wavefront Core Middleware (a.k.a Floware) The core middleware service that provides APIs, authentication, authorization, and data connectivity. @@ -105,13 +102,11 @@ The core middleware service that provides APIs, authentication, authorization, a | **Agent-Level RBAC** | Fine-grained permissions for agent access and execution | High | Yet to start | v0.1.0 | | **Data Source RBAC** | Granular permissions for data source access | High | Yet to start | v0.1.0 | | **Role Management** | Create, update, and manage custom roles | High | โœ… Available | v0.1.0 | -| **Permission Inheritance** | Hierarchical permission inheritance | Medium | Yet to start | v0.2.0 | -| **Attribute-Based Access Control (ABAC)** | Advanced ABAC policies | Low | Yet to start | v0.3.0 | | **Audit Logging for Access** | Comprehensive audit logs for all access attempts | High | Yet to start | v0.1.0 | --- -## ๐ŸŽ›๏ธ Wavefront Control Panel +## ๐ŸŽ›๏ธ Wavefront Control Panel (a.k.a Flo Console) Unified frontend for configuring agents, workflows, AI models, guardrails, and RBAC. @@ -193,12 +188,11 @@ Command-line interface for configuring and managing Wavefront AI. | Adapter | Description | Priority | Status | Target Release | |---------|-------------|----------|--------|----------------| -| **Custom API Configuration** | Flexible HTTP endpoint support with custom authentication | High | ๐Ÿ”„ In Progress | v0.1.0 | +| **Custom API Configuration** | Flexible HTTP endpoint support with custom authentication | High | โœ… Available | v0.1.0 | | **Salesforce** | Native Salesforce API integration | High | ๐Ÿ”„ In Progress | v0.1.0 | | **SAP** | SAP ERP system integration | Medium | Yet to start | v0.2.0 | -| **ServiceNow** | ServiceNow API integration | Medium | Yet to start | v0.2.0 | | **Jira** | Jira API integration for project management | Low | Yet to start | v0.3.0 | -| **Slack** | Slack API integration for notifications and workflows | Medium | Yet to start | v0.2.0 | +| **Slack** | Slack API integration for notifications and workflows | Medium | โœ… Available | v0.2.0 | | **Microsoft 365** | Microsoft 365 API integration | Medium | Yet to start | v0.2.0 | | **GitHub/GitLab** | Version control system integrations | Low | Yet to start | v0.3.0 | @@ -224,8 +218,6 @@ Command-line interface for configuring and managing Wavefront AI. ## ๐ŸŽจ Developer Experience -### Flo AI Studio Enhancements - ### Developer Tools | Feature | Description | Priority | Status | Target Release | @@ -302,88 +294,8 @@ Command-line interface for configuring and managing Wavefront AI. --- -## ๐ŸŒ Community & Ecosystem - -### Documentation - -| Feature | Description | Priority | Status | Target Release | -|---------|-------------|----------|--------|----------------| -| **Getting Started Guide** | Comprehensive getting started documentation | High | ๐Ÿ”„ In Progress | v0.1.0 | -| **API Documentation** | Complete API reference documentation | High | Yet to start | v0.1.0 | -| **Tutorials** | Step-by-step tutorials for common use cases | High | Yet to start | v0.1.0 | -| **Architecture Documentation** | Detailed architecture and design documentation | Medium | Yet to start | v0.2.0 | -| **Best Practices Guide** | Best practices for building production agents | Medium | Yet to start | v0.2.0 | -| **Video Tutorials** | Video tutorials and demos | Low | Yet to start | v0.3.0 | - -### Examples & Templates - -| Feature | Description | Priority | Status | Target Release | -|---------|-------------|----------|--------|----------------| -| **Example Gallery** | Comprehensive collection of example agents and workflows | High | ๐Ÿ”„ In Progress | v0.1.0 | -| **Use Case Templates** | Pre-built templates for common use cases | High | Yet to start | v0.2.0 | -| **Integration Examples** | Examples for integrating with popular services | Medium | Yet to start | v0.2.0 | -| **Community Templates** | Platform for sharing community-created templates | Low | Yet to start | v0.3.0 | - -### Community Features - -| Feature | Description | Priority | Status | Target Release | -|---------|-------------|----------|--------|----------------| -| **Community Forum** | Discussion forum for community support | Medium | Yet to start | v0.2.0 | -| **Template Marketplace** | Marketplace for sharing and discovering templates | Low | Yet to start | v0.3.0 | -| **Contributor Guide** | Comprehensive guide for contributors | High | ๐Ÿ”„ In Progress | v0.1.0 | -| **Community Showcase** | Showcase of community-built solutions | Low | Yet to start | v0.3.0 | - ---- - -## โœ… Released Features - -### Flo AI Library - -| Feature | Description | Status | Version | -|---------|-------------|--------|---------| -| **Full Composability** | Teams can be combined with teams and agents with agents. Extended to team + agent composability | โœ… | v0.0.4 | -| **Error Handling** | Ability to handle errors autonomously | โœ… | v0.0.4 | -| **LLM Extensibility** | Ability to use different LLMs across different agents and teams | โœ… | v0.0.4 | -| **Async Tools** | Ability to create tools easily within asyncio | โœ… | v0.0.4 | -| **Observer Framework** | Observer framework for raising agent decision events and other important events | โœ… | v0.0.4 | -| **Test Framework** | Framework for unit-testing flo-ai and its internal functionalities | โœ… | v0.0.4 | -| **Linear Router** | Router that lets you build agents or teams that execute linearly or sequentially | โœ… | v0.0.3 | -| **Reflection Router** | Component that can make the AI retrospectively look at the current output and retry or work again on the task | โœ… | v0.0.3 | -| **Delegator Router** | Component that can help delegate a flo to a particular agent, by some condition | โœ… | v0.0.3 | -| **Logging Framework** | Better logging framework which can be extended to parent application (with log level control) | โœ… | v0.0.3 | -| **Output Formatter** | Ability to templatize output format using Pydantic | โœ… | v0.0.5 | -| **YAML-Based Agents** | Define agents and workflows using YAML configuration | โœ… | v1.0.0 | -| **LLM-Powered Routers** | Intelligent routing using Large Language Models | โœ… | v1.0.0 | -| **Plan-Execute Router** | Cursor-style plan-and-execute workflows | โœ… | v1.0.0 | -| **Document Processing** | Process PDF and TXT documents with AI agents | โœ… | v1.0.0 | -| **Variables System** | Dynamic variable resolution in agent prompts | โœ… | v1.0.0 | -| **Agent Builder Pattern** | Fluent interface for building agents | โœ… | v1.0.0 | -| **Arium Workflow Engine** | Multi-agent workflow orchestration engine | โœ… | v1.0.0 | -| **OpenTelemetry Integration** | Built-in observability with automatic instrumentation | โœ… | v1.0.0 | -| **Flo AI Studio** | Visual workflow designer with React-based UI | โœ… | v1.0.0 | - -### Platform Components - -| Feature | Description | Status | Version | -|---------|-------------|--------|---------| -| **Frontend SDK** | React component library for building AI applications | โœ… | v1.0.0 | -| **Low Code YAML Builder** | YAML-based agent and workflow builder | โœ… | v1.0.0 | - ---- - ## ๐Ÿ“ Notes -- **Status Legend**: - - โœ… Available - Feature is implemented and available - - ๐Ÿ”„ In Progress - Feature is currently being developed - - Yet to start - Feature is planned but not yet started - - ๐Ÿ“‹ Roadmap - Feature is on the roadmap with lower priority - -- **Priority Levels**: - - **High**: Critical for core functionality or major milestones - - **Medium**: Important but not blocking - - **Low**: Nice to have, can be deferred - - **Version Numbers**: Version numbers are estimates and subject to change based on priorities and community feedback. - **Community Contributions**: The community is welcome to suggest changes to the roadmap through pull requests. Community-suggested features will be evaluated and prioritized based on alignment with project goals.