diff --git a/.github/workflows/deploy_zep.yml b/.github/workflows/deploy_zep.yml deleted file mode 100644 index 172cd3f9f..000000000 --- a/.github/workflows/deploy_zep.yml +++ /dev/null @@ -1,28 +0,0 @@ -name: Build and deploy Python app to Azure Web App - l3-zep-dev - -on: - push: - branches: - - main - paths: - - "zep/**" - workflow_dispatch: - -jobs: - deploy: - runs-on: ubuntu-latest - - environment: - name: "production" - url: ${{ steps.deploy-to-webapp.outputs.webapp-url }} - - steps: - - name: "Deploy to Azure Web App" - uses: azure/webapps-deploy@v2 - id: deploy-to-webapp - with: - app-name: "l3-zep-dev" - slot-name: "production" - # publish-profile: ${{ secrets.AzureAppService_PublishProfile_5aa592a5843d47f5ab6d78132942a60f }} - publish-profile: ${{ secrets.AZUREAPPSERVICE_PUBLISHPROFILE_AC74324B8D274B7F9F5FE91CAE3ADB57 }} - images: ghcr.io/getzep/zep-cloud:0.19,ghcr.io/getzep/zep-nlp-server:0.4.1 diff --git a/apps/server/agents/agent_simulations/agent/dialogue_agent_with_tools.py b/apps/server/agents/agent_simulations/agent/dialogue_agent_with_tools.py index ba69cc624..2638bc355 100644 --- a/apps/server/agents/agent_simulations/agent/dialogue_agent_with_tools.py +++ b/apps/server/agents/agent_simulations/agent/dialogue_agent_with_tools.py @@ -1,18 +1,15 @@ from typing import List + +from langchain.agents import AgentType, initialize_agent from langchain.chat_models import ChatOpenAI from langchain.memory import ConversationBufferMemory -from langchain.schema import ( - AIMessage, -) +from langchain.schema import AIMessage, SystemMessage + from agents.agent_simulations.agent.dialogue_agent import DialogueAgent -from langchain.agents import initialize_agent -from langchain.agents import AgentType -from langchain.schema import ( - SystemMessage, -) -from typings.agent import AgentWithConfigsOutput -from memory.zep.zep_memory import ZepMemory +from agents.conversational.output_parser import ConvoOutputParser from config import Config +from memory.zep.zep_memory import ZepMemory +from typings.agent import AgentWithConfigsOutput class DialogueAgentWithTools(DialogueAgent): @@ -68,6 +65,7 @@ def send(self) -> str: memory=memory, agent_kwargs={ "system_message": self.system_message.content, + "output_parser": ConvoOutputParser(), }, ) diff --git a/apps/server/agents/agent_simulations/decentralized/decentralized_speaker.py b/apps/server/agents/agent_simulations/decentralized/decentralized_speaker.py index 5592b4c58..f0f5503f0 100644 --- a/apps/server/agents/agent_simulations/decentralized/decentralized_speaker.py +++ b/apps/server/agents/agent_simulations/decentralized/decentralized_speaker.py @@ -145,9 +145,8 @@ def generate_character_header( return f"""{game_description} Your name is {character_name}. Your role is: {role} -You are a speaker. -You are speaking on the topic: {topic}. -Your goal is to be as creative as possible and speak in the style of {character_name}. +Your goal is to accomplish tasks. +Here is task or topic: {topic}. """ # def generate_character_system_message( @@ -171,14 +170,14 @@ def generate_character_header( # ) # ) - def generate_character_bidding_template(self, header: str): + def generate_character_bidding_template(self, header: str, name: str, role: str): bidding_template = f"""{header} ``` {{message_history}} ``` - On the scale of 1 to 10, where 1 is not contradictory and 10 is extremely contradictory, rate how contradictory the following message is to your ideas. + In the context of {name}, On the scale of 1 to 10, where 1 is not relevant and 10 is extremely relevant, rate how relevant are you to accomplish task. ``` {{recent_message}} @@ -234,7 +233,7 @@ def run( ) bidding_template = self.generate_character_bidding_template( - character_header + character_header, name, agent_with_configs.agent.role ) # character_system_message = self.generate_character_system_message( @@ -257,7 +256,7 @@ def run( ) ) - max_iters = 10 + max_iters = 1 n = 0 diff --git a/apps/server/controllers/team.py b/apps/server/controllers/team.py index c17283c99..56d19e933 100644 --- a/apps/server/controllers/team.py +++ b/apps/server/controllers/team.py @@ -162,6 +162,21 @@ def get_team_type(auth: UserAccount = Depends(authenticate)) -> List[object]: """ return [ + { + "is_public": True, + "is_active": True, + "name": "Decentralized Speaker", + "description": "This notebook showcases how to implement a multi-agent simulation where a privileged agent decides who to speak", + "team_type": TeamOfAgentsType.DECENTRALIZED_SPEAKER, + "fields": [], + "agents": [ + {"id": 1, "role": "Speaker"}, + {"id": 2, "role": "Speaker"}, + {"id": 3, "role": "Speaker"}, + {"id": 4, "role": "Speaker"}, + {"id": 5, "role": "Speaker"}, + ], + }, { "is_public": True, "is_active": True, @@ -228,21 +243,6 @@ def get_team_type(auth: UserAccount = Depends(authenticate)) -> List[object]: "fields": [], "agents": [{"id": 1, "role": "Planner"}, {"id": 2, "role": "Executor"}], }, - { - "is_public": True, - "is_active": True, - "name": "Decentralized Speaker", - "description": "This notebook showcases how to implement a multi-agent simulation where a privileged agent decides who to speak", - "team_type": TeamOfAgentsType.DECENTRALIZED_SPEAKER, - "fields": [], - "agents": [ - {"id": 1, "role": "Speaker"}, - {"id": 2, "role": "Speaker"}, - {"id": 3, "role": "Speaker"}, - {"id": 4, "role": "Speaker"}, - {"id": 5, "role": "Speaker"}, - ], - }, ] diff --git a/apps/server/main.py b/apps/server/main.py index ae2aa48d8..d599492db 100644 --- a/apps/server/main.py +++ b/apps/server/main.py @@ -122,7 +122,7 @@ def root(): return f"Server is running on {Config.ENV} environment" -print("Server is running on port 4000") +print("Server is running on 4000 port") if __name__ == "__main__": uvicorn.run(app, host="0.0.0.0", port=4000) diff --git a/apps/server/models/chat.py b/apps/server/models/chat.py index abe48222a..6ff22ff71 100644 --- a/apps/server/models/chat.py +++ b/apps/server/models/chat.py @@ -216,6 +216,7 @@ def get_chats(cls, db, account): .outerjoin(AccountModel, ChatModel.creator_account_id == AccountModel.id) .outerjoin(TeamModel, ChatModel.team_id == TeamModel.id) .outerjoin(AgentModel, ChatModel.agent_id == AgentModel.id) + .order_by(ChatModel.created_on.desc()) .filter( ChatModel.creator_account_id == account.id, or_( diff --git a/apps/server/tools/cal/cal_booking_tool.py b/apps/server/tools/cal/cal_booking_tool.py index 6769d0e88..81e30adab 100644 --- a/apps/server/tools/cal/cal_booking_tool.py +++ b/apps/server/tools/cal/cal_booking_tool.py @@ -53,7 +53,7 @@ class CalBookingTool(BaseTool): def _run( self, query: str, run_manager: Optional[CallbackManagerForToolRun] = None ) -> str: - api = os.environ.get("CALCOM_API") + base_url = "https://api.cal.com/v1" cal_api_key = self.get_env_key("CALCOM_API_KEY") cal_username = self.get_env_key("CALCOM_USERNAME") @@ -70,7 +70,9 @@ def _run( duration = action.get("duration") try: - res = requests.get(f"{api}/event-types", params={"apiKey": cal_api_key}) + res = requests.get( + f"{base_url}/event-types", params={"apiKey": cal_api_key} + ) event_types = res.json().get("event_types", []) if not event_types: raise ToolException( @@ -93,7 +95,7 @@ def _run( try: response = requests.post( - f"{api}/bookings", + f"{base_url}/bookings", params={"apiKey": cal_api_key}, json={ "eventTypeId": duration, diff --git a/apps/server/tools/cal/cal_get_available_tool.py b/apps/server/tools/cal/cal_get_available_tool.py index 266e41c2f..67b20cbd7 100644 --- a/apps/server/tools/cal/cal_get_available_tool.py +++ b/apps/server/tools/cal/cal_get_available_tool.py @@ -49,7 +49,7 @@ class CalGetAvailableDatesTool(BaseTool): def _run( self, query: str, run_manager: Optional[CallbackManagerForToolRun] = None ) -> str: - api = os.environ.get("CALCOM_API") + base_url = "https://api.cal.com/v1" cal_api_key = self.get_env_key("CALCOM_API_KEY") cal_username = self.get_env_key("CALCOM_USERNAME") @@ -69,7 +69,7 @@ def _run( dateFrom = datetime.strptime(dates["dateFrom"], "%d/%m/%Y").timestamp() dateTo = datetime.strptime(dates["dateTo"], "%d/%m/%Y").timestamp() try: - api = f"{api}/availability" + api = f"{base_url}/availability" response = requests.get( api, params={ diff --git a/apps/server/tools/zapier/zapier_send.py b/apps/server/tools/zapier/zapier_send.py index cf50e00dd..36ba89bf3 100644 --- a/apps/server/tools/zapier/zapier_send.py +++ b/apps/server/tools/zapier/zapier_send.py @@ -1,20 +1,24 @@ +import json +import os from typing import Optional, Type -from langchain.agents import AgentType, initialize_agent -from langchain.agents.agent_toolkits import ZapierToolkit +import requests from langchain.callbacks.manager import CallbackManagerForToolRun -from langchain.utilities.zapier import ZapierNLAWrapper from pydantic import BaseModel, Field -from exceptions import ToolEnvKeyException +from exceptions import ToolEnvKeyException, ToolException from tools.base import BaseTool -from utils.model import get_llm class ZapierSendSchema(BaseModel): query: str = Field( ..., - description="use zapier", + description=( + "Your task is to process a JSON string representing an instruction-related query for a specific action.\n" + "Extract the 'instructions' field from the JSON, containing clear, human-readable instructions.\n" + "Retrieve the 'action_id' separately if provided by the user; if not, set it as an empty string.\n" + "Ensure 'action_id' is not included inside the 'instructions' field in the returned JSON.\n" + ), ) @@ -25,7 +29,12 @@ class ZapierSendTool(BaseTool): slug = "zapierSend" - description = "use zapier" + description = ( + "Your task is to process a JSON string representing an instruction-related query for a specific action.\n" + "Extract the 'instructions' field from the JSON, containing clear, human-readable instructions.\n" + "Retrieve the 'action_id' separately if provided by the user; if not, set it as an empty string.\n" + "Ensure 'action_id' is not included inside the 'instructions' field in the returned JSON.\n" + ) args_schema: Type[ZapierSendSchema] = ZapierSendSchema @@ -35,6 +44,7 @@ def _run( self, query: str, run_manager: Optional[CallbackManagerForToolRun] = None ) -> str: """Send Zapier and return the results.""" + base_url = "https://actions.zapier.com/api/v1" zapier_nla_api_key = self.get_env_key("ZAPIER_NLA_API_KEY") if not zapier_nla_api_key: @@ -42,16 +52,42 @@ def _run( "Please fill Zapier API Key in the [Zapier Toolkit](/toolkits/zapier)" ) - llm = get_llm( - self.settings, - self.agent_with_configs, - ) - zapier = ZapierNLAWrapper(zapier_nla_api_key=zapier_nla_api_key) - toolkit = ZapierToolkit.from_zapier_nla_wrapper(zapier) - agent = initialize_agent( - toolkit.get_tools(), - llm, - agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION, - verbose=True, - ) - return agent.run(query) + data = json.loads(query) + try: + response = requests.get( + f"{base_url}/exposed/", params={"api_key": zapier_nla_api_key} + ) + + result = response.json().get("results") + if not result: + raise ToolException( + "Please set up at least one Zap in the [Zapier Dashboard](https://zapier.com/app/dashboard)" + ) + + action_id = next( + ( + result_item.get("id") + for result_item in result + if result_item.get("id") == data.get("action_id") + ), + None, + ) + if not action_id: + error = "Action with provided 'id' not found, Here is your available actions that you can use with Zapier Integration:\n" + for result_item in result: + error += f'- {result_item["id"]} | {result_item["description"]}\n' + + raise ToolException(error) + + executionResponse = requests.post( + f"{base_url}/exposed/{action_id}/execute/", + params={"api_key": zapier_nla_api_key}, + json={ + "instructions": data.get("instructions"), + "preview_only": False, + }, + ) + + return str(executionResponse.json()) + except Exception as e: + raise ToolException(str(e)) diff --git a/apps/server/utils/configs/default.py b/apps/server/utils/configs/default.py index 7fb8c3119..f2b545f1e 100644 --- a/apps/server/utils/configs/default.py +++ b/apps/server/utils/configs/default.py @@ -3,7 +3,7 @@ "naming": { "home": "Home", "agent": "Agent", - "team": "Team", + "team": "Multi-Agent", "datasource": "Knowledge", "model": "Model", "discovery": "Discovery", diff --git a/apps/ui/.env.develop b/apps/ui/.env.develop index 8c1bf3430..3dd9ac123 100644 --- a/apps/ui/.env.develop +++ b/apps/ui/.env.develop @@ -14,6 +14,7 @@ REACT_APP_TWITTER_LINK=https://twitter.com/l3velshq REACT_APP_YOUTUBE_LINK=https://www.youtube.com/@L3AGI REACT_APP_YOUTUBE_VIDEO_ID=i84RodECglM +REACT_APP_YOUTUBE_VIDEO_DATA_SOURCE_ID=Fza4gHP_M3o REACT_APP_TERMS_LINK=https://github.com/l3vels/L3AGI/blob/main/docs/terms.md REACT_APP_PRIVACY=https://github.com/l3vels/L3AGI/blob/main/docs/privacy.md diff --git a/apps/ui/.env.local b/apps/ui/.env.local index a4c05655b..7fba89eb4 100644 --- a/apps/ui/.env.local +++ b/apps/ui/.env.local @@ -18,6 +18,8 @@ REACT_APP_TWITTER_LINK=https://twitter.com/l3velshq REACT_APP_YOUTUBE_LINK=https://www.youtube.com/@L3AGI REACT_APP_YOUTUBE_VIDEO_ID=i84RodECglM +REACT_APP_YOUTUBE_VIDEO_DATA_SOURCE_ID=Fza4gHP_M3o + REACT_APP_TERMS_LINK=https://github.com/l3vels/L3AGI/blob/main/docs/terms.md REACT_APP_PRIVACY=https://github.com/l3vels/L3AGI/blob/main/docs/privacy.md diff --git a/apps/ui/.env.production b/apps/ui/.env.production index 784d077d6..d2c96f000 100644 --- a/apps/ui/.env.production +++ b/apps/ui/.env.production @@ -15,6 +15,8 @@ REACT_APP_TWITTER_LINK=https://twitter.com/l3velshq REACT_APP_YOUTUBE_LINK=https://www.youtube.com/@L3AGI REACT_APP_YOUTUBE_VIDEO_ID=i84RodECglM +REACT_APP_YOUTUBE_VIDEO_DATA_SOURCE_ID=Fza4gHP_M3o + REACT_APP_TERMS_LINK=https://github.com/l3vels/L3AGI/blob/main/docs/terms.md REACT_APP_PRIVACY=https://github.com/l3vels/L3AGI/blob/main/docs/privacy.md diff --git a/apps/ui/src/@types/vite-env.d.ts b/apps/ui/src/@types/vite-env.d.ts index baecae1a0..dbd39dae7 100644 --- a/apps/ui/src/@types/vite-env.d.ts +++ b/apps/ui/src/@types/vite-env.d.ts @@ -18,6 +18,7 @@ interface ImportMetaEnv { readonly REACT_APP_TWITTER_LINK: string readonly REACT_APP_YOUTUBE_LINK: string readonly REACT_APP_YOUTUBE_VIDEO_ID: string + readonly REACT_APP_YOUTUBE_VIDEO_DATA_SOURCE_ID: string readonly REACT_APP_TERMS_LINK: string readonly REACT_APP_PRIVACY: string readonly REACT_APP_BASICS_LINK: string diff --git a/apps/ui/src/Route.tsx b/apps/ui/src/Route.tsx index fa70ecdb2..706e7a008 100644 --- a/apps/ui/src/Route.tsx +++ b/apps/ui/src/Route.tsx @@ -93,6 +93,7 @@ import VoiceView from 'plugins/contact/pages/Voice/VoiceView' import VoiceModal from 'modals/VoiceModal' import ImportContacts from 'plugins/contact/pages/Contact/ImportContacts' import CallLogsModal from 'modals/CallLogsModal' +import VideoModal from 'modals/VideoModal' const Route = () => { const { loading } = useContext(AuthContext) @@ -379,6 +380,7 @@ const Route = () => { + void }) => { + return ( + + + + + ) +} + +export default DemoButton diff --git a/apps/ui/src/components/DemoButton/index.ts b/apps/ui/src/components/DemoButton/index.ts new file mode 100644 index 000000000..d81139fde --- /dev/null +++ b/apps/ui/src/components/DemoButton/index.ts @@ -0,0 +1 @@ +export { default } from './DemoButton' diff --git a/apps/ui/src/i18n/locales/en.json b/apps/ui/src/i18n/locales/en.json index 42ccfc477..64888d35f 100644 --- a/apps/ui/src/i18n/locales/en.json +++ b/apps/ui/src/i18n/locales/en.json @@ -354,5 +354,6 @@ "contacts": "$t(contact)s", "groups": "$t(group)s", "integrations": "$t(integration)s", - "models": "$t(model)s" + "models": "$t(model)s", + "type": "Type" } diff --git a/apps/ui/src/modals/AIChatModal/components/ChatMembers/ChatMembers.tsx b/apps/ui/src/modals/AIChatModal/components/ChatMembers/ChatMembers.tsx index e8799acfa..f3d51892b 100644 --- a/apps/ui/src/modals/AIChatModal/components/ChatMembers/ChatMembers.tsx +++ b/apps/ui/src/modals/AIChatModal/components/ChatMembers/ChatMembers.tsx @@ -80,29 +80,30 @@ const ChatMembers = ({
{voiceUrl && ( - - - - )} - - - openModal({ - name: CALL_LOGS_MODAL_NAME, - data: { - chatId: call?.chat_id, - }, - }) - } - > - + <> + + + {' '} + + openModal({ + name: CALL_LOGS_MODAL_NAME, + data: { + chatId: call?.chat_id, + }, + }) + } + > + - - + + + + )}
diff --git a/apps/ui/src/modals/AgentViewModal.tsx b/apps/ui/src/modals/AgentViewModal.tsx index 3daf80717..7bb1693dc 100644 --- a/apps/ui/src/modals/AgentViewModal.tsx +++ b/apps/ui/src/modals/AgentViewModal.tsx @@ -24,9 +24,9 @@ const AgentViewModal = ({ data }: AgentViewModalProps) => { const { id, agent } = data - const { data: agentObj } = useAgentByIdService({ id: agent.agent.id }) + const { data: agentObj } = useAgentByIdService({ id }) - const { data: agentById } = useDiscoverAgentByIdService({ id: id }) + const { data: agentById } = useDiscoverAgentByIdService({ id }) return ( <> diff --git a/apps/ui/src/modals/VideoModal.tsx b/apps/ui/src/modals/VideoModal.tsx new file mode 100644 index 000000000..a2e0de960 --- /dev/null +++ b/apps/ui/src/modals/VideoModal.tsx @@ -0,0 +1,68 @@ +import withRenderModal from 'hocs/withRenderModal' + +import Modal from '@l3-lib/ui-core/dist/Modal' + +import IconButton from '@l3-lib/ui-core/dist/IconButton' +import Close from '@l3-lib/ui-core/dist/icons/Close' + +import { useModal } from 'hooks' +import styled from 'styled-components' +import { StyledButtonWrapper } from './AgentViewModal' + +type VideoModalProps = { + data: { + videoSrc: string + } +} + +const VideoModal = ({ data }: VideoModalProps) => { + const { closeModal } = useModal() + + const { videoSrc } = data + + return ( + closeModal('video-modal')} + show + backgroundColor='dark' + hideCloseButton + > + + + + + + } + kind={IconButton.kinds.TERTIARY} + onClick={() => closeModal('video-modal')} + /> + + + ) +} + +export default withRenderModal('video-modal')(VideoModal) + +const StyledModalBody = styled.div` + padding-top: 10px; +` + +const StyledModal = styled(Modal)` + .components-Modal-Modal-module__overlay--OO00T { + backdrop-filter: unset; + } +` +const StyledIframe = styled.iframe` + border-radius: 10px; + margin: auto; +` diff --git a/apps/ui/src/pages/Agents/AgentForm/CreateAgentForm.tsx b/apps/ui/src/pages/Agents/AgentForm/CreateAgentForm.tsx index cce2b38ea..b8cbedd43 100644 --- a/apps/ui/src/pages/Agents/AgentForm/CreateAgentForm.tsx +++ b/apps/ui/src/pages/Agents/AgentForm/CreateAgentForm.tsx @@ -21,6 +21,9 @@ import { t } from 'i18next' import { StyledFormWrapper } from 'styles/formStyles.css' import { useGetAccountModule } from 'utils/useGetAccountModule' +import { StyledCombiner } from 'pages/Datasource/DatasourceForm/CreateDatasourceForm' +import AgentDemoButton from './components/AgentDemoButton' + const CreateAgentForm = () => { const { formik, isLoading } = useCreateAgent() @@ -34,7 +37,11 @@ const CreateAgentForm = () => {
- {`${t('add-agent')}`} + + {`${t('add-agent')}`} + + + {/* {`${t('agent-description')}`} */}
diff --git a/apps/ui/src/pages/Agents/AgentForm/CreateAgentTempate.tsx b/apps/ui/src/pages/Agents/AgentForm/CreateAgentTempate.tsx index 7d733b3a0..93328f092 100644 --- a/apps/ui/src/pages/Agents/AgentForm/CreateAgentTempate.tsx +++ b/apps/ui/src/pages/Agents/AgentForm/CreateAgentTempate.tsx @@ -20,6 +20,8 @@ import { useAgentTemplatesService } from 'services/discover/useAgentTemplatesSer import TypographyPrimary from 'components/Typography/Primary' import { useCreateAgent } from '../useCreateAgent' import { t } from 'i18next' +import { StyledCombiner } from 'pages/Datasource/DatasourceForm/CreateDatasourceForm' +import AgentDemoButton from './components/AgentDemoButton' const CreateAgentTemplate = () => { const { refetchAgent } = useCreateAgent() @@ -34,7 +36,11 @@ const CreateAgentTemplate = () => {
- {`${t('add-agent')}`} + + {`${t('add-agent')}`} + + + {/* Here are all your agents, managing tasks and operations. */} @@ -96,7 +102,7 @@ const StyledTemplatesWrapper = styled.div` height: calc(100vh - 225px); - max-height: 1000px; + max-height: 2500px; overflow-y: auto; padding: 0 20px; width: 100%; diff --git a/apps/ui/src/pages/Agents/AgentForm/EditAgentForm.tsx b/apps/ui/src/pages/Agents/AgentForm/EditAgentForm.tsx index f0df631dd..5a5d1c31b 100644 --- a/apps/ui/src/pages/Agents/AgentForm/EditAgentForm.tsx +++ b/apps/ui/src/pages/Agents/AgentForm/EditAgentForm.tsx @@ -18,6 +18,8 @@ import ComponentsWrapper from 'components/ComponentsWrapper/ComponentsWrapper' import { t } from 'i18next' import { StyledFormWrapper } from 'styles/formStyles.css' import { useGetAccountModule } from 'utils/useGetAccountModule' +import { StyledCombiner } from 'pages/Datasource/DatasourceForm/CreateDatasourceForm' +import AgentDemoButton from './components/AgentDemoButton' const EditAgentForm = () => { const { t } = useTranslation() @@ -32,10 +34,14 @@ const EditAgentForm = () => {
- {`${t('edit-agent')}`} {/* Here are all your agents, managing tasks and operations. */} + + {`${t('edit-agent')}`} + + +
diff --git a/apps/ui/src/pages/Agents/AgentForm/components/AgentDemoButton.tsx b/apps/ui/src/pages/Agents/AgentForm/components/AgentDemoButton.tsx new file mode 100644 index 000000000..0a9b9aa48 --- /dev/null +++ b/apps/ui/src/pages/Agents/AgentForm/components/AgentDemoButton.tsx @@ -0,0 +1,19 @@ +import DemoButton from 'components/DemoButton' +import { useModal } from 'hooks' + +const AgentDemoButton = () => { + const { openModal } = useModal() + + return ( + + openModal({ + name: 'video-modal', + data: { videoSrc: import.meta.env.REACT_APP_YOUTUBE_VIDEO_ID }, + }) + } + /> + ) +} + +export default AgentDemoButton diff --git a/apps/ui/src/pages/Agents/AgentView/AgentView.tsx b/apps/ui/src/pages/Agents/AgentView/AgentView.tsx index e61fc3ce3..5789a9aab 100644 --- a/apps/ui/src/pages/Agents/AgentView/AgentView.tsx +++ b/apps/ui/src/pages/Agents/AgentView/AgentView.tsx @@ -61,57 +61,33 @@ const AgentView = ({ agentData }: { agentData?: AgentWithConfigs }) => { {system_message?.length ? ( - + ) : null} {tools?.length > 0 && } {datasources?.length > 0 && } - {goals?.length > 0 && ( - - )} + {goals?.length > 0 && } {constraints?.length > 0 && ( - + )} {instructions?.length > 0 && ( - + )} {suggestions?.length > 0 && ( - + )} - {greeting?.length > 0 && } + {greeting?.length > 0 && ( + + )} {text?.length > 0 && ( - + )} diff --git a/apps/ui/src/pages/Agents/AgentView/components/AdditionalInfoBox.tsx b/apps/ui/src/pages/Agents/AgentView/components/AdditionalInfoBox.tsx index e70020051..8c87172ea 100644 --- a/apps/ui/src/pages/Agents/AgentView/components/AdditionalInfoBox.tsx +++ b/apps/ui/src/pages/Agents/AgentView/components/AdditionalInfoBox.tsx @@ -7,12 +7,33 @@ import TypographySecondary from 'components/Typography/Secondary' type AdditionalInfoBoxProps = { items: string[] title: string + noCount?: boolean } -const AdditionalInfoBox = ({ items, title }: AdditionalInfoBoxProps) => { +const AdditionalInfoBox = ({ items, title, noCount }: AdditionalInfoBoxProps) => { + const getCountOfNonEmptyItems = (items: string[]) => { + const nonEmptyItems = items.filter(item => item.length > 0) + return nonEmptyItems.length + } + const count = getCountOfNonEmptyItems(items) + let convertedTitle + if (noCount) { + convertedTitle = title + } else if (count === 1) { + convertedTitle = `1 ${title}` + } else { + convertedTitle = `${count} ${title}s` + } + + if (count === 0) return
+ return ( - + {items.map((item: string, index: number) => { return ( diff --git a/apps/ui/src/pages/Agents/AgentView/components/AgentDatasources.tsx b/apps/ui/src/pages/Agents/AgentView/components/AgentDatasources.tsx index f675643c7..6e399061f 100644 --- a/apps/ui/src/pages/Agents/AgentView/components/AgentDatasources.tsx +++ b/apps/ui/src/pages/Agents/AgentView/components/AgentDatasources.tsx @@ -20,6 +20,8 @@ const AgentDatasources = ({ datasources }: AgentDataSourcesProps) => { return datasources?.includes(id) }) + if (filteredDatasources?.length === 0) return
+ return ( { {items.map((item: string, index: number) => { + const { shortText: shortName } = textSlicer(item, 35) return ( diff --git a/apps/ui/src/pages/Datasource/DatasourceForm/CreateDatasourceForm.tsx b/apps/ui/src/pages/Datasource/DatasourceForm/CreateDatasourceForm.tsx index e4addb9a7..3a72faec6 100644 --- a/apps/ui/src/pages/Datasource/DatasourceForm/CreateDatasourceForm.tsx +++ b/apps/ui/src/pages/Datasource/DatasourceForm/CreateDatasourceForm.tsx @@ -3,6 +3,9 @@ import DatasourceForm from './DatasourceForm' import Button from '@l3-lib/ui-core/dist/Button' import Loader from '@l3-lib/ui-core/dist/Loader' +import Typography from '@l3-lib/ui-core/dist/Typography' + +import Play from '@l3-lib/ui-core/dist/icons/PlayOutline' import { StyledHeaderGroup, @@ -19,6 +22,9 @@ import { ButtonPrimary } from 'components/Button/Button' import { t } from 'i18next' import { StyledFormWrapper } from 'styles/formStyles.css' +import DatasourceDemoButton from './components/DatasourceDemoButton' +import styled from 'styled-components' + const CreateDatasourceForm = () => { const { formik, isLoading } = useCreateDatasource() @@ -29,9 +35,12 @@ const CreateDatasourceForm = () => {
{`${t('add-datasource')}`} - - {`${t('datasource-description')}`} - + + + {`${t('datasource-description')}`} + + +
@@ -58,3 +67,9 @@ const CreateDatasourceForm = () => { } export default CreateDatasourceForm + +export const StyledCombiner = styled.div` + display: flex; + align-items: center; + gap: 5px; +` diff --git a/apps/ui/src/pages/Datasource/DatasourceForm/EditDatasourceForm.tsx b/apps/ui/src/pages/Datasource/DatasourceForm/EditDatasourceForm.tsx index 6715041e0..24de1e9e5 100644 --- a/apps/ui/src/pages/Datasource/DatasourceForm/EditDatasourceForm.tsx +++ b/apps/ui/src/pages/Datasource/DatasourceForm/EditDatasourceForm.tsx @@ -19,6 +19,8 @@ import BackButton from 'components/BackButton' import { ButtonPrimary } from 'components/Button/Button' import { t } from 'i18next' import { StyledFormWrapper } from 'styles/formStyles.css' +import DatasourceDemoButton from './components/DatasourceDemoButton' +import { StyledCombiner } from './CreateDatasourceForm' const EditDatasourceForm = () => { const { formik, isLoading } = useEditDatasource() @@ -30,9 +32,12 @@ const EditDatasourceForm = () => {
{`${t('edit-datasource')}`} - - {`${t('datasource-description')}`} - + + + {`${t('datasource-description')}`} + + +
diff --git a/apps/ui/src/pages/Datasource/DatasourceForm/components/DataLoaderCard.tsx b/apps/ui/src/pages/Datasource/DatasourceForm/components/DataLoaderCard.tsx index 958d5a08e..f8184f790 100644 --- a/apps/ui/src/pages/Datasource/DatasourceForm/components/DataLoaderCard.tsx +++ b/apps/ui/src/pages/Datasource/DatasourceForm/components/DataLoaderCard.tsx @@ -69,4 +69,6 @@ const StyledIcon = styled.img` width: 24px; height: 24px; border-radius: 8px; + + object-fit: cover; ` diff --git a/apps/ui/src/pages/Datasource/DatasourceForm/components/DatasourceDemoButton.tsx b/apps/ui/src/pages/Datasource/DatasourceForm/components/DatasourceDemoButton.tsx new file mode 100644 index 000000000..206ce3cc0 --- /dev/null +++ b/apps/ui/src/pages/Datasource/DatasourceForm/components/DatasourceDemoButton.tsx @@ -0,0 +1,26 @@ +import DemoButton from 'components/DemoButton' +import { useModal } from 'hooks' +import styled from 'styled-components' + +const DatasourceDemoButton = () => { + const { openModal } = useModal() + + return ( + + + openModal({ + name: 'video-modal', + data: { videoSrc: import.meta.env.REACT_APP_YOUTUBE_VIDEO_DATA_SOURCE_ID }, + }) + } + /> + + ) +} + +export default DatasourceDemoButton + +const StyledCustomButtonWrapper = styled.div` + margin-right: auto; +` diff --git a/apps/ui/src/pages/Datasource/constants.ts b/apps/ui/src/pages/Datasource/constants.ts index a5aabd8fd..a7028ee4a 100644 --- a/apps/ui/src/pages/Datasource/constants.ts +++ b/apps/ui/src/pages/Datasource/constants.ts @@ -4,6 +4,8 @@ import fileImg from 'assets/images/file.jpg' import webImg from 'assets/images/web.jpg' import notionImg from 'assets/images/notion.png' import shopifyImg from 'assets/images/shopify.png' +import googleAnalyticsLogo from 'assets/images/googleAnalytics.png' +import firebaseLogo from 'assets/images/firebase.png' export const DATA_LOADER_IMAGES = [ { @@ -30,4 +32,12 @@ export const DATA_LOADER_IMAGES = [ sourceName: 'Shopify', imageSrc: shopifyImg, }, + { + sourceName: 'Google Analytics', + imageSrc: googleAnalyticsLogo, + }, + { + sourceName: 'Firebase', + imageSrc: firebaseLogo, + }, ] diff --git a/apps/ui/src/pages/Discover/Discover.tsx b/apps/ui/src/pages/Discover/Discover.tsx index 619e707c4..1acebca24 100644 --- a/apps/ui/src/pages/Discover/Discover.tsx +++ b/apps/ui/src/pages/Discover/Discover.tsx @@ -1,18 +1,61 @@ import styled from 'styled-components' import DiscoverTeamAgents from './components/DiscoverTeamAgents' import DiscoverTemplateAgents from './components/DiscoverTemplateAgents' -import HeadingPrimary from 'components/Heading/Primary' + +import { StyledTab, StyledTabListSpan, StyledTabListWrapper } from 'styles/tabStyles.css' + +import Tab from '@l3-lib/ui-core/dist/Tab' +import TabList from '@l3-lib/ui-core/dist/TabList' +import TabPanel from '@l3-lib/ui-core/dist/TabPanel' +import TabPanels from '@l3-lib/ui-core/dist/TabPanels' +import TabsContext from '@l3-lib/ui-core/dist/TabsContext' +import { t } from 'i18next' +import { useState } from 'react' +import { useLocation, useNavigate } from 'react-router-dom' + const Discover = () => { + const navigate = useNavigate() + + const location = useLocation() + const urlParams = new URLSearchParams(location.search) + const tabQuery = urlParams.get('tab') + + const defaultActiveTab = () => { + if (tabQuery === 'team') return 0 + if (tabQuery === 'agent') return 1 + } + + const [activeTab, setActiveTab] = useState(defaultActiveTab || 0) + const handleTabClick = (tabId: number, tabName: string) => { + setActiveTab(tabId) + navigate(`/discover?tab=${tabName}`) + } return ( - - {/* {} */} - - + + + handleTabClick(0, 'team')}> + {`${t('team')}s`} + + handleTabClick(1, 'agent')}> + {`${t('agent')}s`} + + + - + + + + + + + + + + + {/* {} */} {/* {!user && } */} @@ -21,23 +64,7 @@ const Discover = () => { export default Discover - - - export const StyledRoot = styled.div` display: flex; flex-direction: column; - gap: 100px; ` - -const StyledHeadingWrapper = styled.div` - display: flex; - flex-direction: column; - align-items: center; - - padding: 16px 10px; -` -const StyledHeadingPrimary = styled(HeadingPrimary)` - font-size: 40px; -` - diff --git a/apps/ui/src/pages/Discover/components/DiscoverTeamAgents.tsx b/apps/ui/src/pages/Discover/components/DiscoverTeamAgents.tsx index b2fc93e00..d23845874 100644 --- a/apps/ui/src/pages/Discover/components/DiscoverTeamAgents.tsx +++ b/apps/ui/src/pages/Discover/components/DiscoverTeamAgents.tsx @@ -9,7 +9,7 @@ import { StyledSectionWrapper, } from 'pages/Home/homeStyle.css' import TeamOfAgentsCard from 'pages/TeamOfAgents/TeamOfAgentsCard' -import { useNavigate, useLocation} from 'react-router-dom' +import { useNavigate, useLocation } from 'react-router-dom' import { useTeamOfAgentsPublicService } from 'services/team/useTeamOfAgentsPublicService' import TypographySecondary from 'components/Typography/Secondary' import Typography from '@l3-lib/ui-core/dist/Typography' @@ -25,13 +25,10 @@ const DiscoverTeamAgents = () => { const { data: publicTeamAgents } = useTeamOfAgentsPublicService() const location = useLocation() - return ( - - - + { const { templateAgents } = useDiscover() return ( - <> + <> {/* {} */} {templateAgents?.length > 0 && ( - + - + {templateAgents?.map((agentObj: any, index: number) => { const { agent } = agentObj @@ -62,7 +65,7 @@ const Discover = () => { /> ) })} - + )} @@ -72,8 +75,17 @@ const Discover = () => { export default Discover - - +export const StyledTabCardsWrapper = styled.div` + display: flex; + align-items: center; + flex-wrap: wrap; + gap: 16px; + width: 100%; + max-height: calc(100vh - 370px); + height: 100%; + overflow-y: auto; + padding: 5px 32px; +` export const StyledRoot = styled.div` display: flex; @@ -91,4 +103,3 @@ const StyledHeadingWrapper = styled.div` const StyledHeadingPrimary = styled(HeadingPrimary)` font-size: 40px; ` - diff --git a/apps/ui/src/pages/Home/Home.tsx b/apps/ui/src/pages/Home/Home.tsx index 1ad1622c3..f934b5d98 100644 --- a/apps/ui/src/pages/Home/Home.tsx +++ b/apps/ui/src/pages/Home/Home.tsx @@ -8,13 +8,10 @@ import styled from 'styled-components' import Agents from 'pages/Agents' import { AuthContext } from 'contexts' -import Discover from 'pages/Discover' -import GetStartedCard from './GetStarted/GetStartedCard' -import cardBg4 from 'assets/images/whiteBg.png' import DiscoverTeamAgents from 'pages/Discover/components/DiscoverTeamAgents' import DiscoverTemplateAgents from 'pages/Discover/components/DiscoverTemplateAgents' -import DiscoverSystemAgents from 'pages/Discover/components/DiscoverSystemAgents' + import TeamOfAgents from 'pages/TeamOfAgents' import { useTeamOfAgents } from 'pages/TeamOfAgents/useTeamOfAgents' import { useAgents } from 'pages/Agents/useAgents' @@ -39,26 +36,19 @@ const Home = () => { {!user && } {user ? ( <> - {/* */} - {agentModules?.list && agentsData?.length > 0 ? : } - {teamModules?.list && (teamOfAgents?.length > 0 ? : )} - + + {agentModules?.list && agentsData?.length > 0 ? ( + + ) : ( + + )} ) : ( <> - {/* */} - { allowFullScreen > - + + )} - - {/* {user ? ( - <> - - - - - ) : ( - - )} */} - {/* - - */} ) @@ -95,7 +73,7 @@ export default Home const StyledInnerWrapperEdit = styled(StyledInnerWrapper)` display: grid; grid-auto-rows: max-content; - gap: 20px; + gap: 30px; ` const StyledWrapper = styled.div` diff --git a/apps/ui/src/pages/Sessions/columnConfig.tsx b/apps/ui/src/pages/Sessions/columnConfig.tsx index e5ba48e00..ad5cd50f4 100644 --- a/apps/ui/src/pages/Sessions/columnConfig.tsx +++ b/apps/ui/src/pages/Sessions/columnConfig.tsx @@ -144,6 +144,17 @@ const columns = [ accessor: 'sender_name', minWidth: 343, width: '24.8%', + Cell: (props: { row: { original: any } }) => { + const { original: data } = props.row + + if (data.voice_url !== null) { + const audioUrl = data.voice_url + + return + } + + return null + }, }, // { // Header: 'Schedule Name', @@ -167,6 +178,7 @@ const columns = [ Cell: (props: { row: { original: any } }) => { const { original: data } = props.row const { refetch: refetchChat } = useChatsService() + const { deleteChat } = useDeleteChatService() const { openModal, closeModal } = useModal() const { setToast } = useContext(ToastContext) diff --git a/apps/ui/src/pages/Sessions/useSession.ts b/apps/ui/src/pages/Sessions/useSession.ts index b36aac408..4f071c779 100644 --- a/apps/ui/src/pages/Sessions/useSession.ts +++ b/apps/ui/src/pages/Sessions/useSession.ts @@ -8,6 +8,7 @@ import { AgentWithConfigs, ScheduleWithConfigs } from 'types' type Chat = { id: string name: string + voice_url: string agent?: { agent?: { name: string @@ -41,6 +42,7 @@ export const useSession = () => { agent_id: chat?.agent?.agent?.id, team_name: chat?.team?.team?.name, added_At: new Date().toISOString(), + voice_url: chat?.voice_url, })) const [startDate, setStartDate] = useState(null) diff --git a/apps/ui/src/pages/TeamOfAgents/TeamOfAgentView.tsx b/apps/ui/src/pages/TeamOfAgents/TeamOfAgentView.tsx index bc3928c2c..f3ad0d68f 100644 --- a/apps/ui/src/pages/TeamOfAgents/TeamOfAgentView.tsx +++ b/apps/ui/src/pages/TeamOfAgents/TeamOfAgentView.tsx @@ -145,46 +145,26 @@ const TeamOfAgentView = ({ teamOfAgentsData }: { teamOfAgentsData?: any }) => { {datasources?.length > 0 && } - {goals?.length > 0 && ( - - )} + {goals?.length > 0 && } {constraints?.length > 0 && ( - + )} {instructions?.length > 0 && ( - + )} {suggestions?.length > 0 && ( - + )} - {greeting?.length > 0 && } + {greeting?.length > 0 && ( + + )} {text?.length > 0 && ( - + )} diff --git a/apps/ui/src/pages/TeamOfAgents/TeamOfAgentsForm/TeamOfAgentsForm.tsx b/apps/ui/src/pages/TeamOfAgents/TeamOfAgentsForm/TeamOfAgentsForm.tsx index b6935857a..ef284f31c 100644 --- a/apps/ui/src/pages/TeamOfAgents/TeamOfAgentsForm/TeamOfAgentsForm.tsx +++ b/apps/ui/src/pages/TeamOfAgents/TeamOfAgentsForm/TeamOfAgentsForm.tsx @@ -198,7 +198,7 @@ const TeamOfAgentsForm = ({ formik, isLoading }: TeamOfAgentsFormProps) => { fieldName={'team_greeting'} /> - { /> - )} + )} */}
diff --git a/apps/ui/src/pages/TeamOfAgents/useCreateTeamOfAgents.ts b/apps/ui/src/pages/TeamOfAgents/useCreateTeamOfAgents.ts index d357f3aeb..6a5686cbe 100644 --- a/apps/ui/src/pages/TeamOfAgents/useCreateTeamOfAgents.ts +++ b/apps/ui/src/pages/TeamOfAgents/useCreateTeamOfAgents.ts @@ -23,7 +23,7 @@ export const useCreateTeamOfAgents = () => { const initialValues = { teamOfAgents_name: '', teamOfAgents_description: '', - teamOfAgents_team_type: 'Plan and Execute', + teamOfAgents_team_type: 'Decentralized Speaker', agents: [], is_memory: true, // TODO: add agents selected in form diff --git a/apps/ui/src/plugins/contact/pages/Contact/Contacts.tsx b/apps/ui/src/plugins/contact/pages/Contact/Contacts.tsx index 68acac112..c106a308c 100644 --- a/apps/ui/src/plugins/contact/pages/Contact/Contacts.tsx +++ b/apps/ui/src/plugins/contact/pages/Contact/Contacts.tsx @@ -175,7 +175,7 @@ const Contacts = () => { }, }, ], - [], + [agentsData], ) const location = useLocation() diff --git a/apps/ui/src/plugins/contact/pages/Voice/VoiceView/useVoiceView.ts b/apps/ui/src/plugins/contact/pages/Voice/VoiceView/useVoiceView.ts index afe04b347..61f401d17 100644 --- a/apps/ui/src/plugins/contact/pages/Voice/VoiceView/useVoiceView.ts +++ b/apps/ui/src/plugins/contact/pages/Voice/VoiceView/useVoiceView.ts @@ -4,7 +4,7 @@ import { useVoicesService } from 'plugins/contact/services/voice/useVoicesServic import { useContext, useState } from 'react' import { useParams } from 'react-router-dom' import { useConfigsService } from 'services/config/useConfigsService' -import { useCreateConfigService } from 'services/config/useCreateConfigService' +import { ConfigInput, useCreateConfigService } from 'services/config/useCreateConfigService' import { useUpdateConfigService } from 'services/config/useUpdateConfigService' export const useVoiceView = ({ voiceSlug }: { voiceSlug?: string }) => { @@ -43,10 +43,10 @@ export const useVoiceView = ({ voiceSlug }: { voiceSlug?: string }) => { const handleSubmit = async (values: any) => { setIsLoading(true) - const configs = [] + const configs: ConfigInput[] = [] for (const key in values) { - const value = values[key] + const value = values[key] || '' const field = voice?.fields.find((field: any) => field.key === key) configs.push({ @@ -60,17 +60,18 @@ export const useVoiceView = ({ voiceSlug }: { voiceSlug?: string }) => { } try { - if (filteredConfig.length === 0) { - const promises = configs.map((config: any) => createConfig(config)) - await Promise.all(promises) - } else { - const promises = configs.map((config: any) => - updateConfig(filteredConfig.find((cfg: any) => cfg.key === config.key).id, config), - ) - - await Promise.all(promises) - } + const promises = voice?.fields.map((field: any) => { + const existingConfig = filteredConfig?.find((config: any) => config.key === field.key) + const config = configs.find((config: any) => config.key === field.key) + + if (!config) return + if (!existingConfig) return createConfig(config) + return updateConfig(existingConfig.id, config) + }) + + await Promise.all(promises) await refetchConfigs() + setToast({ message: 'Voice was updated!', type: 'positive', diff --git a/apps/ui/src/styles/formStyles.css.ts b/apps/ui/src/styles/formStyles.css.ts index 53e336771..24c783572 100644 --- a/apps/ui/src/styles/formStyles.css.ts +++ b/apps/ui/src/styles/formStyles.css.ts @@ -3,7 +3,7 @@ import styled from 'styled-components' export const StyledFormWrapper = styled.div` width: 100%; - height: calc(100vh - 250px); + height: calc(100vh - 260px); max-height: 1500px; ` diff --git a/zep/docker-compose.yml b/zep/docker-compose.yml index c9e774bc8..1484cc77b 100644 --- a/zep/docker-compose.yml +++ b/zep/docker-compose.yml @@ -5,15 +5,20 @@ services: image: ghcr.io/getzep/zep-cloud:0.19 restart: on-failure ports: - - "8000:8000" + - "80:8000" environment: - PORT=8000 - - ZEP_SERVER_WEB_ENABLED=true + - ZEP_AUTH_REQUIRED=true + - ZEP_AUTH_SECRET= + - ZEP_NLP_SERVER_URL=http://zep_nlp:5557 + - ZEP_OPENAI_API_KEY= + - ZEP_SERVER_WEB_ENABLED=false + - ZEP_STORE_POSTGRES_DSN=postgres://postgres:password@localhost:5432/db zep_nlp: image: ghcr.io/getzep/zep-nlp-server:0.4.1 - env_file: - - .env + environment: + - ZEP_OPENAI_API_KEY= restart: on-failure healthcheck: test: timeout 10s bash -c ':> /dev/tcp/127.0.0.1/5557' || exit 1