Files
2026-07-13 12:43:34 +08:00

368 lines
13 KiB
Python

from typing import Optional
import requests
from fastapi import APIRouter, Body
from fastapi import HTTPException, Depends, Query
from fastapi_sqlalchemy import db
from superagi.config.config import get_config
from superagi.helper.auth import get_user_organisation
from superagi.helper.tool_helper import get_readme_content_from_code_link, download_tool, process_files, \
add_tool_to_json
from superagi.helper.github_helper import GithubHelper
from superagi.models.organisation import Organisation
from superagi.models.tool import Tool
from superagi.models.tool_config import ToolConfig
from superagi.models.toolkit import Toolkit
from superagi.types.common import GitHubLinkRequest
from superagi.helper.tool_helper import compare_toolkit
from superagi.helper.encyption_helper import decrypt_data, is_encrypted
router = APIRouter()
# marketplace_url = "https://app.superagi.com/api"
# marketplace_url = "http://localhost:8001/"
# For internal use
@router.get("/marketplace/list/{page}")
def get_marketplace_toolkits(
page: int = 0,
):
"""
Get marketplace tool kits.
Args:
page (int): The page number for pagination.
Returns:
list: A list of tool kits in the marketplace.
"""
organisation_id = int(get_config("MARKETPLACE_ORGANISATION_ID"))
page_size = 30
# Apply search filter if provided
query = db.session.query(Toolkit).filter(Toolkit.organisation_id == organisation_id)
# Paginate the results
toolkits = query.offset(page * page_size).limit(page_size).all()
# Fetch tools for each tool kit
for toolkit in toolkits:
toolkit.tools = db.session.query(Tool).filter(Tool.toolkit_id == toolkit.id).all()
toolkit.updated_at = toolkit.updated_at.strftime('%d-%b-%Y').upper()
return toolkits
# For internal use
@router.get("/marketplace/details/{toolkit_name}")
def get_marketplace_toolkit_detail(toolkit_name: str):
"""
Get tool kit details from the marketplace.
Args:
toolkit_name (str): The name of the tool kit.
Returns:
Toolkit: The tool kit details from the marketplace.
"""
organisation_id = int(get_config("MARKETPLACE_ORGANISATION_ID"))
toolkit = db.session.query(Toolkit).filter(Toolkit.organisation_id == organisation_id,
Toolkit.name == toolkit_name).first()
toolkit.tools = db.session.query(Tool).filter(Tool.toolkit_id == toolkit.id).all()
toolkit.configs = db.session.query(ToolConfig).filter(ToolConfig.toolkit_id == toolkit.id).all()
for tool_configs in toolkit.configs:
if is_encrypted(tool_configs.value):
tool_configs.value = decrypt_data(tool_configs.value)
return toolkit
# For internal use
@router.get("/marketplace/readme/{toolkit_name}")
def get_marketplace_toolkit_readme(toolkit_name: str):
"""
Get tool kit readme from the marketplace.
Args:
toolkit_name (str): The name of the tool kit.
Returns:
str: The content of the tool kit's readme file.
Raises:
HTTPException (status_code=404): If the specified tool kit is not found.
"""
organisation_id = int(get_config("MARKETPLACE_ORGANISATION_ID"))
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')
return get_readme_content_from_code_link(toolkit.tool_code_link)
# For internal use
@router.get("/marketplace/tools/{toolkit_name}")
def get_marketplace_toolkit_tools(toolkit_name: str):
"""
Get tools of a specific tool kit from the marketplace.
Args:
toolkit_name (str): The name of the tool kit.
Returns:
Tool: The tools associated with the tool kit.
Raises:
HTTPException (status_code=404): If the specified tool kit is not found.
"""
organisation_id = int(get_config("MARKETPLACE_ORGANISATION_ID"))
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")
tools = db.session.query(Tool).filter(Tool.toolkit_id == toolkit.id).first()
return tools
@router.get("/get/install/{toolkit_name}")
def install_toolkit_from_marketplace(toolkit_name: str,
organisation: Organisation = Depends(get_user_organisation)):
"""
Download and install a tool kit from the marketplace.
Args:
toolkit_name (str): The name of the tool kit.
organisation (Organisation): The user's organisation.
Returns:
dict: A message indicating the successful installation of the tool kit.
"""
# Check if the tool kit exists
toolkit = Toolkit.fetch_marketplace_detail(search_str="details",
toolkit_name=toolkit_name)
db_toolkit = Toolkit.add_or_update(session=db.session, name=toolkit['name'], description=toolkit['description'],
tool_code_link=toolkit['tool_code_link'], organisation_id=organisation.id,
show_toolkit=toolkit['show_toolkit'])
for tool in toolkit['tools']:
Tool.add_or_update(session=db.session, tool_name=tool['name'], description=tool['description'],
folder_name=tool['folder_name'], class_name=tool['class_name'], file_name=tool['file_name'],
toolkit_id=db_toolkit.id)
for config in toolkit['configs']:
ToolConfig.add_or_update(session=db.session, toolkit_id=db_toolkit.id, key=config['key'], value=config['value'], key_type = config['key_type'], is_secret = config['is_secret'], is_required = config['is_required'])
return {"message": "ToolKit installed successfully"}
@router.get("/get/toolkit_name/{toolkit_name}")
def get_installed_toolkit_details(toolkit_name: str,
organisation: Organisation = Depends(get_user_organisation)):
"""
Get details of a locally installed tool kit by its name, including the details of its tools.
Args:
toolkit_name (str): The name of the tool kit.
organisation (Organisation): The user's organisation.
Returns:
Toolkit: The tool kit object with its associated tools.
Raises:
HTTPException (status_code=404): If the specified tool kit is not found.
"""
# Fetch the tool kit by its ID
toolkit = db.session.query(Toolkit).filter(Toolkit.name == toolkit_name,
Organisation.id == organisation.id).first()
if not toolkit:
# Return an appropriate response if the tool kit doesn't exist
raise HTTPException(status_code=404, detail='ToolKit not found')
# Fetch the tools associated with the tool kit
tools = db.session.query(Tool).filter(Tool.toolkit_id == toolkit.id).all()
# Add the tools to the tool kit object
toolkit.tools = tools
# readme_content = get_readme(toolkit.tool_code_link)
return toolkit
@router.post("/get/local/install", status_code=200)
def download_and_install_tool(github_link_request: GitHubLinkRequest = Body(...),
organisation: Organisation = Depends(get_user_organisation)):
"""
Install a tool locally from a GitHub link.
Args:
github_link_request (GitHubLinkRequest): The GitHub link request object.
organisation (Organisation): The user's organisation.
Returns:
None
Raises:
HTTPException (status_code=400): If the GitHub link is invalid.
"""
github_link = github_link_request.github_link
if not GithubHelper.validate_github_link(github_link):
raise HTTPException(status_code=400, detail="Invalid Github link")
# download_folder = get_config("TOOLS_DIR")
# download_tool(github_link, download_folder)
# process_files(download_folder, db.session, organisation, code_link=github_link)
add_tool_to_json(github_link)
@router.get("/get/readme/{toolkit_name}")
def get_installed_toolkit_readme(toolkit_name: str, organisation: Organisation = Depends(get_user_organisation)):
"""
Get the readme content of a toolkit.
Args:
toolkit_name (str): The name of the toolkit.
organisation (Organisation): The user's organisation.
Returns:
str: The readme content of the toolkit.
Raises:
HTTPException (status_code=404): If the toolkit is not found.
"""
toolkit = db.session.query(Toolkit).filter(Toolkit.name == toolkit_name,
Organisation.id == organisation.id).first()
if not toolkit:
raise HTTPException(status_code=404, detail='ToolKit not found')
readme_content = get_readme_content_from_code_link(toolkit.tool_code_link)
return readme_content
# Following APIs will be used to get marketplace related information
@router.get("/get")
def handle_marketplace_operations(
search_str: str = Query(None, title="Search String"),
toolkit_name: str = Query(None, title="Tool Kit Name")
):
"""
Handle marketplace operations.
Args:
search_str (str, optional): The search string to filter toolkits. Defaults to None.
toolkit_name (str, optional): The name of the toolkit. Defaults to None.
Returns:
dict: The response containing the marketplace details.
"""
response = Toolkit.fetch_marketplace_detail(search_str, toolkit_name)
return response
@router.get("/get/list")
def handle_marketplace_operations_list(
page: int = Query(None, title="Page Number"),
organisation: Organisation = Depends(get_user_organisation)
):
"""
Handle marketplace operation list.
Args:
page (int, optional): The page number for pagination. Defaults to None.
Returns:
dict: The response containing the marketplace list.
"""
marketplace_toolkits = Toolkit.fetch_marketplace_list(page=page)
marketplace_toolkits_with_install = Toolkit.get_toolkit_installed_details(db.session, marketplace_toolkits,
organisation)
return marketplace_toolkits_with_install
@router.get("/get/local/list")
def get_installed_toolkit_list(organisation: Organisation = Depends(get_user_organisation)):
"""
Get the list of installed tool kits.
Args:
organisation (Organisation): The organisation associated with the tool kits.
Returns:
list: The list of installed tool kits.
"""
toolkits = db.session.query(Toolkit).filter(Toolkit.organisation_id == organisation.id).all()
for toolkit in toolkits:
toolkit_tools = db.session.query(Tool).filter(Tool.toolkit_id == toolkit.id).all()
toolkit.tools = toolkit_tools
return toolkits
@router.get("/check_update/{toolkit_name}")
def check_toolkit_update(toolkit_name: str, organisation: Organisation = Depends(get_user_organisation)):
"""
Check if there is an update available for the installed tool kits.
Returns:
dict: The response containing the update details.
"""
marketplace_toolkit = Toolkit.fetch_marketplace_detail(search_str="details",
toolkit_name=toolkit_name)
if marketplace_toolkit is None:
raise HTTPException(status_code=404, detail="Toolkit not found in marketplace")
installed_toolkit = Toolkit.get_toolkit_from_name(db.session, toolkit_name, organisation)
if installed_toolkit is None:
return True
installed_toolkit = installed_toolkit.to_dict()
tools = Tool.get_toolkit_tools(db.session, installed_toolkit["id"])
configs = ToolConfig.get_toolkit_tool_config(db.session, installed_toolkit["id"])
installed_toolkit["configs"] = []
installed_toolkit["tools"] = []
for config in configs:
installed_toolkit["configs"].append(config.to_dict())
for tool in tools:
installed_toolkit["tools"].append(tool.to_dict())
return compare_toolkit(marketplace_toolkit, installed_toolkit)
@router.put("/update/{toolkit_name}")
def update_toolkit(toolkit_name: str, organisation: Organisation = Depends(get_user_organisation)):
"""
Update the toolkit with the latest version from the marketplace.
"""
marketplace_toolkit = Toolkit.fetch_marketplace_detail(search_str="details",
toolkit_name=toolkit_name)
update_toolkit = Toolkit.add_or_update(
db.session,
name=marketplace_toolkit["name"],
description=marketplace_toolkit["description"],
show_toolkit=True if len(marketplace_toolkit["tools"]) > 1 else False,
organisation_id=organisation.id,
tool_code_link=marketplace_toolkit["tool_code_link"]
)
for tool in marketplace_toolkit["tools"]:
Tool.add_or_update(db.session, tool_name=tool["name"], folder_name=tool["folder_name"],
class_name=tool["class_name"], file_name=tool["file_name"],
toolkit_id=update_toolkit.id, description=tool["description"])
for tool_config_key in marketplace_toolkit["configs"]:
ToolConfig.add_or_update(db.session, toolkit_id=update_toolkit.id, key=tool_config_key["key"], key_type = tool_config_key['key_type'], is_secret = tool_config_key['is_secret'], is_required = tool_config_key['is_required'])