diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 000000000..e8036609f --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,70 @@ +# ⚡ Contributing to SuperAGI +

+ +

+ +First of all, thank you for taking your time to to contribute to this project. We truly appreciate your contributions, whether it's bug reports, feature suggestions, or pull requests. Your time and effort are highly valued in this project. 🚀 + +This document provides guidelines and best practices to help you to contribute effectively. These are meant to serve as guidelines, not strict rules. We encourage you to use your best judgment and feel comfortable proposing changes to this document through a pull request. + +**********************************Table of Content:********************************** +1. [Code of conduct](https://github.com/Phoenix2809/SuperAGI/blob/contributing-md/CONTRIBUTING.md#code-of-conduct) +2. [Getting Started](https://github.com/Phoenix2809/SuperAGI/blob/contributing-md/CONTRIBUTING.md#getting-started) +3. [How can I contribute](https://github.com/Phoenix2809/SuperAGI/blob/contributing-md/CONTRIBUTING.md#getting-started) + 1. [Reporting Bugs](https://github.com/Phoenix2809/SuperAGI/blob/contributing-md/CONTRIBUTING.md#reporting-bugs) + 2. [Suggesting Enhancements](https://github.com/Phoenix2809/SuperAGI/blob/contributing-md/CONTRIBUTING.md#suggesting-enhancements) + 3. [Pull Requests](https://github.com/Phoenix2809/SuperAGI/blob/contributing-md/CONTRIBUTING.md#pull-requests) +4. Styleguides +5. Testing + +## Code of Conduct: + +Please read our [Code of Conduct](https://github.com/TransformerOptimus/SuperAGI/blob/main/CODE_OF_CONDUCT.md) to understand the expectations we have for all contributors participating in this project. By participating, you agree to abide by our Code of Conduct. + +## Getting Started + +1. Create a fork of this repository and clone your fork +2. Create a new branch for your changes (make sure you’re using a descriptive name, such as bug-fix-293 +3. Make the respective changes in your new branch +4. Test your changes thoroughly +5. Commit and push your changes to your fork +6. Create a pull request. Please refer to the Submitting Pull Requests section for guidelines. + +## How can I contribute + +### Reporting Bugs + +You can start contributing to SuperAGI by reporting bugs that you’ve encountered. Please create an issue on GitHub with the following information: + +1. Title describing the issue in a clear and concise manner +2. Provide a detailed description of the problem, along with the necessary steps to reproduce the issue. +3. Make sure to include any relevant logs, screenshots, or other helpful information that supports the issue. + +### Suggesting Enhancements + +You can start adding ideas for new features or improvements to SuperAGI. Create an issue on Github with the following information: + +1. Title describing the issue in a clear and concise manner +2. Please provide a clear description of the proposed enhancement, highlighting its benefits and potential drawbacks. +3. Provide example and supporting information. + +### Pull Requests + +When submitting your pull request, please ensure that your changes meet the following criteria: + +1. The pull request is atomic and focuses on a single change. +2. You have read the contributing guide and your code conforms to the guidelines. +3. You have documented your changes clearly and comprehensively. +4. You have added the required tests. + + +## Styleguides + +will need extensive Developer KT on this + +## Code Formatting +Pre-commit Hooks + +## Testing Changes + +Will need Dev KT on filling this documentation diff --git a/docker-compose.yaml b/docker-compose.yaml index 69b8fb1e6..afaff531c 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -27,9 +27,10 @@ services: - NEXT_PUBLIC_API_BASE_URL=/api networks: - super_network - volumes: - - ./gui:/app - - /app/.next +# volumes: +# - ./gui:/app +# - /app/node_modules/ +# - /app/.next/ super__redis: image: "docker.io/library/redis:latest" networks: diff --git a/gui/Dockerfile b/gui/Dockerfile index 48365d6b9..e6a63f58d 100644 --- a/gui/Dockerfile +++ b/gui/Dockerfile @@ -5,6 +5,9 @@ WORKDIR /app COPY package*.json ./ RUN npm ci +FROM node:lts AS builder +WORKDIR /app COPY . . +COPY --from=deps /app/node_modules ./node_modules CMD ["npm", "run", "dev"] \ No newline at end of file diff --git a/local-llm-gpu b/local-llm-gpu index dceffd3d8..efa81264e 100644 --- a/local-llm-gpu +++ b/local-llm-gpu @@ -42,14 +42,16 @@ services: super__tgwui: build: - context: . + context: ./tgwui/ target: llama-cublas - dockerfile: ./tgwui/DockerfileTGWUI + dockerfile: DockerfileTGWUI # args: # - LCL_SRC_DIR=text-generation-webui # Developers - see Dockerfile app_base + image: atinoda/text-generation-webui:llama-cublas # Specify variant as the :tag container_name: super__tgwui environment: - - EXTRA_LAUNCH_ARGS="--listen --no-mmap --verbose --extensions openai --auto-devices --n_ctx 1600 --gpu-memory 20 20 --n-gpu-layers 128 --threads 8 --model vicuna-13b-cot.ggmlv3.q8_0.bin" + - EXTRA_LAUNCH_ARGS="--no-mmap --verbose --extensions openai --auto-devices --n_ctx 2000 --gpu-memory 22 22 --n-gpu-layers 128 --threads 8" +# - BUILD_EXTENSIONS_LIVE="silero_tts whisper_stt" # Install named extensions during every container launch. THIS WILL SIGNIFICANLTLY SLOW LAUNCH TIME. ports: - 7860:7860 # Default web port - 5000:5000 # Default API port @@ -62,7 +64,7 @@ services: - ./tgwui/config/prompts:/app/prompts - ./tgwui/config/softprompts:/app/softprompts - ./tgwui/config/training:/app/training - - ./tgwui/config/embeddings:/app/embeddings +# - ./config/extensions:/app/extensions logging: driver: json-file options: @@ -70,7 +72,6 @@ services: max-size: '10m' networks: - super_network -### Uncomment the following lines to run the container using the host machine's GPU resources deploy: resources: reservations: @@ -79,8 +80,6 @@ services: # count: "all" device_ids: ['0', '1'] # must comment the above line if this line is uncommented. capabilities: [gpu] - - super__redis: image: "docker.io/library/redis:latest" networks: diff --git a/superagi/controllers/tool_config.py b/superagi/controllers/tool_config.py index 8f2c38dbc..709b15bf4 100644 --- a/superagi/controllers/tool_config.py +++ b/superagi/controllers/tool_config.py @@ -1,19 +1,19 @@ -from fastapi import APIRouter, HTTPException, Depends, Path +from fastapi import APIRouter, HTTPException, Depends +from fastapi_jwt_auth import AuthJWT from fastapi_sqlalchemy import db from pydantic_sqlalchemy import sqlalchemy_to_pydantic + +from superagi.helper.auth import check_auth +from superagi.helper.auth import get_user_organisation from superagi.models.organisation import Organisation from superagi.models.tool_config import ToolConfig from superagi.models.toolkit import Toolkit -from fastapi_jwt_auth import AuthJWT -from superagi.helper.auth import check_auth -from superagi.helper.auth import get_user_organisation -from typing import List router = APIRouter() @router.post("/add/{toolkit_name}", status_code=201) -def update_tool_config(toolkit_name: str, configs: list): +def update_tool_config(toolkit_name: str, configs: list, organisation: Organisation = Depends(get_user_organisation)): """ Update tool configurations for a specific tool kit. @@ -34,7 +34,7 @@ def update_tool_config(toolkit_name: str, configs: list): try: # Check if the tool kit exists - toolkit = Toolkit.get_toolkit_from_name(db.session, toolkit_name) + toolkit = Toolkit.get_toolkit_from_name(db.session, toolkit_name,organisation) if toolkit is None: raise HTTPException(status_code=404, detail="Tool kit not found") @@ -114,12 +114,11 @@ def get_all_tool_configs(toolkit_name: str, organisation: Organisation = Depends HTTPException (status_code=404): If the specified tool kit is not found. HTTPException (status_code=403): If the user is not authorized to access the tool kit. """ - user_toolkits = db.session.query(Toolkit).filter(Toolkit.organisation_id == organisation.id).all() - toolkit = db.session.query(Toolkit).filter_by(name=toolkit_name).first() + + toolkit = db.session.query(Toolkit).filter(Toolkit.name == toolkit_name, + Toolkit.organisation_id == organisation.id).first() if not toolkit: raise HTTPException(status_code=404, detail='ToolKit not found') - if toolkit.name not in [user_toolkit.name for user_toolkit in user_toolkits]: - raise HTTPException(status_code=403, detail='Unauthorized') tool_configs = db.session.query(ToolConfig).filter(ToolConfig.toolkit_id == toolkit.id).all() return tool_configs diff --git a/superagi/jobs/agent_executor.py b/superagi/jobs/agent_executor.py index 53ecdc33a..11c52a709 100644 --- a/superagi/jobs/agent_executor.py +++ b/superagi/jobs/agent_executor.py @@ -44,7 +44,7 @@ def __init__(self, session=None, toolkit_id=None): def get_tool_config(self, key: str): tool_config = self.session.query(ToolConfig).filter_by(key=key, toolkit_id=self.toolkit_id).first() - if tool_config: + if tool_config and tool_config.value: return tool_config.value return super().get_tool_config(key=key) @@ -77,8 +77,11 @@ def create_object(tool,session): """ file_name = AgentExecutor.validate_filename(filename=tool.file_name) - tools_dir = get_config("TOOLS_DIR").rstrip("/") - module_name = ".".join(tools_dir.split("/") + [tool.folder_name, file_name]) + tools_dir = get_config("TOOLS_DIR") + if tools_dir is None: + tools_dir = "superagi/tools" + parsed_tools_dir = tools_dir.rstrip("/") + module_name = ".".join(parsed_tools_dir.split("/") + [tool.folder_name, file_name]) # module_name = f"superagi.tools.{folder_name}.{file_name}" diff --git a/superagi/models/agent_config.py b/superagi/models/agent_config.py index bf5d72bd9..eb00eecf8 100644 --- a/superagi/models/agent_config.py +++ b/superagi/models/agent_config.py @@ -7,7 +7,7 @@ class AgentConfiguration(DBBaseModel): """ - Represents a configuration for an agent. + Agent related configurations like goals, instructions, constraints and tools are stored here Attributes: id (int): The unique identifier of the agent configuration. diff --git a/superagi/models/agent_execution.py b/superagi/models/agent_execution.py index 0419c322e..17a6561fd 100644 --- a/superagi/models/agent_execution.py +++ b/superagi/models/agent_execution.py @@ -8,7 +8,7 @@ class AgentExecution(DBBaseModel): """ - Represents an execution of an agent. + Represents single agent run Attributes: id (int): The unique identifier of the agent execution. diff --git a/superagi/models/agent_execution_feed.py b/superagi/models/agent_execution_feed.py index 98acf5d26..d6dbd8c8c 100644 --- a/superagi/models/agent_execution_feed.py +++ b/superagi/models/agent_execution_feed.py @@ -6,7 +6,7 @@ class AgentExecutionFeed(DBBaseModel): """ - Represents a feed entry for an agent execution. + Feed of the agent execution. Attributes: id (int): The unique identifier of the agent execution feed. diff --git a/superagi/models/agent_execution_permission.py b/superagi/models/agent_execution_permission.py index 32719a49c..1f6f84dbb 100644 --- a/superagi/models/agent_execution_permission.py +++ b/superagi/models/agent_execution_permission.py @@ -6,7 +6,7 @@ class AgentExecutionPermission(DBBaseModel): """ - Represents an Agent Execution Permission record in the database. + Agent Execution Permissions at each step to be approved or rejected by the user. Attributes: id (Integer): The primary key of the agent execution permission record. diff --git a/superagi/models/agent_template.py b/superagi/models/agent_template.py index ea683e6f0..55adc9170 100644 --- a/superagi/models/agent_template.py +++ b/superagi/models/agent_template.py @@ -13,7 +13,7 @@ class AgentTemplate(DBBaseModel): """ - Represents a preconfigured agent template. + Preconfigured agent templates that can be used to create agents. Attributes: id (int): The unique identifier of the agent template. diff --git a/superagi/models/agent_template_config.py b/superagi/models/agent_template_config.py index 0056d8c5d..e5bbdaa9f 100644 --- a/superagi/models/agent_template_config.py +++ b/superagi/models/agent_template_config.py @@ -7,7 +7,7 @@ class AgentTemplateConfig(DBBaseModel): """ - Represents the configuration settings for an agent template. + Agent template related configurations like goals, instructions, constraints and tools are stored here Attributes: id (int): The unique identifier of the agent template config. diff --git a/superagi/models/agent_workflow.py b/superagi/models/agent_workflow.py index 1cd235f80..795c77af7 100644 --- a/superagi/models/agent_workflow.py +++ b/superagi/models/agent_workflow.py @@ -8,7 +8,7 @@ class AgentWorkflow(DBBaseModel): """ - Represents an agent workflow. + Agent workflows which runs part of each agent execution step Attributes: id (int): The unique identifier of the agent workflow. diff --git a/superagi/models/agent_workflow_step.py b/superagi/models/agent_workflow_step.py index b287e13f0..7466d54cf 100644 --- a/superagi/models/agent_workflow_step.py +++ b/superagi/models/agent_workflow_step.py @@ -7,7 +7,7 @@ class AgentWorkflowStep(DBBaseModel): """ - Represents a step in an agent workflow. + Step of an agent workflow Attributes: id (int): The unique identifier of the agent workflow step. diff --git a/superagi/models/configuration.py b/superagi/models/configuration.py index 70cc92076..2193e941d 100644 --- a/superagi/models/configuration.py +++ b/superagi/models/configuration.py @@ -4,7 +4,7 @@ class Configuration(DBBaseModel): """ - Model representing a configuration. + General org level configurations are stored here Attributes: id (Integer): The primary key of the configuration. diff --git a/superagi/models/toolkit.py b/superagi/models/toolkit.py index 522e69c43..c52f179d5 100644 --- a/superagi/models/toolkit.py +++ b/superagi/models/toolkit.py @@ -6,13 +6,13 @@ from superagi.models.base_model import DBBaseModel -# marketplace_url = "https://app.superagi.com/api" -marketplace_url = "http://localhost:8001" +marketplace_url = "https://app.superagi.com/api" +# marketplace_url = "http://localhost:8001" class Toolkit(DBBaseModel): """ - ToolKit - used to store tool kits + ToolKit - Used to group tools together Attributes: id(int) : id of the tool kit name(str) : name of the tool kit @@ -112,8 +112,8 @@ def fetch_marketplace_detail(cls, search_str, toolkit_name): return None @staticmethod - def get_toolkit_from_name(session, toolkit_name): - toolkit = session.query(Toolkit).filter_by(name=toolkit_name).first() + def get_toolkit_from_name(session, toolkit_name, organisation): + toolkit = session.query(Toolkit).filter_by(name=toolkit_name, organisation_id=organisation.id).first() if toolkit: return toolkit return None diff --git a/superagi/tools/base_tool.py b/superagi/tools/base_tool.py index 54aa49ac0..4f52f3d11 100644 --- a/superagi/tools/base_tool.py +++ b/superagi/tools/base_tool.py @@ -58,7 +58,7 @@ def create_function_schema( class BaseToolkitConfiguration: - def get_tool_config(key: str): + def get_tool_config(self, key: str): # Default implementation of the tool configuration retrieval logic with open("config.yaml") as file: config = yaml.safe_load(file) diff --git a/superagi/tools/code/write_code.py b/superagi/tools/code/write_code.py index 97b1bb12e..2b29d6f0d 100644 --- a/superagi/tools/code/write_code.py +++ b/superagi/tools/code/write_code.py @@ -59,7 +59,7 @@ def _execute(self, code_description: str) -> str: code_file_name: The name of the file where the generated codes will be saved. Returns: - Generated codes files or error message. + Generated code with where the code is being saved or error message. """ prompt = PromptReader.read_tools_prompt(__file__, "write_code.txt") + "\nUseful to know:\n" + PromptReader.read_tools_prompt(__file__, "generate_logic.txt") prompt = prompt.replace("{goals}", AgentPromptBuilder.add_list_items_to_string(self.goals)) diff --git a/superagi/tools/email/read_email.py b/superagi/tools/email/read_email.py index 34675f8d4..702444f71 100644 --- a/superagi/tools/email/read_email.py +++ b/superagi/tools/email/read_email.py @@ -40,7 +40,7 @@ def _execute(self, imap_folder: str = "INBOX", page: int = 0, limit: int = 5) -> limit : Number of emails to fetch in one cycle. Defaults to 5. Returns: - email content or error message + email contents or error message. """ email_sender = self.get_tool_config('EMAIL_ADDRESS') email_password = self.get_tool_config('EMAIL_PASSWORD') diff --git a/superagi/tools/email/send_email.py b/superagi/tools/email/send_email.py index bfd506e3d..2aa55cde7 100644 --- a/superagi/tools/email/send_email.py +++ b/superagi/tools/email/send_email.py @@ -38,7 +38,7 @@ def _execute(self, to: str, subject: str, body: str) -> str: body : The body of the email. Returns: - + success or error message. """ email_sender = self.get_tool_config('EMAIL_ADDRESS') email_password = self.get_tool_config('EMAIL_PASSWORD') diff --git a/superagi/tools/email/send_email_attachment.py b/superagi/tools/email/send_email_attachment.py index eeb6ac275..2a659d1b4 100644 --- a/superagi/tools/email/send_email_attachment.py +++ b/superagi/tools/email/send_email_attachment.py @@ -42,7 +42,7 @@ def _execute(self, to: str, subject: str, body: str, filename: str) -> str: filename : The name of the file to be sent as an attachment with the email. Returns: - + success or failure message """ input_root_dir = self.get_tool_config('RESOURCES_INPUT_ROOT_DIR') output_root_dir = self.get_tool_config('RESOURCES_OUTPUT_ROOT_DIR') diff --git a/superagi/tools/file/append_file.py b/superagi/tools/file/append_file.py index 94348d58c..cf6eb24ce 100644 --- a/superagi/tools/file/append_file.py +++ b/superagi/tools/file/append_file.py @@ -37,7 +37,7 @@ def _execute(self, file_name: str, content: str): content : The text to append to the file. Returns: - file written to successfully. or error message. + success or error message. """ final_path = ResourceHelper.get_root_output_dir() + file_name if "{agent_id}" in final_path: diff --git a/superagi/tools/file/delete_file.py b/superagi/tools/file/delete_file.py index d5883b480..5b4dae509 100644 --- a/superagi/tools/file/delete_file.py +++ b/superagi/tools/file/delete_file.py @@ -35,7 +35,7 @@ def _execute(self, file_name: str): file_name : The name of the file to delete. Returns: - file deleted successfully. or error message. + success or error message. """ final_path = ResourceHelper.get_root_output_dir() if "{agent_id}" in final_path: diff --git a/superagi/tools/file/read_file.py b/superagi/tools/file/read_file.py index 9b6de62bd..47cb23096 100644 --- a/superagi/tools/file/read_file.py +++ b/superagi/tools/file/read_file.py @@ -36,7 +36,7 @@ def _execute(self, file_name: str): file_name : The name of the file to read. Returns: - The file content + The file content and the file name """ output_root_dir = ResourceHelper.get_root_output_dir() diff --git a/superagi/tools/file/write_file.py b/superagi/tools/file/write_file.py index b75ee21fe..93e979c00 100644 --- a/superagi/tools/file/write_file.py +++ b/superagi/tools/file/write_file.py @@ -45,6 +45,6 @@ def _execute(self, file_name: str, content: str): content : The text to write to the file. Returns: - file written to successfully. or error message. + success message if message is file written successfully or failure message if writing file fails. """ return self.resource_manager.write_file(file_name, content) diff --git a/superagi/tools/github/add_file.py b/superagi/tools/github/add_file.py index caf89de10..197c89ecd 100644 --- a/superagi/tools/github/add_file.py +++ b/superagi/tools/github/add_file.py @@ -66,7 +66,7 @@ def _execute(self, repository_name: str, base_branch: str, body: str, commit_mes folder_path : The path of the folder to add the file to. Returns: - Pull request to add file/folder has been created. or error message. + Pull request success message if pull request is created successfully else error message. """ try: github_access_token = self.get_tool_config("GITHUB_ACCESS_TOKEN") diff --git a/superagi/tools/github/delete_file.py b/superagi/tools/github/delete_file.py index d940704a9..d90153bca 100644 --- a/superagi/tools/github/delete_file.py +++ b/superagi/tools/github/delete_file.py @@ -61,7 +61,7 @@ def _execute(self, repository_name: str, base_branch: str, file_name: str, commi folder_path : The path of the folder to delete the file from. Returns: - pull request deletion message. or error message + success message mentioning the pull request name for the delete file operation. or error message. """ try: diff --git a/superagi/tools/github/search_repo.py b/superagi/tools/github/search_repo.py index 4c5c86800..88919ed85 100644 --- a/superagi/tools/github/search_repo.py +++ b/superagi/tools/github/search_repo.py @@ -50,7 +50,7 @@ def _execute(self, repository_owner: str, repository_name: str, file_name: str, folder_path : The path of the folder to search the file in. Returns: - The content of the file. + The content of the github file. """ github_access_token = self.get_tool_config("GITHUB_ACCESS_TOKEN") github_username = self.get_tool_config("GITHUB_USERNAME") diff --git a/superagi/tools/google_calendar/README.md b/superagi/tools/google_calendar/README.md new file mode 100644 index 000000000..58751f04b --- /dev/null +++ b/superagi/tools/google_calendar/README.md @@ -0,0 +1,105 @@ +

