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

542 lines
22 KiB
Python

from datetime import datetime
from fastapi import APIRouter
from fastapi import HTTPException, Depends
from fastapi_sqlalchemy import db
from pydantic import BaseModel
from main import get_config
from superagi.controllers.types.agent_execution_config import AgentRunIn
from superagi.controllers.types.agent_publish_config import AgentPublish
from superagi.helper.auth import get_user_organisation
from superagi.helper.auth import get_current_user
from superagi.models.agent import Agent
from superagi.models.agent_config import AgentConfiguration
from superagi.models.agent_execution import AgentExecution
from superagi.models.agent_execution_config import AgentExecutionConfiguration
from superagi.models.agent_template import AgentTemplate
from superagi.models.agent_template_config import AgentTemplateConfig
from superagi.models.workflows.agent_workflow import AgentWorkflow
from superagi.models.tool import Tool
import json
# from superagi.types.db import AgentTemplateIn, AgentTemplateOut
router = APIRouter()
class AgentTemplateOut(BaseModel):
id: int
organisation_id: int
agent_workflow_id: int
name: str
description: str
marketplace_template_id: int
created_at: datetime
updated_at: datetime
class Config:
orm_mode = True
class AgentTemplateIn(BaseModel):
organisation_id: int
agent_workflow_id: int
name: str
description: str
marketplace_template_id: int
class Config:
orm_mode = True
@router.get("/get/{agent_template_id}")
def get_agent_template(template_source, agent_template_id: int, organisation=Depends(get_user_organisation)):
"""
Get the details of a specific agent template.
Args:
template_source (str): The source of the agent template ("local" or "marketplace").
agent_template_id (int): The ID of the agent template.
organisation (Depends): Dependency to get the user organisation.
Returns:
dict: The details of the agent template.
Raises:
HTTPException (status_code=404): If the agent template is not found.
"""
if template_source == "local":
db_agent_template = db.session.query(AgentTemplate).filter(AgentTemplate.organisation_id == organisation.id,
AgentTemplate.id == agent_template_id).first()
if not db_agent_template:
raise HTTPException(status_code=404, detail="Agent execution not found")
template = db_agent_template.to_dict()
configs = {}
agent_template_configs = db.session.query(AgentTemplateConfig).filter(
AgentTemplateConfig.agent_template_id == agent_template_id).all()
agent_workflow = AgentWorkflow.find_by_id(db_agent_template.agent_workflow_id)
for agent_template_config in agent_template_configs:
config_value = AgentTemplate.eval_agent_config(agent_template_config.key, agent_template_config.value)
configs[agent_template_config.key] = {"value": config_value}
template["configs"] = configs
template["agent_workflow_name"] = agent_workflow.name
else:
template = AgentTemplate.fetch_marketplace_detail(agent_template_id)
return template
@router.put("/update_agent_template/{agent_template_id}", status_code=200)
def edit_agent_template(agent_template_id: int,
updated_agent_configs: dict,
organisation=Depends(get_user_organisation)):
"""
Update the details of an agent template.
Args:
agent_template_id (int): The ID of the agent template to update.
updated_agent_configs (dict): The updated agent configurations.
organisation (Depends): Dependency to get the user organisation.
Returns:
HTTPException (status_code=200): If the agent gets successfully edited.
Raises:
HTTPException (status_code=404): If the agent template is not found.
"""
db_agent_template = db.session.query(AgentTemplate).filter(AgentTemplate.organisation_id == organisation.id,
AgentTemplate.id == agent_template_id).first()
if db_agent_template is None:
raise HTTPException(status_code=404, detail="Agent Template not found")
agent_workflow = AgentWorkflow.find_by_name(db.session, updated_agent_configs["agent_configs"]["agent_workflow"])
db_agent_template.name = updated_agent_configs["name"]
db_agent_template.description = updated_agent_configs["description"]
db_agent_template.agent_workflow_id = agent_workflow.id
db.session.commit()
agent_config_values = updated_agent_configs.get('agent_configs', {})
for key, value in agent_config_values.items():
if isinstance(value, (list, dict)):
value = json.dumps(value)
config = db.session.query(AgentTemplateConfig).filter(
AgentTemplateConfig.agent_template_id == agent_template_id,
AgentTemplateConfig.key == key
).first()
if config is not None:
config.value = value
else:
new_config = AgentTemplateConfig(
agent_template_id=agent_template_id,
key=key,
value= value
)
db.session.add(new_config)
db.session.commit()
db.session.flush()
# @router.put("/update_agent_template/{agent_template_id}", status_code=200)
# def edit_agent_template(agent_template_id: int,
# updated_agent_configs: dict,
# organisation=Depends(get_user_organisation)):
# """
# Update the details of an agent template.
# Args:
# agent_template_id (int): The ID of the agent template to update.
# edited_agent_configs (dict): The updated agent configurations.
# organisation (Depends): Dependency to get the user organisation.
# Returns:
# HTTPException (status_code=200): If the agent gets successfully edited.
# Raises:
# HTTPException (status_code=404): If the agent template is not found.
# """
# db_agent_template = db.session.query(AgentTemplate).filter(AgentTemplate.organisation_id == organisation.id,
# AgentTemplate.id == agent_template_id).first()
# if db_agent_template is None:
# raise HTTPException(status_code=404, detail="Agent Template not found")
# db_agent_template.name = updated_agent_configs["name"]
# db_agent_template.description = updated_agent_configs["description"]
# db.session.commit()
# agent_config_values = updated_agent_configs.get('agent_configs', {})
# for key, value in agent_config_values.items():
# if isinstance(value, (list, dict)):
# value = json.dumps(value)
# config = db.session.query(AgentTemplateConfig).filter(
# AgentTemplateConfig.agent_template_id == agent_template_id,
# AgentTemplateConfig.key == key
# ).first()
# if config is not None:
# config.value = value
# else:
# new_config = AgentTemplateConfig(
# agent_template_id=agent_template_id,
# key=key,
# value= value
# )
# db.session.add(new_config)
# db.session.commit()
# db.session.flush()
@router.post("/save_agent_as_template/agent_id/{agent_id}/agent_execution_id/{agent_execution_id}")
def save_agent_as_template(agent_execution_id: str,
agent_id: str,
organisation=Depends(get_user_organisation)):
"""
Save an agent as a template.
Args:
agent_id (str): The ID of the agent to save as a template.
agent_execution_id (str): The ID of the agent execution to save as a template.
organisation (Depends): Dependency to get the user organisation.
Returns:
dict: The saved agent template.
Raises:
HTTPException (status_code=404): If the agent or agent execution configurations are not found.
"""
if agent_execution_id == 'undefined':
raise HTTPException(status_code = 404, detail = "Agent Execution Id undefined")
if agent_id == 'undefined':
raise HTTPException(status_code = 404, detail = "Agent Id undefined")
agent = db.session.query(Agent).filter(Agent.id == agent_id).first()
if agent is None:
raise HTTPException(status_code=404, detail="Agent not found")
configs = None
if agent_execution_id == "-1":
configs = db.session.query(AgentConfiguration).filter(AgentConfiguration.agent_id == agent_id).all()
if not configs:
raise HTTPException(status_code=404, detail="Agent configurations not found")
else:
configs = db.session.query(AgentExecutionConfiguration).filter(AgentExecutionConfiguration.agent_execution_id == agent_execution_id).all()
if not configs:
raise HTTPException(status_code=404, detail="Agent execution configurations not found")
if configs is None:
raise HTTPException(status_code=404, detail="Configurations not found")
agent_template = AgentTemplate(name=agent.name, description=agent.description,
agent_workflow_id=agent.agent_workflow_id,
organisation_id=organisation.id)
db.session.add(agent_template)
db.session.commit()
for config in configs:
config_value = config.value
if config.key not in AgentTemplate.main_keys():
continue
if config.key == "tools":
config_value = str(Tool.convert_tool_ids_to_names(db, eval(config.value)))
agent_template_config = AgentTemplateConfig(agent_template_id=agent_template.id, key=config.key,
value=config_value)
db.session.add(agent_template_config)
db.session.commit()
db.session.flush()
return agent_template.to_dict()
@router.get("/list")
def list_agent_templates(template_source="local", search_str="", page=0, organisation=Depends(get_user_organisation)):
"""
List agent templates.
Args:
template_source (str, optional): The source of the templates ("local" or "marketplace"). Defaults to "local".
search_str (str, optional): The search string to filter templates. Defaults to "".
page (int, optional): The page number for paginated results. Defaults to 0.
organisation (Depends): Dependency to get the user organisation.
Returns:
list: A list of agent templates.
"""
output_json = []
if template_source == "local":
templates = db.session.query(AgentTemplate).filter(AgentTemplate.organisation_id == organisation.id).all()
for template in templates:
template.updated_at = template.updated_at.strftime('%d-%b-%Y').upper()
output_json.append(template)
else:
local_templates = db.session.query(AgentTemplate).filter(AgentTemplate.organisation_id == organisation.id,
AgentTemplate.marketplace_template_id != None).all()
local_templates_hash = {}
for local_template in local_templates:
local_templates_hash[local_template.marketplace_template_id] = True
print(local_templates_hash)
templates = AgentTemplate.fetch_marketplace_list(search_str, page)
print(templates)
for template in templates:
template["is_installed"] = local_templates_hash.get(template["id"], False)
template["organisation_id"] = organisation.id
output_json.append(template)
return output_json
@router.get("/marketplace/list")
def list_marketplace_templates(page=0):
"""
Get all marketplace agent templates.
Args:
page (int, optional): The page number for paginated results. Defaults to 0.
Returns:
list: A list of marketplace agent templates.
"""
organisation_id = int(get_config("MARKETPLACE_ORGANISATION_ID"))
page_size = 30
templates = db.session.query(AgentTemplate).filter(AgentTemplate.organisation_id == organisation_id).offset(
page * page_size).limit(page_size).all()
output_json = []
for template in templates:
template.updated_at = template.updated_at.strftime('%d-%b-%Y').upper()
output_json.append(template)
return output_json
@router.get("/marketplace/template_details/{agent_template_id}")
def marketplace_template_detail(agent_template_id):
"""
Get marketplace template details.
Args:
agent_template_id (int): The ID of the marketplace agent template.
Returns:
dict: A dictionary containing the marketplace template details.
"""
organisation_id = int(get_config("MARKETPLACE_ORGANISATION_ID"))
template = db.session.query(AgentTemplate).filter(AgentTemplate.organisation_id == organisation_id,
AgentTemplate.id == agent_template_id).first()
template_configs = db.session.query(AgentTemplateConfig).filter(
AgentTemplateConfig.agent_template_id == template.id).all()
workflow = db.session.query(AgentWorkflow).filter(AgentWorkflow.id == template.agent_workflow_id).first()
tool_configs = {}
for template_config in template_configs:
config_value = AgentTemplate.eval_agent_config(template_config.key, template_config.value)
tool_configs[template_config.key] = {"value": config_value}
output_json = {
"id": template.id,
"name": template.name,
"description": template.description,
"agent_workflow_id": template.agent_workflow_id,
"agent_workflow_name": workflow.name,
"configs": tool_configs
}
return output_json
@router.post("/download", status_code=201)
def download_template(agent_template_id: int,
organisation=Depends(get_user_organisation)):
"""
Create a new agent with configurations.
Args:
agent_template_id (int): The ID of the agent template.
organisation: User's organisation.
Returns:
dict: A dictionary containing the details of the downloaded template.
"""
template = AgentTemplate.clone_agent_template_from_marketplace(db, organisation.id, agent_template_id)
return template.to_dict()
@router.get("/agent_config", status_code=201)
def fetch_agent_config_from_template(agent_template_id: int,
organisation=Depends(get_user_organisation)):
"""
Fetches agent configuration from a template.
Args:
agent_template_id (int): The ID of the agent template.
organisation: User's organisation.
Returns:
dict: A dictionary containing the agent configuration fetched from the template.
Raises:
HTTPException: If the template is not found.
"""
agent_template = db.session.query(AgentTemplate).filter(AgentTemplate.id == agent_template_id,
AgentTemplate.organisation_id == organisation.id).first()
if not agent_template:
raise HTTPException(status_code=404, detail="Template not found")
template_config = db.session.query(AgentTemplateConfig).filter(
AgentTemplateConfig.agent_template_id == agent_template_id).all()
template_config_dict = {}
main_keys = AgentTemplate.main_keys()
for config in template_config:
if config.key in main_keys:
template_config_dict[config.key] = AgentTemplate.eval_agent_config(config.key, config.value)
if "instruction" not in template_config_dict:
template_config_dict["instruction"] = []
if "constraints" not in template_config_dict:
template_config_dict["constraints"] = []
for key in main_keys:
if key not in template_config_dict:
template_config_dict[key] = ""
template_config_dict["agent_template_id"] = agent_template.id
agent_workflow = AgentWorkflow.find_by_id(db.session, agent_template.agent_workflow_id)
template_config_dict["agent_workflow"] = agent_workflow.name
return template_config_dict
@router.post("/publish_template/agent_execution_id/{agent_execution_id}", status_code=201)
def publish_template(agent_execution_id: str, organisation=Depends(get_user_organisation), user=Depends(get_current_user)):
"""
Publish an agent execution as a template.
Args:
agent_execution_id (str): The ID of the agent execution to save as a template.
organisation (Depends): Dependency to get the user organisation.
user (Depends): Dependency to get the user.
Returns:
dict: The saved agent template.
Raises:
HTTPException (status_code=404): If the agent or agent execution configurations are not found.
"""
if agent_execution_id == 'undefined':
raise HTTPException(status_code = 404, detail = "Agent Execution Id undefined")
agent_executions = AgentExecution.get_agent_execution_from_id(db.session, agent_execution_id)
if agent_executions is None:
raise HTTPException(status_code = 404, detail = "Agent Execution not found")
agent_id = agent_executions.agent_id
agent = db.session.query(Agent).filter(Agent.id == agent_id).first()
if agent is None:
raise HTTPException(status_code=404, detail="Agent not found")
agent_execution_configurations = db.session.query(AgentExecutionConfiguration).filter(AgentExecutionConfiguration.agent_execution_id == agent_execution_id).all()
if not agent_execution_configurations:
raise HTTPException(status_code=404, detail="Agent execution configurations not found")
agent_template = AgentTemplate(name=agent.name, description=agent.description,
agent_workflow_id=agent.agent_workflow_id,
organisation_id=organisation.id)
db.session.add(agent_template)
db.session.commit()
main_keys = AgentTemplate.main_keys()
for agent_execution_configuration in agent_execution_configurations:
config_value = agent_execution_configuration.value
if agent_execution_configuration.key not in main_keys:
continue
if agent_execution_configuration.key == "tools":
config_value = str(Tool.convert_tool_ids_to_names(db, eval(agent_execution_configuration.value)))
agent_template_config = AgentTemplateConfig(agent_template_id=agent_template.id, key=agent_execution_configuration.key,
value=config_value)
db.session.add(agent_template_config)
agent_template_configs = [
AgentTemplateConfig(agent_template_id=agent_template.id, key="status", value="UNDER REVIEW"),
AgentTemplateConfig(agent_template_id=agent_template.id, key="Contributor Name", value=user.name),
AgentTemplateConfig(agent_template_id=agent_template.id, key="Contributor Email", value=user.email)]
db.session.add_all(agent_template_configs)
db.session.commit()
db.session.flush()
return agent_template.to_dict()
@router.post("/publish_template", status_code=201)
def handle_publish_template(updated_details: AgentPublish, organisation=Depends(get_user_organisation), user=Depends(get_current_user)):
"""
Publish a template from edit template page.
Args:
organisation (Depends): Dependency to get the user organisation.
user (Depends): Dependency to get the user.
Returns:
dict: The saved agent template.
Raises:
HTTPException (status_code=404): If the agent template or workflow are not found.
"""
old_template_id = updated_details.agent_template_id
old_agent_template = db.session.query(AgentTemplate).filter(AgentTemplate.id==old_template_id, AgentTemplate.organisation_id==organisation.id).first()
if old_agent_template is None:
raise HTTPException(status_code = 404, detail = "Agent Template not found")
agent_workflow_id = old_agent_template.agent_workflow_id
if agent_workflow_id is None:
raise HTTPException(status_code = 404, detail = "Agent Workflow not found")
agent_template = AgentTemplate(name=updated_details.name, description=updated_details.description,
agent_workflow_id=agent_workflow_id,
organisation_id=organisation.id)
db.session.add(agent_template)
db.session.commit()
agent_template_configs = {
"goal": updated_details.goal,
"instruction": updated_details.instruction,
"constraints": updated_details.constraints,
"toolkits": updated_details.toolkits,
"exit": updated_details.exit,
"tools": updated_details.tools,
"iteration_interval": updated_details.iteration_interval,
"model": updated_details.model,
"permission_type": updated_details.permission_type,
"LTM_DB": updated_details.LTM_DB,
"max_iterations": updated_details.max_iterations,
"user_timezone": updated_details.user_timezone,
"knowledge": updated_details.knowledge
}
for key, value in agent_template_configs.items():
if key == "tools":
value = Tool.convert_tool_ids_to_names(db, value)
agent_template_config = AgentTemplateConfig(agent_template_id=agent_template.id, key=key, value=str(value))
db.session.add(agent_template_config)
agent_template_configs = [
AgentTemplateConfig(agent_template_id=agent_template.id, key="status", value="UNDER REVIEW"),
AgentTemplateConfig(agent_template_id=agent_template.id, key="Contributor Name", value=user.name),
AgentTemplateConfig(agent_template_id=agent_template.id, key="Contributor Email", value=user.email)]
db.session.add_all(agent_template_configs)
db.session.commit()
db.session.flush()
return agent_template.to_dict()