diff --git a/src/backend/base/langflow/components/olivya/__init__.py b/src/backend/base/langflow/components/olivya/__init__.py new file mode 100644 index 000000000..8aa987f5d --- /dev/null +++ b/src/backend/base/langflow/components/olivya/__init__.py @@ -0,0 +1,3 @@ +from .olivya import OlivyaComponent + +__all__ = ["OlivyaComponent"] diff --git a/src/backend/base/langflow/components/olivya/olivya.py b/src/backend/base/langflow/components/olivya/olivya.py new file mode 100644 index 000000000..1604df9be --- /dev/null +++ b/src/backend/base/langflow/components/olivya/olivya.py @@ -0,0 +1,116 @@ +import json + +import httpx +from loguru import logger + +from langflow.custom import Component +from langflow.io import MessageTextInput, Output +from langflow.schema import Data + + +class OlivyaComponent(Component): + display_name = "Place Call" + description = "A component to create an outbound call request from Olivya's platform." + documentation: str = "http://docs.langflow.org/components/olivya" + icon = "Olivya" + name = "OlivyaComponent" + + inputs = [ + MessageTextInput( + name="api_key", + display_name="API Key", + info="Your API key for authentication", + value="", + required=True, + ), + MessageTextInput( + name="from_number", + display_name="From Number", + info="The Agent's phone number", + value="", + required=True, + ), + MessageTextInput( + name="to_number", + display_name="To Number", + info="The recipient's phone number", + value="", + required=True, + ), + MessageTextInput( + name="first_message", + display_name="First Message", + info="The Agent's introductory message", + value="", + required=False, + tool_mode=True, + ), + MessageTextInput( + name="system_prompt", + display_name="System Prompt", + info="The system prompt to guide the interaction", + value="", + required=False, + ), + MessageTextInput( + name="conversation_history", + display_name="Conversation History", + info="The summary of the conversation", + value="", + required=False, + tool_mode=True, + ), + ] + + outputs = [ + Output(display_name="Output", name="output", method="build_output"), + ] + + async def build_output(self) -> Data: + try: + payload = { + "variables": { + "first_message": self.first_message.strip() if self.first_message else None, + "system_prompt": self.system_prompt.strip() if self.system_prompt else None, + "conversation_history": self.conversation_history.strip() if self.conversation_history else None, + }, + "from_number": self.from_number.strip(), + "to_number": self.to_number.strip(), + } + + headers = { + "Authorization": self.api_key.strip(), + "Content-Type": "application/json", + } + + logger.info("Sending POST request with payload: %s", payload) + + # Send the POST request with a timeout + async with httpx.AsyncClient() as client: + response = await client.post( + "https://phone.olivya.io/create_zap_call", + headers=headers, + json=payload, + timeout=10.0, + ) + response.raise_for_status() + + # Parse and return the successful response + response_data = response.json() + logger.info("Request successful: %s", response_data) + + except httpx.HTTPStatusError as http_err: + logger.exception("HTTP error occurred") + response_data = {"error": f"HTTP error occurred: {http_err}", "response_text": response.text} + except httpx.RequestError as req_err: + logger.exception("Request failed") + response_data = {"error": f"Request failed: {req_err}"} + except json.JSONDecodeError as json_err: + logger.exception("Response parsing failed") + response_data = {"error": f"Response parsing failed: {json_err}", "raw_response": response.text} + except Exception as e: # noqa: BLE001 + logger.exception("An unexpected error occurred") + response_data = {"error": f"An unexpected error occurred: {e!s}"} + + # Return the response as part of the output + return Data(value=response_data) diff --git a/src/frontend/src/icons/Olivya/index.tsx b/src/frontend/src/icons/Olivya/index.tsx new file mode 100644 index 000000000..705f3f4f4 --- /dev/null +++ b/src/frontend/src/icons/Olivya/index.tsx @@ -0,0 +1,9 @@ +import React, { forwardRef } from "react"; +import OlivyaSVG from "./olivya"; + +export const OlivyaIcon = forwardRef< + SVGSVGElement, + React.PropsWithChildren<{}> +>((props, ref) => { + return ; +}); diff --git a/src/frontend/src/icons/Olivya/olivya.jsx b/src/frontend/src/icons/Olivya/olivya.jsx new file mode 100644 index 000000000..bc82d1955 --- /dev/null +++ b/src/frontend/src/icons/Olivya/olivya.jsx @@ -0,0 +1,478 @@ +const OlivyaSVG = (props) => ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +); +export default OlivyaSVG; diff --git a/src/frontend/src/utils/styleUtils.ts b/src/frontend/src/utils/styleUtils.ts index da2c2c86d..9783a6b2f 100644 --- a/src/frontend/src/utils/styleUtils.ts +++ b/src/frontend/src/utils/styleUtils.ts @@ -287,6 +287,7 @@ import { NotDiamondIcon } from "../icons/NotDiamond"; import { NotionIcon } from "../icons/Notion"; import { NovitaIcon } from "../icons/Novita"; import { NvidiaIcon } from "../icons/Nvidia"; +import { OlivyaIcon } from "../icons/Olivya"; import { OllamaIcon } from "../icons/Ollama"; import { OpenAiIcon } from "../icons/OpenAi"; import { OpenRouterIcon } from "../icons/OpenRouter"; @@ -399,6 +400,7 @@ export const nodeColors: { [char: string]: string } = { chains: "#FE7500", list: "#9AAE42", agents: "#903BBE", + Olivya: "#00413B", tools: "#00fbfc", memories: "#F5B85A", saved_components: "#a5B85A", @@ -525,6 +527,7 @@ export const SIDEBAR_BUNDLES = [ name: "astra_assistants", icon: "AstraDB", }, + { display_name: "Olivya", name: "olivya", icon: "Olivya" }, { display_name: "LangWatch", name: "langwatch", icon: "Langwatch" }, { display_name: "Notion", name: "Notion", icon: "Notion" }, { display_name: "Needle", name: "needle", icon: "Needle" }, @@ -639,6 +642,7 @@ export const nodeIconsLucide: iconsType = { AstraDB: AstraDBIcon, BingSearchAPIWrapper: BingIcon, BingSearchRun: BingIcon, + Olivya: OlivyaIcon, Bing: BingIcon, Cohere: CohereIcon, ChevronsUpDownIcon,