+ +

+ +# SuperAGI - Google Calendar Toolkit + +Introducing the Google Calendar Toolkit, a powerful integration for SuperAGI. With the Gogole Calendar toolkit, you gain the ability to do the following: + +1. **Create Calendar Events** +2. **List your Calendar Events** +3. **Fetch an event from your Calendar** +4. **Delete Calendar Events** + +# ⚙️ Installation + +### ⚒️ Setting up of SuperAGI + +Set-up SuperAGI by following the instructions given [here](https://github.com/TransformerOptimus/SuperAGI/blob/main/README.MD) + +# ✅ Quick start Guide: + +In order to get started with integrating Google Calendar with SuperAGI, you need to do the following: + +## API Creation and OAuth Consent Screen + +1. Go to Google Developer Console: +[https://console.cloud.google.com/](https://console.cloud.google.com/) & Create a new project. If you’re having an existing project, you can proceed with that as well: + +![GC1](README/GC1.png) + +2. After the project is created/you’re in your selected project, head to “APIs and Services” + +![GC2](README/GC2.png) + +3. Click on “ENABLED APIS AND SERVICES” and search for “Google Calendar” + +![GC3](README/GC3.png) + +![GC4](README/GC4.png) + +4. Enable the API + +![GC5](README/GC5.png) + +5. Once the API is Enabled, go to “OAuth Consent Screen” + +![GC6](README/GC6.png) + +6. Select your User Type as “External” and click on "Create" + +![GC7](README/GC7.png) + +7. Fill in the required details such as the App Information, App Domain, Authorized Domain, Developer contact information. Once filled in, click “Save and Continue” + +![GC8](README/GC8.png) + +8. On the next page, you don’t need to select scopes. Proceed to “save and continue” and at the final page, review the process and click “Back to Dashboard”. With this, you’ve created your OAuth Consent Screen for Google Calendar. + +9. You can go ahead and click the “Publish App” + +![GC9](README/GC9.png) + +## 🔧 Configuring endpoints & obtaining Client ID and Client Secret Key + +In order to obtain the Client ID and Secret ID, you need to do the following steps: + +1. Go to “Credentials” Page + +![GC10](README/GC10.png) + +2. Click on “Create Credentials” and click on “OAuth Client ID” + +![GC11](README/GC11.png) + +![GC12](README/GC12.png) + +3. Once you click on OAuth Client ID, choose the type of application as “Web Application” and give it a name of your choice + +![GC13](README/GC13.png) + +4. Create JavaScript Origins and add the following details as shown in the image: + +![GC14](README/GC14.png) + +5. Go to Authorized redirect URIs and add the following as per the image: + +![GC15](README/GC15.png) + +6. Once you’re completed with adding the Authorized redirect URIs, you can click “Create” to obtain the Client ID and Client Secret Key + +![GC16](README/GC16.png) + +7. Copy the Client ID and Secret Key and save it in a file. + +## Configuring your Client ID, Secret Key and Authenticating Calendar with SuperAGI + +Once the ClientID and Secret Key is obtained, you can configure and authorize Calendar to be used with SuperAGI by following these steps: + +1. Add your Client ID and Client Secret Key on the toolkit page and click on “Update Changes” + +![GC17](README/GC17.png) + +2. Click on “Authenticate Tool” - which will now take you to the OAuth Flow. + +Once the OAuth Authentication is complete, you can now start using SuperAGI Agents with Google Calendar! diff --git a/superagi/tools/google_calendar/README/GC1.png b/superagi/tools/google_calendar/README/GC1.png new file mode 100644 index 000000000..a466bbcb0 Binary files /dev/null and b/superagi/tools/google_calendar/README/GC1.png differ diff --git a/superagi/tools/google_calendar/README/GC10.png b/superagi/tools/google_calendar/README/GC10.png new file mode 100644 index 000000000..a7002b555 Binary files /dev/null and b/superagi/tools/google_calendar/README/GC10.png differ diff --git a/superagi/tools/google_calendar/README/GC11.png b/superagi/tools/google_calendar/README/GC11.png new file mode 100644 index 000000000..a3ae229a5 Binary files /dev/null and b/superagi/tools/google_calendar/README/GC11.png differ diff --git a/superagi/tools/google_calendar/README/GC12.png b/superagi/tools/google_calendar/README/GC12.png new file mode 100644 index 000000000..4ec0eedf9 Binary files /dev/null and b/superagi/tools/google_calendar/README/GC12.png differ diff --git a/superagi/tools/google_calendar/README/GC13.png b/superagi/tools/google_calendar/README/GC13.png new file mode 100644 index 000000000..a68888188 Binary files /dev/null and b/superagi/tools/google_calendar/README/GC13.png differ diff --git a/superagi/tools/google_calendar/README/GC14.png b/superagi/tools/google_calendar/README/GC14.png new file mode 100644 index 000000000..9285e3481 Binary files /dev/null and b/superagi/tools/google_calendar/README/GC14.png differ diff --git a/superagi/tools/google_calendar/README/GC15.png b/superagi/tools/google_calendar/README/GC15.png new file mode 100644 index 000000000..bc33172b7 Binary files /dev/null and b/superagi/tools/google_calendar/README/GC15.png differ diff --git a/superagi/tools/google_calendar/README/GC16.png b/superagi/tools/google_calendar/README/GC16.png new file mode 100644 index 000000000..a5480620f Binary files /dev/null and b/superagi/tools/google_calendar/README/GC16.png differ diff --git a/superagi/tools/google_calendar/README/GC17.png b/superagi/tools/google_calendar/README/GC17.png new file mode 100644 index 000000000..ad72ec7c4 Binary files /dev/null and b/superagi/tools/google_calendar/README/GC17.png differ diff --git a/superagi/tools/google_calendar/README/GC2.png b/superagi/tools/google_calendar/README/GC2.png new file mode 100644 index 000000000..eeeb06277 Binary files /dev/null and b/superagi/tools/google_calendar/README/GC2.png differ diff --git a/superagi/tools/google_calendar/README/GC3.png b/superagi/tools/google_calendar/README/GC3.png new file mode 100644 index 000000000..d831298ee Binary files /dev/null and b/superagi/tools/google_calendar/README/GC3.png differ diff --git a/superagi/tools/google_calendar/README/GC4.png b/superagi/tools/google_calendar/README/GC4.png new file mode 100644 index 000000000..e85cd662f Binary files /dev/null and b/superagi/tools/google_calendar/README/GC4.png differ diff --git a/superagi/tools/google_calendar/README/GC5.png b/superagi/tools/google_calendar/README/GC5.png new file mode 100644 index 000000000..a2fa8145a Binary files /dev/null and b/superagi/tools/google_calendar/README/GC5.png differ diff --git a/superagi/tools/google_calendar/README/GC6.png b/superagi/tools/google_calendar/README/GC6.png new file mode 100644 index 000000000..62b893098 Binary files /dev/null and b/superagi/tools/google_calendar/README/GC6.png differ diff --git a/superagi/tools/google_calendar/README/GC7.png b/superagi/tools/google_calendar/README/GC7.png new file mode 100644 index 000000000..7fee7be4b Binary files /dev/null and b/superagi/tools/google_calendar/README/GC7.png differ diff --git a/superagi/tools/google_calendar/README/GC8.png b/superagi/tools/google_calendar/README/GC8.png new file mode 100644 index 000000000..c89d1cad1 Binary files /dev/null and b/superagi/tools/google_calendar/README/GC8.png differ diff --git a/superagi/tools/google_calendar/README/GC9.png b/superagi/tools/google_calendar/README/GC9.png new file mode 100644 index 000000000..7caaf3cf5 Binary files /dev/null and b/superagi/tools/google_calendar/README/GC9.png differ diff --git a/superagi/tools/google_search/google_search.py b/superagi/tools/google_search/google_search.py index 4bd3e427e..c0c7e875b 100644 --- a/superagi/tools/google_search/google_search.py +++ b/superagi/tools/google_search/google_search.py @@ -43,7 +43,7 @@ def _execute(self, query: str) -> tuple: query : The query to search for. Returns: - A tuple of (snippets, webpages, links) + Search result summary along with related links """ api_key = self.get_tool_config("GOOGLE_API_KEY") search_engine_id = self.get_tool_config("SEARCH_ENGINE_ID") diff --git a/superagi/tools/google_serp_search/google_serp_search.py b/superagi/tools/google_serp_search/google_serp_search.py index d3a69ae05..f780d2d78 100644 --- a/superagi/tools/google_serp_search/google_serp_search.py +++ b/superagi/tools/google_serp_search/google_serp_search.py @@ -45,7 +45,7 @@ def _execute(self, query: str) -> tuple: query : The query to search for. Returns: - A tuple of (snippets, webpages, links) + Search result summary along with related links """ api_key = self.get_tool_config("SERP_API_KEY") serp_api = GoogleSerpApiWrap(api_key) diff --git a/superagi/tools/image_generation/dalle_image_gen.py b/superagi/tools/image_generation/dalle_image_gen.py index 2b120efc2..c1ed8c578 100644 --- a/superagi/tools/image_generation/dalle_image_gen.py +++ b/superagi/tools/image_generation/dalle_image_gen.py @@ -47,7 +47,7 @@ def _execute(self, prompt: str, image_names: list, size: int = 512, num: int = 2 image_names (list): The name of the image to be generated. Returns: - Image generated successfully. or error message. + Image generated successfully message if image is generated or error message. """ if size not in [256, 512, 1024]: size = min([256, 512, 1024], key=lambda x: abs(x - size)) diff --git a/superagi/tools/jira/create_issue.py b/superagi/tools/jira/create_issue.py index b67146425..860c135db 100644 --- a/superagi/tools/jira/create_issue.py +++ b/superagi/tools/jira/create_issue.py @@ -34,8 +34,8 @@ def _execute(self, fields: dict): "name": "Low"}} Returns: - The key of the created issue. + The success message mentioning the key of the created issue. """ - jira = JiraTool.build_jira_instance() + jira = self.build_jira_instance() new_issue = jira.create_issue(fields=fields) return f"Issue '{new_issue.key}' created successfully!" diff --git a/superagi/tools/jira/edit_issue.py b/superagi/tools/jira/edit_issue.py index 79fb27b2e..d5119dc1f 100644 --- a/superagi/tools/jira/edit_issue.py +++ b/superagi/tools/jira/edit_issue.py @@ -40,9 +40,9 @@ def _execute(self, key: str, fields: dict): "name": "Low"}} Returns: - The key of the created issue. or Issue not found! + The success message mentioning key of the edited issue or Issue not found! """ - jira = JiraTool.build_jira_instance() + jira = self.build_jira_instance() issues = jira.search_issues('key=') if len(issues) > 0: issues[0].update(fields=fields) diff --git a/superagi/tools/jira/get_projects.py b/superagi/tools/jira/get_projects.py index 52e0a3384..d6442723c 100644 --- a/superagi/tools/jira/get_projects.py +++ b/superagi/tools/jira/get_projects.py @@ -32,9 +32,9 @@ def _execute(self) -> str: Execute the get projects tool. Returns: - The key of the created issue. + Found projects: """ - jira = JiraTool.build_jira_instance() + jira = self.build_jira_instance() projects = jira.projects() parsed_projects = self.parse_projects(projects) parsed_projects_str = ( diff --git a/superagi/tools/jira/search_issues.py b/superagi/tools/jira/search_issues.py index 707b983d5..8458719fc 100644 --- a/superagi/tools/jira/search_issues.py +++ b/superagi/tools/jira/search_issues.py @@ -4,7 +4,7 @@ from pydantic import Field, BaseModel from superagi.helper.token_counter import TokenCounter -from superagi.tools.jira.tool import JiraTool, JiraIssueSchema +from superagi.tools.jira.tool import JiraTool class SearchIssueSchema(BaseModel): @@ -33,14 +33,14 @@ def _execute(self, query: str) -> str: Args: query : JQL query string to search issues. For example, to find all the issues in project "Test" - assigned to the, you would pass in the following string: project = Test AND assignee = currentUser() or to + assigned to, you would pass in the following string: project = Test AND assignee = currentUser() or to find issues with summaries that contain the word "test", you would pass in the following string: summary ~ 'test'. Returns: - The key of the created issue. + The list of issues matching the query. """ - jira = JiraTool.build_jira_instance() + jira = self.build_jira_instance() issues = jira.search_issues(query) parsed_issues = self.parse_issues(issues) parsed_issues_str = ( diff --git a/superagi/tools/jira/tool.py b/superagi/tools/jira/tool.py index ef5f0de4f..54fbacb69 100644 --- a/superagi/tools/jira/tool.py +++ b/superagi/tools/jira/tool.py @@ -28,7 +28,6 @@ class JiraTool(BaseTool): description : The description. args_schema : The args schema. """ - @classmethod def build_jira_instance(self) -> dict: """ Build a Jira instance. diff --git a/superagi/tools/thinking/tools.py b/superagi/tools/thinking/tools.py index 0e8850999..2c2e0b869 100644 --- a/superagi/tools/thinking/tools.py +++ b/superagi/tools/thinking/tools.py @@ -48,7 +48,7 @@ def _execute(self, task_description: str): task_description : The task description. Returns: - response from the Thinking tool. or error message. + Thought process of llm for the task """ try: prompt = PromptReader.read_tools_prompt(__file__, "thinking.txt") diff --git a/tests/unit_tests/controllers/test_tool_config.py b/tests/unit_tests/controllers/test_tool_config.py index 8b97f1d37..eab3afb24 100644 --- a/tests/unit_tests/controllers/test_tool_config.py +++ b/tests/unit_tests/controllers/test_tool_config.py @@ -75,7 +75,6 @@ def test_get_all_tool_configs_success(mocks): patch('superagi.helper.auth.db') as mock_auth_db: mock_db.session.query.return_value.filter_by.return_value.first.return_value = toolkit_1 mock_db.session.query.return_value.filter.return_value.all.side_effect = [ - [toolkit_1, toolkit_2], [tool_config] ] response = client.get(f"/tool_configs/get/toolkit/test_toolkit_1") @@ -98,28 +97,13 @@ def test_get_all_tool_configs_toolkit_not_found(mocks): with patch('superagi.helper.auth.get_user_organisation') as mock_get_user_org, \ patch('superagi.controllers.tool_config.db') as mock_db, \ patch('superagi.helper.auth.db') as mock_auth_db: - mock_db.session.query.return_value.filter_by.return_value.first.return_value = None + mock_db.session.query.return_value.filter.return_value.first.return_value = None response = client.get(f"/tool_configs/get/toolkit/nonexistent_toolkit") # Assertions assert response.status_code == 404 assert response.json() == {'detail': 'ToolKit not found'} - -def test_get_all_tool_configs_unauthorized_access(mocks): - user_organisation, _, _, toolkit_1, toolkit_2 = mocks - - with patch('superagi.helper.auth.get_user_organisation') as mock_get_user_org, \ - patch('superagi.controllers.tool_config.db') as mock_db, \ - patch('superagi.helper.auth.db') as mock_auth_db: - mock_db.session.query.return_value.filter_by.return_value.first.return_value = toolkit_1 - response = client.get(f"/tool_configs/get/toolkit/test_toolkit_3") - - # Assertions - assert response.status_code == 403 - assert response.json() == {'detail': 'Unauthorized'} - - def test_get_tool_config_success(mocks): # Unpack the fixture data user_organisation, user_toolkits, tool_config, toolkit_1, toolkit_2 = mocks diff --git a/tests/unit_tests/jobs/test_agent_executor.py b/tests/unit_tests/jobs/test_agent_executor.py new file mode 100644 index 000000000..41691779c --- /dev/null +++ b/tests/unit_tests/jobs/test_agent_executor.py @@ -0,0 +1,33 @@ +import pytest +from unittest.mock import MagicMock + +from superagi.jobs.agent_executor import AgentExecutor +from superagi.models.tool import Tool +from superagi.tools.file.write_file import WriteFileTool + + +def test_validate_filename(): + # Test when filename ends with ".py" + assert AgentExecutor.validate_filename("tool.py") == "tool" + + # Test when filename doesn't end with ".py" + assert AgentExecutor.validate_filename("tool") == "tool" + + +def test_create_object(): + # Setup mock objects + tool = Tool() + tool.file_name = "file_toolkit.py" + tool.folder_name = "file" + tool.class_name = "WriteFileTool" + tool.toolkit_id = 1 + + session = MagicMock() + + # Test creating an object + obj = AgentExecutor.create_object(tool, session) + + # Assertions + assert isinstance(obj, WriteFileTool) + assert obj.toolkit_config.session == session + assert obj.toolkit_config.toolkit_id == tool.toolkit_id diff --git a/tests/unit_tests/models/test_toolkit.py b/tests/unit_tests/models/test_toolkit.py index 3a9d9bf2e..e0faa3fc0 100644 --- a/tests/unit_tests/models/test_toolkit.py +++ b/tests/unit_tests/models/test_toolkit.py @@ -8,7 +8,8 @@ def mock_session(): return MagicMock() -marketplace_url = "http://localhost:8001" +# marketplace_url = "http://localhost:8001" +marketplace_url = "https://app.superagi.com/api" def test_add_or_update_existing_toolkit(mock_session): @@ -153,18 +154,19 @@ def test_fetch_marketplace_detail_error(): def test_get_toolkit_from_name_existing_toolkit(mock_session): # Arrange toolkit_name = "example_toolkit" - expected_toolkit = Toolkit(name=toolkit_name) + organisation = Organisation(id=1) + expected_toolkit = Toolkit(name=toolkit_name,organisation_id=organisation.id) # Mock the session.query method mock_session.query.return_value.filter_by.return_value.first.return_value = expected_toolkit # Act - result = Toolkit.get_toolkit_from_name(mock_session, toolkit_name) + result = Toolkit.get_toolkit_from_name(mock_session, toolkit_name,organisation) # Assert assert result == expected_toolkit mock_session.query.assert_called_once_with(Toolkit) - mock_session.query.return_value.filter_by.assert_called_once_with(name=toolkit_name) + mock_session.query.return_value.filter_by.assert_called_once_with(name=toolkit_name,organisation_id=organisation.id) mock_session.query.return_value.filter_by.return_value.first.assert_called_once() def test_get_toolkit_from_name_nonexistent_toolkit(mock_session): @@ -173,14 +175,15 @@ def test_get_toolkit_from_name_nonexistent_toolkit(mock_session): # Mock the session.query method to return None mock_session.query.return_value.filter_by.return_value.first.return_value = None + organisation = Organisation(id=1) # Act - result = Toolkit.get_toolkit_from_name(mock_session, toolkit_name) + result = Toolkit.get_toolkit_from_name(mock_session, toolkit_name,organisation) # Assert assert result is None mock_session.query.assert_called_once_with(Toolkit) - mock_session.query.return_value.filter_by.assert_called_once_with(name=toolkit_name) + mock_session.query.return_value.filter_by.assert_called_once_with(name=toolkit_name,organisation_id=organisation.id) mock_session.query.return_value.filter_by.return_value.first.assert_called_once() def test_get_toolkit_installed_details(mock_session): diff --git a/tgwui/DockerfileTGWUI b/tgwui/DockerfileTGWUI index e25f0cbb9..41724b835 100644 --- a/tgwui/DockerfileTGWUI +++ b/tgwui/DockerfileTGWUI @@ -19,28 +19,26 @@ RUN git clone https://github.com/oobabooga/text-generation-webui /src # To use local source: comment out the git clone command then set the build arg `LCL_SRC_DIR` #ARG LCL_SRC_DIR="text-generation-webui" #COPY ${LCL_SRC_DIR} /src -# This is required to get multi-gpu support until the main branch updates the requirements.txt file to include llama-cpp-python 0.1.59 or greater. - ################################# +ENV LLAMA_CUBLAS=1 # Copy source to app RUN cp -ar /src /app # Install oobabooga/text-generation-webui RUN --mount=type=cache,target=/root/.cache/pip pip3 install -r /app/requirements.txt # Install extensions -COPY tgwui/scripts/build_extensions.sh /app/scripts/build_extensions.sh +COPY ./scripts/build_extensions.sh /scripts/build_extensions.sh RUN --mount=type=cache,target=/root/.cache/pip \ - chmod +x /app/scripts/build_extensions.sh && . /app/scripts/build_extensions.sh - -## Clone default GPTQ -RUN git clone https://github.com/oobabooga/GPTQ-for-LLaMa.git -## Build and install default GPTQ ('quant_cuda') + chmod +x /scripts/build_extensions.sh && . /scripts/build_extensions.sh +# Clone default GPTQ +RUN git clone https://github.com/oobabooga/GPTQ-for-LLaMa.git -b cuda /app/repositories/GPTQ-for-LLaMa +# Build and install default GPTQ ('quant_cuda') ARG TORCH_CUDA_ARCH_LIST="6.1;7.0;7.5;8.0;8.6+PTX" -RUN cd GPTQ-for-LLaMa/ && python3 setup_cuda.py install +RUN cd /app/repositories/GPTQ-for-LLaMa/ && python3 setup_cuda.py install FROM nvidia/cuda:11.8.0-devel-ubuntu22.04 AS base # Runtime pre-reqs RUN apt-get update && apt-get install --no-install-recommends -y \ - python3-venv python3-dev git + python3-venv python3-dev git # Copy app and src COPY --from=app_base /app /app COPY --from=app_base /src /src @@ -49,30 +47,26 @@ COPY --from=app_base /venv /venv ENV VIRTUAL_ENV=/venv RUN python3 -m venv $VIRTUAL_ENV ENV PATH="$VIRTUAL_ENV/bin:$PATH" +## Link models directory to container +#ADD ./config/models/ /app/models/ # Finalise app setup WORKDIR /app EXPOSE 7860 EXPOSE 5000 EXPOSE 5005 -EXPOSE 5001 # Required for Python print statements to appear in logs ENV PYTHONUNBUFFERED=1 # Force variant layers to sync cache by setting --build-arg BUILD_DATE ARG BUILD_DATE ENV BUILD_DATE=$BUILD_DATE RUN echo "$BUILD_DATE" > /build_date.txt - -# Set embeddings model for llama -#ENV OPENEDAI_EMBEDDING_MODEL=/app/embeddings/SGPT-125M-weightedmean-nli-bitfit -#COPY tgwui/config/embeddings/SGPT-125M-weightedmean-nli-bitfit /app/embeddings -#RUN echo -e "Embeddings model $OPENEDAI_EMBEDDING_MODEL" -#RUN python extensions/openai/cache_embedding_model.py - +# Copy and enable all scripts +COPY ./scripts /scripts +RUN chmod +x /scripts/* # Run -COPY tgwui/scripts/docker-entrypoint.sh /scripts/docker-entrypoint.sh -RUN chmod +x /scripts/docker-entrypoint.sh ENTRYPOINT ["/scripts/docker-entrypoint.sh"] + # VARIANT BUILDS FROM base AS cuda RUN echo "CUDA" >> /variant.txt @@ -100,8 +94,7 @@ FROM base AS llama-cublas RUN echo "LLAMA-CUBLAS" >> /variant.txt RUN apt-get install --no-install-recommends -y git python3-dev build-essential python3-pip ENV LLAMA_CUBLAS=1 -RUN pip uninstall -y llama-cpp-python && \ - CMAKE_ARGS="-DLLAMA_CUBLAS=on" FORCE_CMAKE=1 pip install llama-cpp-python +RUN pip uninstall -y llama-cpp-python && pip install llama-cpp-python ENV EXTRA_LAUNCH_ARGS="" CMD ["python3", "/app/server.py"] diff --git a/tgwui/config/models/place-your-models-here.txt b/tgwui/config/models/place-your-models-here.txt deleted file mode 100644 index e69de29bb..000000000