mirror of
https://github.com/Significant-Gravitas/AutoGPT.git
synced 2026-01-28 16:38:17 -05:00
Compare commits
18 Commits
testing-cl
...
pwuts/open
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f032333a28 | ||
|
|
773e4af6d4 | ||
|
|
a18ca17f25 | ||
|
|
383b72a551 | ||
|
|
158ce75c38 | ||
|
|
cd35e215e3 | ||
|
|
fba9ef2bd7 | ||
|
|
32cf7fae8e | ||
|
|
4eab94510a | ||
|
|
a25d12ba26 | ||
|
|
e94d0844bb | ||
|
|
7045ff190f | ||
|
|
b78d0787f5 | ||
|
|
6476bcbca2 | ||
|
|
e908213049 | ||
|
|
57a7bfe2b7 | ||
|
|
612461fe22 | ||
|
|
e982fe99ac |
@@ -201,7 +201,7 @@ class AgentServer(backend.util.service.AppProcess):
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
async def test_get_presets(user_id: str, page: int = 1, page_size: int = 10):
|
async def test_get_presets(user_id: str, page: int = 1, page_size: int = 10):
|
||||||
return await backend.server.v2.library.routes.presets.get_presets(
|
return await backend.server.v2.library.routes.presets.list_presets(
|
||||||
user_id=user_id, page=page, page_size=page_size
|
user_id=user_id, page=page, page_size=page_size
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -213,7 +213,7 @@ class AgentServer(backend.util.service.AppProcess):
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
async def test_create_preset(
|
async def test_create_preset(
|
||||||
preset: backend.server.v2.library.model.CreateLibraryAgentPresetRequest,
|
preset: backend.server.v2.library.model.LibraryAgentPresetCreatable,
|
||||||
user_id: str,
|
user_id: str,
|
||||||
):
|
):
|
||||||
return await backend.server.v2.library.routes.presets.create_preset(
|
return await backend.server.v2.library.routes.presets.create_preset(
|
||||||
@@ -223,7 +223,7 @@ class AgentServer(backend.util.service.AppProcess):
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
async def test_update_preset(
|
async def test_update_preset(
|
||||||
preset_id: str,
|
preset_id: str,
|
||||||
preset: backend.server.v2.library.model.CreateLibraryAgentPresetRequest,
|
preset: backend.server.v2.library.model.LibraryAgentPresetUpdatable,
|
||||||
user_id: str,
|
user_id: str,
|
||||||
):
|
):
|
||||||
return await backend.server.v2.library.routes.presets.update_preset(
|
return await backend.server.v2.library.routes.presets.update_preset(
|
||||||
|
|||||||
@@ -14,7 +14,9 @@ import backend.server.v2.store.exceptions as store_exceptions
|
|||||||
import backend.server.v2.store.image_gen as store_image_gen
|
import backend.server.v2.store.image_gen as store_image_gen
|
||||||
import backend.server.v2.store.media as store_media
|
import backend.server.v2.store.media as store_media
|
||||||
from backend.data.db import locked_transaction
|
from backend.data.db import locked_transaction
|
||||||
|
from backend.data.execution import get_graph_execution
|
||||||
from backend.data.includes import library_agent_include
|
from backend.data.includes import library_agent_include
|
||||||
|
from backend.util.exceptions import NotFoundError
|
||||||
from backend.util.settings import Config
|
from backend.util.settings import Config
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
@@ -140,7 +142,7 @@ async def get_library_agent(id: str, user_id: str) -> library_model.LibraryAgent
|
|||||||
Get a specific agent from the user's library.
|
Get a specific agent from the user's library.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
library_agent_id: ID of the library agent to retrieve.
|
id: ID of the library agent to retrieve.
|
||||||
user_id: ID of the authenticated user.
|
user_id: ID of the authenticated user.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
@@ -232,7 +234,7 @@ async def create_library_agent(
|
|||||||
isCreatedByUser=(user_id == graph.user_id),
|
isCreatedByUser=(user_id == graph.user_id),
|
||||||
useGraphIsActiveVersion=True,
|
useGraphIsActiveVersion=True,
|
||||||
User={"connect": {"id": user_id}},
|
User={"connect": {"id": user_id}},
|
||||||
# Creator={"connect": {"id": agent.userId}},
|
# Creator={"connect": {"id": graph.user_id}},
|
||||||
AgentGraph={
|
AgentGraph={
|
||||||
"connect": {
|
"connect": {
|
||||||
"graphVersionId": {"id": graph.id, "version": graph.version}
|
"graphVersionId": {"id": graph.id, "version": graph.version}
|
||||||
@@ -398,11 +400,13 @@ async def add_store_agent_to_library(
|
|||||||
|
|
||||||
# Check if user already has this agent
|
# Check if user already has this agent
|
||||||
existing_library_agent = (
|
existing_library_agent = (
|
||||||
await prisma.models.LibraryAgent.prisma().find_first(
|
await prisma.models.LibraryAgent.prisma().find_unique(
|
||||||
where={
|
where={
|
||||||
"userId": user_id,
|
"userId_agentGraphId_agentGraphVersion": {
|
||||||
"agentGraphId": graph.id,
|
"userId": user_id,
|
||||||
"agentGraphVersion": graph.version,
|
"agentGraphId": graph.id,
|
||||||
|
"agentGraphVersion": graph.version,
|
||||||
|
}
|
||||||
},
|
},
|
||||||
include=library_agent_include(user_id),
|
include=library_agent_include(user_id),
|
||||||
)
|
)
|
||||||
@@ -410,13 +414,13 @@ async def add_store_agent_to_library(
|
|||||||
if existing_library_agent:
|
if existing_library_agent:
|
||||||
if existing_library_agent.isDeleted:
|
if existing_library_agent.isDeleted:
|
||||||
# Even if agent exists it needs to be marked as not deleted
|
# Even if agent exists it needs to be marked as not deleted
|
||||||
await set_is_deleted_for_library_agent(
|
await update_library_agent(
|
||||||
user_id, graph.id, graph.version, False
|
existing_library_agent.id, user_id, is_deleted=False
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
logger.debug(
|
logger.debug(
|
||||||
f"User #{user_id} already has graph #{graph.id} "
|
f"User #{user_id} already has graph #{graph.id} "
|
||||||
"in their library"
|
f"v{graph.version} in their library"
|
||||||
)
|
)
|
||||||
return library_model.LibraryAgent.from_db(existing_library_agent)
|
return library_model.LibraryAgent.from_db(existing_library_agent)
|
||||||
|
|
||||||
@@ -424,8 +428,11 @@ async def add_store_agent_to_library(
|
|||||||
added_agent = await prisma.models.LibraryAgent.prisma().create(
|
added_agent = await prisma.models.LibraryAgent.prisma().create(
|
||||||
data=prisma.types.LibraryAgentCreateInput(
|
data=prisma.types.LibraryAgentCreateInput(
|
||||||
userId=user_id,
|
userId=user_id,
|
||||||
agentGraphId=graph.id,
|
AgentGraph={
|
||||||
agentGraphVersion=graph.version,
|
"connect": {
|
||||||
|
"graphVersionId": {"id": graph.id, "version": graph.version}
|
||||||
|
}
|
||||||
|
},
|
||||||
isCreatedByUser=False,
|
isCreatedByUser=False,
|
||||||
),
|
),
|
||||||
include=library_agent_include(user_id),
|
include=library_agent_include(user_id),
|
||||||
@@ -445,60 +452,22 @@ async def add_store_agent_to_library(
|
|||||||
raise store_exceptions.DatabaseError("Failed to add agent to library") from e
|
raise store_exceptions.DatabaseError("Failed to add agent to library") from e
|
||||||
|
|
||||||
|
|
||||||
async def set_is_deleted_for_library_agent(
|
|
||||||
user_id: str, agent_id: str, agent_version: int, is_deleted: bool
|
|
||||||
) -> None:
|
|
||||||
"""
|
|
||||||
Changes the isDeleted flag for a library agent.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
user_id: The user's library from which the agent is being removed.
|
|
||||||
agent_id: The ID of the agent to remove.
|
|
||||||
agent_version: The version of the agent to remove.
|
|
||||||
is_deleted: Whether the agent is being marked as deleted.
|
|
||||||
|
|
||||||
Raises:
|
|
||||||
DatabaseError: If there's an issue updating the Library
|
|
||||||
"""
|
|
||||||
logger.debug(
|
|
||||||
f"Setting isDeleted={is_deleted} for agent {agent_id} v{agent_version} "
|
|
||||||
f"in library for user {user_id}"
|
|
||||||
)
|
|
||||||
try:
|
|
||||||
logger.warning(
|
|
||||||
f"Setting isDeleted={is_deleted} for agent {agent_id} v{agent_version} in library for user {user_id}"
|
|
||||||
)
|
|
||||||
count = await prisma.models.LibraryAgent.prisma().update_many(
|
|
||||||
where={
|
|
||||||
"userId": user_id,
|
|
||||||
"agentGraphId": agent_id,
|
|
||||||
"agentGraphVersion": agent_version,
|
|
||||||
},
|
|
||||||
data={"isDeleted": is_deleted},
|
|
||||||
)
|
|
||||||
logger.warning(f"Updated {count} isDeleted library agents")
|
|
||||||
except prisma.errors.PrismaError as e:
|
|
||||||
logger.error(f"Database error setting agent isDeleted: {e}")
|
|
||||||
raise store_exceptions.DatabaseError(
|
|
||||||
"Failed to set agent isDeleted in library"
|
|
||||||
) from e
|
|
||||||
|
|
||||||
|
|
||||||
##############################################
|
##############################################
|
||||||
########### Presets DB Functions #############
|
########### Presets DB Functions #############
|
||||||
##############################################
|
##############################################
|
||||||
|
|
||||||
|
|
||||||
async def get_presets(
|
async def list_presets(
|
||||||
user_id: str, page: int, page_size: int
|
user_id: str, page: int, page_size: int, graph_id: Optional[str] = None
|
||||||
) -> library_model.LibraryAgentPresetResponse:
|
) -> library_model.LibraryAgentPresetResponse:
|
||||||
"""
|
"""
|
||||||
Retrieves a paginated list of AgentPresets for the specified user.
|
Retrieves a paginated list of AgentPresets for the specified user.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
user_id: The user ID whose presets are being retrieved.
|
user_id: The user ID whose presets are being retrieved.
|
||||||
page: The current page index (0-based or 1-based, clarify in your domain).
|
page: The current page index (1-based).
|
||||||
page_size: Number of items to retrieve per page.
|
page_size: Number of items to retrieve per page.
|
||||||
|
graph_id: Agent Graph ID to filter by.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
A LibraryAgentPresetResponse containing a list of presets and pagination info.
|
A LibraryAgentPresetResponse containing a list of presets and pagination info.
|
||||||
@@ -510,21 +479,24 @@ async def get_presets(
|
|||||||
f"Fetching presets for user #{user_id}, page={page}, page_size={page_size}"
|
f"Fetching presets for user #{user_id}, page={page}, page_size={page_size}"
|
||||||
)
|
)
|
||||||
|
|
||||||
if page < 0 or page_size < 1:
|
if page < 1 or page_size < 1:
|
||||||
logger.warning(
|
logger.warning(
|
||||||
"Invalid pagination input: page=%d, page_size=%d", page, page_size
|
"Invalid pagination input: page=%d, page_size=%d", page, page_size
|
||||||
)
|
)
|
||||||
raise store_exceptions.DatabaseError("Invalid pagination parameters")
|
raise store_exceptions.DatabaseError("Invalid pagination parameters")
|
||||||
|
|
||||||
|
query_filter: prisma.types.AgentPresetWhereInput = {"userId": user_id}
|
||||||
|
if graph_id:
|
||||||
|
query_filter["agentGraphId"] = graph_id
|
||||||
|
|
||||||
try:
|
try:
|
||||||
presets_records = await prisma.models.AgentPreset.prisma().find_many(
|
presets_records = await prisma.models.AgentPreset.prisma().find_many(
|
||||||
where={"userId": user_id},
|
where=query_filter,
|
||||||
skip=page * page_size,
|
skip=(page - 1) * page_size,
|
||||||
take=page_size,
|
take=page_size,
|
||||||
|
include={"InputPresets": True},
|
||||||
)
|
)
|
||||||
total_items = await prisma.models.AgentPreset.prisma().count(
|
total_items = await prisma.models.AgentPreset.prisma().count(where=query_filter)
|
||||||
where={"userId": user_id}
|
|
||||||
)
|
|
||||||
total_pages = (total_items + page_size - 1) // page_size
|
total_pages = (total_items + page_size - 1) // page_size
|
||||||
|
|
||||||
presets = [
|
presets = [
|
||||||
@@ -577,69 +549,142 @@ async def get_preset(
|
|||||||
raise store_exceptions.DatabaseError("Failed to fetch preset") from e
|
raise store_exceptions.DatabaseError("Failed to fetch preset") from e
|
||||||
|
|
||||||
|
|
||||||
async def upsert_preset(
|
async def create_preset(
|
||||||
user_id: str,
|
user_id: str,
|
||||||
preset: library_model.CreateLibraryAgentPresetRequest,
|
preset: library_model.LibraryAgentPresetCreatable,
|
||||||
preset_id: Optional[str] = None,
|
|
||||||
) -> library_model.LibraryAgentPreset:
|
) -> library_model.LibraryAgentPreset:
|
||||||
"""
|
"""
|
||||||
Creates or updates an AgentPreset for a user.
|
Creates a new AgentPreset for a user.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
user_id: The ID of the user creating/updating the preset.
|
user_id: The ID of the user creating the preset.
|
||||||
preset: The preset data used for creation or update.
|
preset: The preset data used for creation.
|
||||||
preset_id: An optional preset ID to update; if None, a new preset is created.
|
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
The newly created or updated LibraryAgentPreset.
|
The newly created LibraryAgentPreset.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
DatabaseError: If there's a database error in creating or updating the preset.
|
DatabaseError: If there's a database error in creating the preset.
|
||||||
|
"""
|
||||||
|
logger.debug(
|
||||||
|
f"Creating preset ({repr(preset.name)}) for user #{user_id}",
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
new_preset = await prisma.models.AgentPreset.prisma().create(
|
||||||
|
data=prisma.types.AgentPresetCreateInput(
|
||||||
|
userId=user_id,
|
||||||
|
name=preset.name,
|
||||||
|
description=preset.description,
|
||||||
|
agentGraphId=preset.graph_id,
|
||||||
|
agentGraphVersion=preset.graph_version,
|
||||||
|
isActive=preset.is_active,
|
||||||
|
InputPresets={
|
||||||
|
"create": [
|
||||||
|
prisma.types.AgentNodeExecutionInputOutputCreateWithoutRelationsInput( # noqa
|
||||||
|
name=name, data=prisma.fields.Json(data)
|
||||||
|
)
|
||||||
|
for name, data in preset.inputs.items()
|
||||||
|
]
|
||||||
|
},
|
||||||
|
),
|
||||||
|
include={"InputPresets": True},
|
||||||
|
)
|
||||||
|
return library_model.LibraryAgentPreset.from_db(new_preset)
|
||||||
|
except prisma.errors.PrismaError as e:
|
||||||
|
logger.error(f"Database error creating preset: {e}")
|
||||||
|
raise store_exceptions.DatabaseError("Failed to create preset") from e
|
||||||
|
|
||||||
|
|
||||||
|
async def create_preset_from_graph_execution(
|
||||||
|
user_id: str,
|
||||||
|
create_request: library_model.LibraryAgentPresetCreatableFromGraphExecution,
|
||||||
|
) -> library_model.LibraryAgentPreset:
|
||||||
|
"""
|
||||||
|
Creates a new AgentPreset from an AgentGraphExecution.
|
||||||
|
|
||||||
|
Params:
|
||||||
|
user_id: The ID of the user creating the preset.
|
||||||
|
create_request: The data used for creation.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The newly created LibraryAgentPreset.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
DatabaseError: If there's a database error in creating the preset.
|
||||||
|
"""
|
||||||
|
graph_exec_id = create_request.graph_execution_id
|
||||||
|
graph_execution = await get_graph_execution(user_id, graph_exec_id)
|
||||||
|
if not graph_execution:
|
||||||
|
raise NotFoundError(f"Graph execution #{graph_exec_id} not found")
|
||||||
|
|
||||||
|
logger.debug(
|
||||||
|
f"Creating preset for user #{user_id} from graph execution #{graph_exec_id}",
|
||||||
|
)
|
||||||
|
return await create_preset(
|
||||||
|
user_id=user_id,
|
||||||
|
preset=library_model.LibraryAgentPresetCreatable(
|
||||||
|
inputs=graph_execution.inputs,
|
||||||
|
graph_id=graph_execution.graph_id,
|
||||||
|
graph_version=graph_execution.graph_version,
|
||||||
|
name=create_request.name,
|
||||||
|
description=create_request.description,
|
||||||
|
is_active=create_request.is_active,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def update_preset(
|
||||||
|
user_id: str,
|
||||||
|
preset_id: str,
|
||||||
|
preset: library_model.LibraryAgentPresetUpdatable,
|
||||||
|
) -> library_model.LibraryAgentPreset:
|
||||||
|
"""
|
||||||
|
Updates an existing AgentPreset for a user.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
user_id: The ID of the user updating the preset.
|
||||||
|
preset_id: The ID of the preset to update.
|
||||||
|
preset: The preset data used for the update.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The updated LibraryAgentPreset.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
DatabaseError: If there's a database error in updating the preset.
|
||||||
ValueError: If attempting to update a non-existent preset.
|
ValueError: If attempting to update a non-existent preset.
|
||||||
"""
|
"""
|
||||||
logger.debug(
|
logger.debug(
|
||||||
f"Upserting preset #{preset_id} ({repr(preset.name)}) for user #{user_id}",
|
f"Updating preset #{preset_id} ({repr(preset.name)}) for user #{user_id}",
|
||||||
)
|
)
|
||||||
try:
|
try:
|
||||||
inputs = [
|
update_data: prisma.types.AgentPresetUpdateInput = {}
|
||||||
prisma.types.AgentNodeExecutionInputOutputCreateWithoutRelationsInput(
|
if preset.name:
|
||||||
name=name, data=prisma.fields.Json(data)
|
update_data["name"] = preset.name
|
||||||
)
|
if preset.description:
|
||||||
for name, data in preset.inputs.items()
|
update_data["description"] = preset.description
|
||||||
]
|
if preset.inputs:
|
||||||
if preset_id:
|
update_data["InputPresets"] = {
|
||||||
# Update existing preset
|
"create": [
|
||||||
updated = await prisma.models.AgentPreset.prisma().update(
|
prisma.types.AgentNodeExecutionInputOutputCreateWithoutRelationsInput( # noqa
|
||||||
where={"id": preset_id},
|
name=name, data=prisma.fields.Json(data)
|
||||||
data={
|
)
|
||||||
"name": preset.name,
|
for name, data in preset.inputs.items()
|
||||||
"description": preset.description,
|
]
|
||||||
"isActive": preset.is_active,
|
}
|
||||||
"InputPresets": {"create": inputs},
|
if preset.is_active:
|
||||||
},
|
update_data["isActive"] = preset.is_active
|
||||||
include={"InputPresets": True},
|
|
||||||
)
|
updated = await prisma.models.AgentPreset.prisma().update(
|
||||||
if not updated:
|
where={"id": preset_id},
|
||||||
raise ValueError(f"AgentPreset #{preset_id} not found")
|
data=update_data,
|
||||||
return library_model.LibraryAgentPreset.from_db(updated)
|
include={"InputPresets": True},
|
||||||
else:
|
)
|
||||||
# Create new preset
|
if not updated:
|
||||||
new_preset = await prisma.models.AgentPreset.prisma().create(
|
raise ValueError(f"AgentPreset #{preset_id} not found")
|
||||||
data=prisma.types.AgentPresetCreateInput(
|
return library_model.LibraryAgentPreset.from_db(updated)
|
||||||
userId=user_id,
|
|
||||||
name=preset.name,
|
|
||||||
description=preset.description,
|
|
||||||
agentGraphId=preset.graph_id,
|
|
||||||
agentGraphVersion=preset.graph_version,
|
|
||||||
isActive=preset.is_active,
|
|
||||||
InputPresets={"create": inputs},
|
|
||||||
),
|
|
||||||
include={"InputPresets": True},
|
|
||||||
)
|
|
||||||
return library_model.LibraryAgentPreset.from_db(new_preset)
|
|
||||||
except prisma.errors.PrismaError as e:
|
except prisma.errors.PrismaError as e:
|
||||||
logger.error(f"Database error upserting preset: {e}")
|
logger.error(f"Database error updating preset: {e}")
|
||||||
raise store_exceptions.DatabaseError("Failed to create preset") from e
|
raise store_exceptions.DatabaseError("Failed to update preset") from e
|
||||||
|
|
||||||
|
|
||||||
async def delete_preset(user_id: str, preset_id: str) -> None:
|
async def delete_preset(user_id: str, preset_id: str) -> None:
|
||||||
|
|||||||
@@ -168,27 +168,62 @@ class LibraryAgentResponse(pydantic.BaseModel):
|
|||||||
pagination: server_model.Pagination
|
pagination: server_model.Pagination
|
||||||
|
|
||||||
|
|
||||||
class LibraryAgentPreset(pydantic.BaseModel):
|
class LibraryAgentPresetCreatable(pydantic.BaseModel):
|
||||||
|
"""
|
||||||
|
Request model used when creating a new preset for a library agent.
|
||||||
|
"""
|
||||||
|
|
||||||
|
graph_id: str
|
||||||
|
graph_version: int
|
||||||
|
|
||||||
|
inputs: block_model.BlockInput
|
||||||
|
|
||||||
|
name: str
|
||||||
|
description: str
|
||||||
|
|
||||||
|
is_active: bool = True
|
||||||
|
|
||||||
|
|
||||||
|
class LibraryAgentPresetCreatableFromGraphExecution(pydantic.BaseModel):
|
||||||
|
"""
|
||||||
|
Request model used when creating a new preset for a library agent.
|
||||||
|
"""
|
||||||
|
|
||||||
|
graph_execution_id: str
|
||||||
|
|
||||||
|
name: str
|
||||||
|
description: str
|
||||||
|
|
||||||
|
is_active: bool = True
|
||||||
|
|
||||||
|
|
||||||
|
class LibraryAgentPresetUpdatable(pydantic.BaseModel):
|
||||||
|
"""
|
||||||
|
Request model used when updating a preset for a library agent.
|
||||||
|
"""
|
||||||
|
|
||||||
|
inputs: Optional[block_model.BlockInput] = None
|
||||||
|
|
||||||
|
name: Optional[str] = None
|
||||||
|
description: Optional[str] = None
|
||||||
|
|
||||||
|
is_active: Optional[bool] = None
|
||||||
|
|
||||||
|
|
||||||
|
class LibraryAgentPreset(LibraryAgentPresetCreatable):
|
||||||
"""Represents a preset configuration for a library agent."""
|
"""Represents a preset configuration for a library agent."""
|
||||||
|
|
||||||
id: str
|
id: str
|
||||||
updated_at: datetime.datetime
|
updated_at: datetime.datetime
|
||||||
|
|
||||||
graph_id: str
|
|
||||||
graph_version: int
|
|
||||||
|
|
||||||
name: str
|
|
||||||
description: str
|
|
||||||
|
|
||||||
is_active: bool
|
|
||||||
|
|
||||||
inputs: block_model.BlockInput
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_db(cls, preset: prisma.models.AgentPreset) -> "LibraryAgentPreset":
|
def from_db(cls, preset: prisma.models.AgentPreset) -> "LibraryAgentPreset":
|
||||||
|
if preset.InputPresets is None:
|
||||||
|
raise ValueError("Input values must be included in object")
|
||||||
|
|
||||||
input_data: block_model.BlockInput = {}
|
input_data: block_model.BlockInput = {}
|
||||||
|
|
||||||
for preset_input in preset.InputPresets or []:
|
for preset_input in preset.InputPresets:
|
||||||
input_data[preset_input.name] = preset_input.data
|
input_data[preset_input.name] = preset_input.data
|
||||||
|
|
||||||
return cls(
|
return cls(
|
||||||
@@ -210,19 +245,6 @@ class LibraryAgentPresetResponse(pydantic.BaseModel):
|
|||||||
pagination: server_model.Pagination
|
pagination: server_model.Pagination
|
||||||
|
|
||||||
|
|
||||||
class CreateLibraryAgentPresetRequest(pydantic.BaseModel):
|
|
||||||
"""
|
|
||||||
Request model used when creating a new preset for a library agent.
|
|
||||||
"""
|
|
||||||
|
|
||||||
name: str
|
|
||||||
description: str
|
|
||||||
inputs: block_model.BlockInput
|
|
||||||
graph_id: str
|
|
||||||
graph_version: int
|
|
||||||
is_active: bool
|
|
||||||
|
|
||||||
|
|
||||||
class LibraryAgentFilter(str, Enum):
|
class LibraryAgentFilter(str, Enum):
|
||||||
"""Possible filters for searching library agents."""
|
"""Possible filters for searching library agents."""
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +1,15 @@
|
|||||||
import logging
|
import logging
|
||||||
from typing import Annotated, Any
|
from typing import Annotated, Any, Optional
|
||||||
|
|
||||||
import autogpt_libs.auth as autogpt_auth_lib
|
import autogpt_libs.auth as autogpt_auth_lib
|
||||||
import autogpt_libs.utils.cache
|
import autogpt_libs.utils.cache
|
||||||
from fastapi import APIRouter, Body, Depends, HTTPException, status
|
from fastapi import APIRouter, Body, Depends, HTTPException, Query, status
|
||||||
|
|
||||||
import backend.executor
|
import backend.executor
|
||||||
import backend.server.v2.library.db as db
|
import backend.server.v2.library.db as db
|
||||||
import backend.server.v2.library.model as models
|
import backend.server.v2.library.model as models
|
||||||
import backend.util.service
|
import backend.util.service
|
||||||
|
from backend.util.exceptions import NotFoundError
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -26,10 +27,13 @@ def execution_manager_client() -> backend.executor.ExecutionManager:
|
|||||||
summary="List presets",
|
summary="List presets",
|
||||||
description="Retrieve a paginated list of presets for the current user.",
|
description="Retrieve a paginated list of presets for the current user.",
|
||||||
)
|
)
|
||||||
async def get_presets(
|
async def list_presets(
|
||||||
user_id: str = Depends(autogpt_auth_lib.depends.get_user_id),
|
user_id: str = Depends(autogpt_auth_lib.depends.get_user_id),
|
||||||
page: int = 1,
|
page: int = Query(default=1, ge=1),
|
||||||
page_size: int = 10,
|
page_size: int = Query(default=10, ge=1),
|
||||||
|
graph_id: Optional[str] = Query(
|
||||||
|
description="Allows to filter presets by a specific agent graph"
|
||||||
|
),
|
||||||
) -> models.LibraryAgentPresetResponse:
|
) -> models.LibraryAgentPresetResponse:
|
||||||
"""
|
"""
|
||||||
Retrieve a paginated list of presets for the current user.
|
Retrieve a paginated list of presets for the current user.
|
||||||
@@ -38,12 +42,18 @@ async def get_presets(
|
|||||||
user_id (str): ID of the authenticated user.
|
user_id (str): ID of the authenticated user.
|
||||||
page (int): Page number for pagination.
|
page (int): Page number for pagination.
|
||||||
page_size (int): Number of items per page.
|
page_size (int): Number of items per page.
|
||||||
|
graph_id: Allows to filter presets by a specific agent graph.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
models.LibraryAgentPresetResponse: A response containing the list of presets.
|
models.LibraryAgentPresetResponse: A response containing the list of presets.
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
return await db.get_presets(user_id, page, page_size)
|
return await db.list_presets(
|
||||||
|
user_id=user_id,
|
||||||
|
graph_id=graph_id,
|
||||||
|
page=page,
|
||||||
|
page_size=page_size,
|
||||||
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.exception(f"Exception occurred while getting presets: {e}")
|
logger.exception(f"Exception occurred while getting presets: {e}")
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
@@ -96,14 +106,17 @@ async def get_preset(
|
|||||||
description="Create a new preset for the current user.",
|
description="Create a new preset for the current user.",
|
||||||
)
|
)
|
||||||
async def create_preset(
|
async def create_preset(
|
||||||
preset: models.CreateLibraryAgentPresetRequest,
|
preset: (
|
||||||
|
models.LibraryAgentPresetCreatable
|
||||||
|
| models.LibraryAgentPresetCreatableFromGraphExecution
|
||||||
|
),
|
||||||
user_id: str = Depends(autogpt_auth_lib.depends.get_user_id),
|
user_id: str = Depends(autogpt_auth_lib.depends.get_user_id),
|
||||||
) -> models.LibraryAgentPreset:
|
) -> models.LibraryAgentPreset:
|
||||||
"""
|
"""
|
||||||
Create a new library agent preset. Automatically corrects node_input format if needed.
|
Create a new library agent preset. Automatically corrects node_input format if needed.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
preset (models.CreateLibraryAgentPresetRequest): The preset data to create.
|
preset (models.LibraryAgentPresetCreatable): The preset data to create.
|
||||||
user_id (str): ID of the authenticated user.
|
user_id (str): ID of the authenticated user.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
@@ -113,7 +126,12 @@ async def create_preset(
|
|||||||
HTTPException: If an error occurs while creating the preset.
|
HTTPException: If an error occurs while creating the preset.
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
return await db.upsert_preset(user_id, preset)
|
if isinstance(preset, models.LibraryAgentPresetCreatable):
|
||||||
|
return await db.create_preset(user_id, preset)
|
||||||
|
else:
|
||||||
|
return await db.create_preset_from_graph_execution(user_id, preset)
|
||||||
|
except NotFoundError as e:
|
||||||
|
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(e))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.exception(f"Exception occurred while creating preset: {e}")
|
logger.exception(f"Exception occurred while creating preset: {e}")
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
@@ -122,22 +140,22 @@ async def create_preset(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@router.put(
|
@router.patch(
|
||||||
"/presets/{preset_id}",
|
"/presets/{preset_id}",
|
||||||
summary="Update an existing preset",
|
summary="Update an existing preset",
|
||||||
description="Update an existing preset by its ID.",
|
description="Update an existing preset by its ID.",
|
||||||
)
|
)
|
||||||
async def update_preset(
|
async def update_preset(
|
||||||
preset_id: str,
|
preset_id: str,
|
||||||
preset: models.CreateLibraryAgentPresetRequest,
|
preset: models.LibraryAgentPresetUpdatable,
|
||||||
user_id: str = Depends(autogpt_auth_lib.depends.get_user_id),
|
user_id: str = Depends(autogpt_auth_lib.depends.get_user_id),
|
||||||
) -> models.LibraryAgentPreset:
|
) -> models.LibraryAgentPreset:
|
||||||
"""
|
"""
|
||||||
Update an existing library agent preset. If the preset doesn't exist, it may be created.
|
Update an existing library agent preset.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
preset_id (str): ID of the preset to update.
|
preset_id (str): ID of the preset to update.
|
||||||
preset (models.CreateLibraryAgentPresetRequest): The preset data to update.
|
preset (models.LibraryAgentPresetUpdatable): The preset data to update.
|
||||||
user_id (str): ID of the authenticated user.
|
user_id (str): ID of the authenticated user.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
@@ -147,7 +165,9 @@ async def update_preset(
|
|||||||
HTTPException: If an error occurs while updating the preset.
|
HTTPException: If an error occurs while updating the preset.
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
return await db.upsert_preset(user_id, preset, preset_id)
|
return await db.update_preset(
|
||||||
|
user_id=user_id, preset_id=preset_id, preset=preset
|
||||||
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.exception(f"Exception occurred whilst updating preset: {e}")
|
logger.exception(f"Exception occurred whilst updating preset: {e}")
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
|
|||||||
@@ -357,7 +357,7 @@ async def test_execute_preset(server: SpinTestServer):
|
|||||||
test_graph = await create_graph(server, test_graph, test_user)
|
test_graph = await create_graph(server, test_graph, test_user)
|
||||||
|
|
||||||
# Create preset with initial values
|
# Create preset with initial values
|
||||||
preset = backend.server.v2.library.model.CreateLibraryAgentPresetRequest(
|
preset = backend.server.v2.library.model.LibraryAgentPresetCreatable(
|
||||||
name="Test Preset With Clash",
|
name="Test Preset With Clash",
|
||||||
description="Test preset with clashing input values",
|
description="Test preset with clashing input values",
|
||||||
graph_id=test_graph.id,
|
graph_id=test_graph.id,
|
||||||
@@ -446,7 +446,7 @@ async def test_execute_preset_with_clash(server: SpinTestServer):
|
|||||||
test_graph = await create_graph(server, test_graph, test_user)
|
test_graph = await create_graph(server, test_graph, test_user)
|
||||||
|
|
||||||
# Create preset with initial values
|
# Create preset with initial values
|
||||||
preset = backend.server.v2.library.model.CreateLibraryAgentPresetRequest(
|
preset = backend.server.v2.library.model.LibraryAgentPresetCreatable(
|
||||||
name="Test Preset With Clash",
|
name="Test Preset With Clash",
|
||||||
description="Test preset with clashing input values",
|
description="Test preset with clashing input values",
|
||||||
graph_id=test_graph.id,
|
graph_id=test_graph.id,
|
||||||
|
|||||||
@@ -10,16 +10,12 @@ from prisma.types import (
|
|||||||
AgentGraphCreateInput,
|
AgentGraphCreateInput,
|
||||||
AgentNodeCreateInput,
|
AgentNodeCreateInput,
|
||||||
AgentNodeLinkCreateInput,
|
AgentNodeLinkCreateInput,
|
||||||
AgentPresetCreateInput,
|
|
||||||
AnalyticsDetailsCreateInput,
|
AnalyticsDetailsCreateInput,
|
||||||
AnalyticsMetricsCreateInput,
|
AnalyticsMetricsCreateInput,
|
||||||
APIKeyCreateInput,
|
APIKeyCreateInput,
|
||||||
CreditTransactionCreateInput,
|
CreditTransactionCreateInput,
|
||||||
LibraryAgentCreateInput,
|
|
||||||
ProfileCreateInput,
|
ProfileCreateInput,
|
||||||
StoreListingCreateInput,
|
|
||||||
StoreListingReviewCreateInput,
|
StoreListingReviewCreateInput,
|
||||||
StoreListingVersionCreateInput,
|
|
||||||
UserCreateInput,
|
UserCreateInput,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ import {
|
|||||||
GraphID,
|
GraphID,
|
||||||
LibraryAgent,
|
LibraryAgent,
|
||||||
LibraryAgentID,
|
LibraryAgentID,
|
||||||
|
LibraryAgentPreset,
|
||||||
|
LibraryAgentPresetID,
|
||||||
Schedule,
|
Schedule,
|
||||||
ScheduleID,
|
ScheduleID,
|
||||||
} from "@/lib/autogpt-server-api";
|
} from "@/lib/autogpt-server-api";
|
||||||
@@ -23,6 +25,20 @@ import AgentRunDetailsView from "@/components/agents/agent-run-details-view";
|
|||||||
import AgentRunsSelectorList from "@/components/agents/agent-runs-selector-list";
|
import AgentRunsSelectorList from "@/components/agents/agent-runs-selector-list";
|
||||||
import AgentScheduleDetailsView from "@/components/agents/agent-schedule-details-view";
|
import AgentScheduleDetailsView from "@/components/agents/agent-schedule-details-view";
|
||||||
|
|
||||||
|
export type AgentRunsViewSelection =
|
||||||
|
| {
|
||||||
|
type: "run";
|
||||||
|
id?: GraphExecutionID;
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
type: "preset";
|
||||||
|
id: LibraryAgentPresetID;
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
type: "schedule";
|
||||||
|
id: ScheduleID;
|
||||||
|
};
|
||||||
|
|
||||||
export default function AgentRunsPage(): React.ReactElement {
|
export default function AgentRunsPage(): React.ReactElement {
|
||||||
const { id: agentID }: { id: LibraryAgentID } = useParams();
|
const { id: agentID }: { id: LibraryAgentID } = useParams();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
@@ -33,11 +49,11 @@ export default function AgentRunsPage(): React.ReactElement {
|
|||||||
const [graph, setGraph] = useState<Graph | null>(null);
|
const [graph, setGraph] = useState<Graph | null>(null);
|
||||||
const [agent, setAgent] = useState<LibraryAgent | null>(null);
|
const [agent, setAgent] = useState<LibraryAgent | null>(null);
|
||||||
const [agentRuns, setAgentRuns] = useState<GraphExecutionMeta[]>([]);
|
const [agentRuns, setAgentRuns] = useState<GraphExecutionMeta[]>([]);
|
||||||
|
const [agentPresets, setAgentPresets] = useState<LibraryAgentPreset[]>([]);
|
||||||
const [schedules, setSchedules] = useState<Schedule[]>([]);
|
const [schedules, setSchedules] = useState<Schedule[]>([]);
|
||||||
const [selectedView, selectView] = useState<
|
const [selectedView, selectView] = useState<AgentRunsViewSelection>({
|
||||||
| { type: "run"; id?: GraphExecutionID }
|
type: "run",
|
||||||
| { type: "schedule"; id: ScheduleID }
|
});
|
||||||
>({ type: "run" });
|
|
||||||
const [selectedRun, setSelectedRun] = useState<
|
const [selectedRun, setSelectedRun] = useState<
|
||||||
GraphExecution | GraphExecutionMeta | null
|
GraphExecution | GraphExecutionMeta | null
|
||||||
>(null);
|
>(null);
|
||||||
@@ -58,6 +74,10 @@ export default function AgentRunsPage(): React.ReactElement {
|
|||||||
selectView({ type: "run", id });
|
selectView({ type: "run", id });
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const selectPreset = useCallback((id: LibraryAgentPresetID) => {
|
||||||
|
selectView({ type: "preset", id });
|
||||||
|
}, []);
|
||||||
|
|
||||||
const selectSchedule = useCallback((schedule: Schedule) => {
|
const selectSchedule = useCallback((schedule: Schedule) => {
|
||||||
selectView({ type: "schedule", id: schedule.id });
|
selectView({ type: "schedule", id: schedule.id });
|
||||||
setSelectedSchedule(schedule);
|
setSelectedSchedule(schedule);
|
||||||
@@ -151,6 +171,20 @@ export default function AgentRunsPage(): React.ReactElement {
|
|||||||
};
|
};
|
||||||
}, [api, selectedView.id]);
|
}, [api, selectedView.id]);
|
||||||
|
|
||||||
|
const fetchPresets = useCallback(async () => {
|
||||||
|
if (!agent) return;
|
||||||
|
await api
|
||||||
|
.listLibraryAgentPresets({ graph_id: agent.graph_id })
|
||||||
|
.then(
|
||||||
|
(response) =>
|
||||||
|
setAgentPresets(response.presets) /* TODO: handle pagination */,
|
||||||
|
);
|
||||||
|
}, [api, agent]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
fetchPresets();
|
||||||
|
}, [fetchPresets]);
|
||||||
|
|
||||||
// load selectedRun based on selectedView
|
// load selectedRun based on selectedView
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (selectedView.type != "run" || !selectedView.id || !agent) return;
|
if (selectedView.type != "run" || !selectedView.id || !agent) return;
|
||||||
@@ -221,6 +255,19 @@ export default function AgentRunsPage(): React.ReactElement {
|
|||||||
[api, agent],
|
[api, agent],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const createPresetFromRun = useCallback(
|
||||||
|
async (run: GraphExecutionMeta) => {
|
||||||
|
const createdPreset = await api.createLibraryAgentPreset({
|
||||||
|
/* FIXME: add dialog to enter name and description */
|
||||||
|
name: agent!.name,
|
||||||
|
description: agent!.description,
|
||||||
|
graph_execution_id: run.id,
|
||||||
|
});
|
||||||
|
setAgentPresets((prev) => [...prev, createdPreset]);
|
||||||
|
},
|
||||||
|
[agent, api],
|
||||||
|
);
|
||||||
|
|
||||||
const agentActions: ButtonAction[] = useMemo(
|
const agentActions: ButtonAction[] = useMemo(
|
||||||
() => [
|
() => [
|
||||||
...(agent?.can_access_graph
|
...(agent?.can_access_graph
|
||||||
@@ -254,14 +301,18 @@ export default function AgentRunsPage(): React.ReactElement {
|
|||||||
className="agpt-div w-full border-b lg:w-auto lg:border-b-0 lg:border-r"
|
className="agpt-div w-full border-b lg:w-auto lg:border-b-0 lg:border-r"
|
||||||
agent={agent}
|
agent={agent}
|
||||||
agentRuns={agentRuns}
|
agentRuns={agentRuns}
|
||||||
|
agentPresets={agentPresets}
|
||||||
schedules={schedules}
|
schedules={schedules}
|
||||||
selectedView={selectedView}
|
selectedView={selectedView}
|
||||||
allowDraftNewRun={!graph.has_webhook_trigger}
|
allowDraftNewRun={!graph.has_webhook_trigger}
|
||||||
onSelectRun={selectRun}
|
onSelectRun={selectRun}
|
||||||
|
onSelectPreset={selectPreset}
|
||||||
onSelectSchedule={selectSchedule}
|
onSelectSchedule={selectSchedule}
|
||||||
onSelectDraftNewRun={openRunDraftView}
|
onSelectDraftNewRun={openRunDraftView}
|
||||||
|
onPinAsPreset={createPresetFromRun}
|
||||||
onDeleteRun={setConfirmingDeleteAgentRun}
|
onDeleteRun={setConfirmingDeleteAgentRun}
|
||||||
onDeleteSchedule={(id) => deleteSchedule(id)}
|
// TODO: onDeletePreset={deletePreset}
|
||||||
|
onDeleteSchedule={deleteSchedule}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div className="flex-1">
|
<div className="flex-1">
|
||||||
@@ -290,6 +341,25 @@ export default function AgentRunsPage(): React.ReactElement {
|
|||||||
<AgentRunDraftView
|
<AgentRunDraftView
|
||||||
graph={graph}
|
graph={graph}
|
||||||
onRun={(runID) => selectRun(runID)}
|
onRun={(runID) => selectRun(runID)}
|
||||||
|
onSavePreset={(preset) => {
|
||||||
|
setAgentPresets((prev) => [...prev, preset]);
|
||||||
|
selectPreset(preset.id);
|
||||||
|
}}
|
||||||
|
agentActions={agentActions}
|
||||||
|
/>
|
||||||
|
) : selectedView.type == "preset" ? (
|
||||||
|
<AgentRunDraftView
|
||||||
|
graph={graph}
|
||||||
|
preset={agentPresets.find((ap) => ap.id == selectedView.id)!}
|
||||||
|
onRun={(runID) => selectRun(runID)}
|
||||||
|
onSavePreset={(preset) =>
|
||||||
|
setAgentPresets((prev) =>
|
||||||
|
prev.with(
|
||||||
|
agentPresets.findIndex((ap) => ap.id == preset.id),
|
||||||
|
preset,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
agentActions={agentActions}
|
agentActions={agentActions}
|
||||||
/>
|
/>
|
||||||
) : selectedView.type == "schedule" ? (
|
) : selectedView.type == "schedule" ? (
|
||||||
|
|||||||
@@ -1,8 +1,12 @@
|
|||||||
"use client";
|
"use client";
|
||||||
import React, { useCallback, useMemo, useState } from "react";
|
import React, { useCallback, useEffect, useMemo, useState } from "react";
|
||||||
|
|
||||||
import { useBackendAPI } from "@/lib/autogpt-server-api/context";
|
import { useBackendAPI } from "@/lib/autogpt-server-api/context";
|
||||||
import { GraphExecutionID, GraphMeta } from "@/lib/autogpt-server-api";
|
import {
|
||||||
|
GraphExecutionID,
|
||||||
|
GraphMeta,
|
||||||
|
LibraryAgentPreset,
|
||||||
|
} from "@/lib/autogpt-server-api";
|
||||||
|
|
||||||
import type { ButtonAction } from "@/components/agptui/types";
|
import type { ButtonAction } from "@/components/agptui/types";
|
||||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||||
@@ -11,14 +15,19 @@ import { useToastOnFail } from "@/components/ui/use-toast";
|
|||||||
import ActionButtonGroup from "@/components/agptui/action-button-group";
|
import ActionButtonGroup from "@/components/agptui/action-button-group";
|
||||||
import SchemaTooltip from "@/components/SchemaTooltip";
|
import SchemaTooltip from "@/components/SchemaTooltip";
|
||||||
import { IconPlay } from "@/components/ui/icons";
|
import { IconPlay } from "@/components/ui/icons";
|
||||||
|
import { deepEquals } from "@/lib/utils";
|
||||||
|
|
||||||
export default function AgentRunDraftView({
|
export default function AgentRunDraftView({
|
||||||
graph,
|
graph,
|
||||||
|
preset,
|
||||||
onRun,
|
onRun,
|
||||||
|
onSavePreset,
|
||||||
agentActions,
|
agentActions,
|
||||||
}: {
|
}: {
|
||||||
graph: GraphMeta;
|
graph: GraphMeta;
|
||||||
|
preset?: LibraryAgentPreset;
|
||||||
onRun: (runID: GraphExecutionID) => void;
|
onRun: (runID: GraphExecutionID) => void;
|
||||||
|
onSavePreset: (preset: LibraryAgentPreset) => void;
|
||||||
agentActions: ButtonAction[];
|
agentActions: ButtonAction[];
|
||||||
}): React.ReactNode {
|
}): React.ReactNode {
|
||||||
const api = useBackendAPI();
|
const api = useBackendAPI();
|
||||||
@@ -27,6 +36,17 @@ export default function AgentRunDraftView({
|
|||||||
const agentInputs = graph.input_schema.properties;
|
const agentInputs = graph.input_schema.properties;
|
||||||
const [inputValues, setInputValues] = useState<Record<string, any>>({});
|
const [inputValues, setInputValues] = useState<Record<string, any>>({});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (preset == undefined) {
|
||||||
|
setInputValues({});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (deepEquals(preset.inputs, inputValues)) return;
|
||||||
|
setInputValues(preset.inputs);
|
||||||
|
// Sets `inputValues` once if `preset` is changed.
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, [preset]);
|
||||||
|
|
||||||
const doRun = useCallback(
|
const doRun = useCallback(
|
||||||
() =>
|
() =>
|
||||||
api
|
api
|
||||||
@@ -36,6 +56,34 @@ export default function AgentRunDraftView({
|
|||||||
[api, graph, inputValues, onRun, toastOnFail],
|
[api, graph, inputValues, onRun, toastOnFail],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const savePreset = useCallback(
|
||||||
|
() =>
|
||||||
|
(preset
|
||||||
|
? // Update existing preset
|
||||||
|
api.updateLibraryAgentPreset(preset.id, {
|
||||||
|
...preset, // TODO: update specific attributes
|
||||||
|
inputs: inputValues,
|
||||||
|
})
|
||||||
|
: // Save run draft as new preset
|
||||||
|
api.createLibraryAgentPreset({
|
||||||
|
graph_id: graph.id,
|
||||||
|
graph_version: graph.version,
|
||||||
|
name: graph.name,
|
||||||
|
description: "", // TODO: add dialog for name + description
|
||||||
|
inputs: inputValues,
|
||||||
|
})
|
||||||
|
).then(onSavePreset),
|
||||||
|
[
|
||||||
|
preset,
|
||||||
|
api,
|
||||||
|
inputValues,
|
||||||
|
graph.id,
|
||||||
|
graph.version,
|
||||||
|
graph.name,
|
||||||
|
onSavePreset,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
const runActions: ButtonAction[] = useMemo(
|
const runActions: ButtonAction[] = useMemo(
|
||||||
() => [
|
() => [
|
||||||
{
|
{
|
||||||
@@ -48,8 +96,12 @@ export default function AgentRunDraftView({
|
|||||||
variant: "accent",
|
variant: "accent",
|
||||||
callback: doRun,
|
callback: doRun,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
label: preset ? "Save preset" : "Save as a preset",
|
||||||
|
callback: savePreset,
|
||||||
|
},
|
||||||
],
|
],
|
||||||
[doRun],
|
[doRun, preset, savePreset],
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
|
import { cn } from "@/lib/utils";
|
||||||
import { Badge } from "@/components/ui/badge";
|
import { Badge } from "@/components/ui/badge";
|
||||||
|
|
||||||
import { GraphExecutionMeta } from "@/lib/autogpt-server-api/types";
|
import { GraphExecutionMeta } from "@/lib/autogpt-server-api/types";
|
||||||
@@ -22,7 +23,6 @@ export const agentRunStatusMap: Record<
|
|||||||
QUEUED: "queued",
|
QUEUED: "queued",
|
||||||
RUNNING: "running",
|
RUNNING: "running",
|
||||||
TERMINATED: "stopped",
|
TERMINATED: "stopped",
|
||||||
// TODO: implement "draft" - https://github.com/Significant-Gravitas/AutoGPT/issues/9168
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const statusData: Record<
|
const statusData: Record<
|
||||||
@@ -51,13 +51,19 @@ const statusStyles = {
|
|||||||
|
|
||||||
export default function AgentRunStatusChip({
|
export default function AgentRunStatusChip({
|
||||||
status,
|
status,
|
||||||
|
className,
|
||||||
}: {
|
}: {
|
||||||
status: AgentRunStatus;
|
status: AgentRunStatus;
|
||||||
|
className?: string;
|
||||||
}): React.ReactElement {
|
}): React.ReactElement {
|
||||||
return (
|
return (
|
||||||
<Badge
|
<Badge
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
className={`text-xs font-medium ${statusStyles[statusData[status].variant]} rounded-[45px] px-[9px] py-[3px]`}
|
className={cn(
|
||||||
|
"rounded-[45px] px-[9px] py-[3px] text-xs font-medium",
|
||||||
|
statusStyles[statusData[status].variant],
|
||||||
|
className,
|
||||||
|
)}
|
||||||
>
|
>
|
||||||
{statusData[status].label}
|
{statusData[status].label}
|
||||||
</Badge>
|
</Badge>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
import { MoreVertical } from "lucide-react";
|
import { MoreVertical, PinIcon } from "lucide-react";
|
||||||
|
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
|
|
||||||
@@ -17,23 +17,28 @@ import AgentRunStatusChip, {
|
|||||||
AgentRunStatus,
|
AgentRunStatus,
|
||||||
} from "@/components/agents/agent-run-status-chip";
|
} from "@/components/agents/agent-run-status-chip";
|
||||||
|
|
||||||
export type AgentRunSummaryProps = {
|
export type AgentRunSummaryProps = (
|
||||||
status: AgentRunStatus;
|
| { type: "run"; status: AgentRunStatus }
|
||||||
|
| { type: "preset" | "schedule"; status?: undefined }
|
||||||
|
) & {
|
||||||
title: string;
|
title: string;
|
||||||
timestamp: number | Date;
|
timestamp?: number | Date;
|
||||||
selected?: boolean;
|
selected?: boolean;
|
||||||
onClick?: () => void;
|
onClick?: () => void;
|
||||||
|
onPinAsPreset?: () => void;
|
||||||
// onRename: () => void;
|
// onRename: () => void;
|
||||||
onDelete: () => void;
|
onDelete?: () => void;
|
||||||
className?: string;
|
className?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function AgentRunSummaryCard({
|
export default function AgentRunSummaryCard({
|
||||||
|
type,
|
||||||
status,
|
status,
|
||||||
title,
|
title,
|
||||||
timestamp,
|
timestamp,
|
||||||
selected = false,
|
selected = false,
|
||||||
onClick,
|
onClick,
|
||||||
|
onPinAsPreset,
|
||||||
// onRename,
|
// onRename,
|
||||||
onDelete,
|
onDelete,
|
||||||
className,
|
className,
|
||||||
@@ -48,9 +53,17 @@ export default function AgentRunSummaryCard({
|
|||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
>
|
>
|
||||||
<CardContent className="relative p-2.5 lg:p-4">
|
<CardContent className="relative p-2.5 lg:p-4">
|
||||||
<AgentRunStatusChip status={status} />
|
{type == "run" ? (
|
||||||
|
<AgentRunStatusChip status={status} />
|
||||||
|
) : type == "schedule" ? (
|
||||||
|
<AgentRunStatusChip status="scheduled" />
|
||||||
|
) : (
|
||||||
|
<div className="flex items-center text-sm text-neutral-700">
|
||||||
|
<PinIcon className="mr-2 size-4" /> Template run
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
<div className="mt-5 flex items-center justify-between">
|
<div className="mt-3 flex items-center justify-between">
|
||||||
<h3 className="truncate pr-2 text-base font-medium text-neutral-900">
|
<h3 className="truncate pr-2 text-base font-medium text-neutral-900">
|
||||||
{title}
|
{title}
|
||||||
</h3>
|
</h3>
|
||||||
@@ -62,25 +75,30 @@ export default function AgentRunSummaryCard({
|
|||||||
</Button>
|
</Button>
|
||||||
</DropdownMenuTrigger>
|
</DropdownMenuTrigger>
|
||||||
<DropdownMenuContent>
|
<DropdownMenuContent>
|
||||||
{/* {onPinAsPreset && (
|
{onPinAsPreset && (
|
||||||
<DropdownMenuItem onClick={onPinAsPreset}>
|
<DropdownMenuItem onClick={onPinAsPreset}>
|
||||||
Pin as a preset
|
Pin as a preset
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
)} */}
|
)}
|
||||||
|
|
||||||
{/* <DropdownMenuItem onClick={onRename}>Rename</DropdownMenuItem> */}
|
{/* <DropdownMenuItem onClick={onRename}>Rename</DropdownMenuItem> */}
|
||||||
|
|
||||||
<DropdownMenuItem onClick={onDelete}>Delete</DropdownMenuItem>
|
{onDelete && (
|
||||||
|
<DropdownMenuItem onClick={onDelete}>Delete</DropdownMenuItem>
|
||||||
|
)}
|
||||||
</DropdownMenuContent>
|
</DropdownMenuContent>
|
||||||
</DropdownMenu>
|
</DropdownMenu>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p
|
{timestamp && (
|
||||||
className="mt-1 text-sm font-normal text-neutral-500"
|
<p
|
||||||
title={moment(timestamp).toString()}
|
className="mt-1 text-sm font-normal text-neutral-500"
|
||||||
>
|
title={moment(timestamp).toString()}
|
||||||
Ran {moment(timestamp).fromNow()}
|
>
|
||||||
</p>
|
{{ run: "Ran", schedule: "Next run", preset: "Last updated" }[type]}{" "}
|
||||||
|
{moment(timestamp).fromNow()}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ import {
|
|||||||
GraphExecutionID,
|
GraphExecutionID,
|
||||||
GraphExecutionMeta,
|
GraphExecutionMeta,
|
||||||
LibraryAgent,
|
LibraryAgent,
|
||||||
|
LibraryAgentPreset,
|
||||||
|
LibraryAgentPresetID,
|
||||||
Schedule,
|
Schedule,
|
||||||
ScheduleID,
|
ScheduleID,
|
||||||
} from "@/lib/autogpt-server-api";
|
} from "@/lib/autogpt-server-api";
|
||||||
@@ -15,34 +17,43 @@ import { ScrollArea } from "@/components/ui/scroll-area";
|
|||||||
import { Button } from "@/components/agptui/Button";
|
import { Button } from "@/components/agptui/Button";
|
||||||
import { Badge } from "@/components/ui/badge";
|
import { Badge } from "@/components/ui/badge";
|
||||||
|
|
||||||
|
import { AgentRunsViewSelection } from "@/app/library/agents/[id]/page";
|
||||||
import { agentRunStatusMap } from "@/components/agents/agent-run-status-chip";
|
import { agentRunStatusMap } from "@/components/agents/agent-run-status-chip";
|
||||||
import AgentRunSummaryCard from "@/components/agents/agent-run-summary-card";
|
import AgentRunSummaryCard from "@/components/agents/agent-run-summary-card";
|
||||||
|
|
||||||
interface AgentRunsSelectorListProps {
|
interface AgentRunsSelectorListProps {
|
||||||
agent: LibraryAgent;
|
agent: LibraryAgent;
|
||||||
agentRuns: GraphExecutionMeta[];
|
agentRuns: GraphExecutionMeta[];
|
||||||
|
agentPresets: LibraryAgentPreset[];
|
||||||
schedules: Schedule[];
|
schedules: Schedule[];
|
||||||
selectedView: { type: "run" | "schedule"; id?: string };
|
selectedView: AgentRunsViewSelection;
|
||||||
allowDraftNewRun?: boolean;
|
allowDraftNewRun?: boolean;
|
||||||
onSelectRun: (id: GraphExecutionID) => void;
|
onSelectRun: (id: GraphExecutionID) => void;
|
||||||
|
onSelectPreset: (id: LibraryAgentPresetID) => void;
|
||||||
onSelectSchedule: (schedule: Schedule) => void;
|
onSelectSchedule: (schedule: Schedule) => void;
|
||||||
onSelectDraftNewRun: () => void;
|
onSelectDraftNewRun: () => void;
|
||||||
onDeleteRun: (id: GraphExecutionMeta) => void;
|
onDeleteRun: (id: GraphExecutionMeta) => void;
|
||||||
|
// onDeletePreset: (id: LibraryAgentPresetID) => void;
|
||||||
onDeleteSchedule: (id: ScheduleID) => void;
|
onDeleteSchedule: (id: ScheduleID) => void;
|
||||||
|
onPinAsPreset: (run: GraphExecutionMeta) => void;
|
||||||
className?: string;
|
className?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function AgentRunsSelectorList({
|
export default function AgentRunsSelectorList({
|
||||||
agent,
|
agent,
|
||||||
agentRuns,
|
agentRuns,
|
||||||
|
agentPresets,
|
||||||
schedules,
|
schedules,
|
||||||
selectedView,
|
selectedView,
|
||||||
allowDraftNewRun = true,
|
allowDraftNewRun = true,
|
||||||
onSelectRun,
|
onSelectRun,
|
||||||
|
onSelectPreset,
|
||||||
onSelectSchedule,
|
onSelectSchedule,
|
||||||
onSelectDraftNewRun,
|
onSelectDraftNewRun,
|
||||||
onDeleteRun,
|
onDeleteRun,
|
||||||
|
// onDeletePreset,
|
||||||
onDeleteSchedule,
|
onDeleteSchedule,
|
||||||
|
onPinAsPreset,
|
||||||
className,
|
className,
|
||||||
}: AgentRunsSelectorListProps): React.ReactElement {
|
}: AgentRunsSelectorListProps): React.ReactElement {
|
||||||
const [activeListTab, setActiveListTab] = useState<"runs" | "scheduled">(
|
const [activeListTab, setActiveListTab] = useState<"runs" | "scheduled">(
|
||||||
@@ -89,7 +100,7 @@ export default function AgentRunsSelectorList({
|
|||||||
</Badge>
|
</Badge>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Runs / Schedules list */}
|
{/* Runs+Presets / Schedules list */}
|
||||||
<ScrollArea className="lg:h-[calc(100vh-200px)]">
|
<ScrollArea className="lg:h-[calc(100vh-200px)]">
|
||||||
<div className="flex gap-2 lg:flex-col">
|
<div className="flex gap-2 lg:flex-col">
|
||||||
{/* New Run button - only in small layouts */}
|
{/* New Run button - only in small layouts */}
|
||||||
@@ -109,37 +120,61 @@ export default function AgentRunsSelectorList({
|
|||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{activeListTab === "runs"
|
{activeListTab === "runs" ? (
|
||||||
? agentRuns
|
<>
|
||||||
|
{/* Presets */}
|
||||||
|
{agentPresets
|
||||||
|
.toSorted(
|
||||||
|
(a, b) => b.updated_at.getTime() - a.updated_at.getTime(),
|
||||||
|
)
|
||||||
|
.map((preset) => (
|
||||||
|
<AgentRunSummaryCard
|
||||||
|
className="h-28 w-72 lg:h-auto xl:w-80"
|
||||||
|
key={preset.id}
|
||||||
|
type="preset"
|
||||||
|
title={preset.name}
|
||||||
|
selected={selectedView.id === preset.id}
|
||||||
|
onClick={() => onSelectPreset(preset.id)}
|
||||||
|
// onDelete={() => onDeletePreset(preset.id)}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
|
||||||
|
{/* Runs */}
|
||||||
|
{agentRuns
|
||||||
.toSorted(
|
.toSorted(
|
||||||
(a, b) => b.started_at.getTime() - a.started_at.getTime(),
|
(a, b) => b.started_at.getTime() - a.started_at.getTime(),
|
||||||
)
|
)
|
||||||
.map((run) => (
|
.map((run) => (
|
||||||
<AgentRunSummaryCard
|
<AgentRunSummaryCard
|
||||||
className="h-28 w-72 lg:h-32 xl:w-80"
|
className="h-28 w-72 lg:h-30 xl:w-80"
|
||||||
key={run.id}
|
key={run.id}
|
||||||
|
type="run"
|
||||||
status={agentRunStatusMap[run.status]}
|
status={agentRunStatusMap[run.status]}
|
||||||
title={agent.name}
|
title={agent.name}
|
||||||
timestamp={run.started_at}
|
timestamp={run.started_at}
|
||||||
selected={selectedView.id === run.id}
|
selected={selectedView.id === run.id}
|
||||||
onClick={() => onSelectRun(run.id)}
|
onClick={() => onSelectRun(run.id)}
|
||||||
onDelete={() => onDeleteRun(run)}
|
onDelete={() => onDeleteRun(run)}
|
||||||
/>
|
onPinAsPreset={() => onPinAsPreset(run)}
|
||||||
))
|
|
||||||
: schedules
|
|
||||||
.filter((schedule) => schedule.graph_id === agent.graph_id)
|
|
||||||
.map((schedule) => (
|
|
||||||
<AgentRunSummaryCard
|
|
||||||
className="h-28 w-72 lg:h-32 xl:w-80"
|
|
||||||
key={schedule.id}
|
|
||||||
status="scheduled"
|
|
||||||
title={schedule.name}
|
|
||||||
timestamp={schedule.next_run_time}
|
|
||||||
selected={selectedView.id === schedule.id}
|
|
||||||
onClick={() => onSelectSchedule(schedule)}
|
|
||||||
onDelete={() => onDeleteSchedule(schedule.id)}
|
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
schedules
|
||||||
|
.filter((schedule) => schedule.graph_id === agent.graph_id)
|
||||||
|
.map((schedule) => (
|
||||||
|
<AgentRunSummaryCard
|
||||||
|
className="h-28 w-72 lg:h-30 xl:w-80"
|
||||||
|
key={schedule.id}
|
||||||
|
type="schedule"
|
||||||
|
title={schedule.name}
|
||||||
|
timestamp={schedule.next_run_time}
|
||||||
|
selected={selectedView.id === schedule.id}
|
||||||
|
onClick={() => onSelectSchedule(schedule)}
|
||||||
|
onDelete={() => onDeleteSchedule(schedule.id)}
|
||||||
|
/>
|
||||||
|
))
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</ScrollArea>
|
</ScrollArea>
|
||||||
</aside>
|
</aside>
|
||||||
|
|||||||
@@ -1,10 +1,5 @@
|
|||||||
import React, { useCallback, useEffect, useState } from "react";
|
import React, { useCallback, useEffect, useState } from "react";
|
||||||
import {
|
import { GraphExecutionMeta, LibraryAgent } from "@/lib/autogpt-server-api";
|
||||||
GraphExecutionMeta,
|
|
||||||
LibraryAgent,
|
|
||||||
NodeExecutionResult,
|
|
||||||
SpecialBlockID,
|
|
||||||
} from "@/lib/autogpt-server-api";
|
|
||||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { Button, buttonVariants } from "@/components/ui/button";
|
import { Button, buttonVariants } from "@/components/ui/button";
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import {
|
|||||||
APIKeyPermission,
|
APIKeyPermission,
|
||||||
Block,
|
Block,
|
||||||
CreateAPIKeyResponse,
|
CreateAPIKeyResponse,
|
||||||
CreateLibraryAgentPresetRequest,
|
|
||||||
CreatorDetails,
|
CreatorDetails,
|
||||||
CreatorsResponse,
|
CreatorsResponse,
|
||||||
Credentials,
|
Credentials,
|
||||||
@@ -25,15 +24,22 @@ import {
|
|||||||
LibraryAgent,
|
LibraryAgent,
|
||||||
LibraryAgentID,
|
LibraryAgentID,
|
||||||
LibraryAgentPreset,
|
LibraryAgentPreset,
|
||||||
|
LibraryAgentPresetCreatable,
|
||||||
|
LibraryAgentPresetCreatableFromGraphExecution,
|
||||||
|
LibraryAgentPresetID,
|
||||||
LibraryAgentPresetResponse,
|
LibraryAgentPresetResponse,
|
||||||
|
LibraryAgentPresetUpdatable,
|
||||||
LibraryAgentResponse,
|
LibraryAgentResponse,
|
||||||
LibraryAgentSortEnum,
|
LibraryAgentSortEnum,
|
||||||
MyAgentsResponse,
|
MyAgentsResponse,
|
||||||
NodeExecutionResult,
|
NodeExecutionResult,
|
||||||
NotificationPreference,
|
NotificationPreference,
|
||||||
NotificationPreferenceDTO,
|
NotificationPreferenceDTO,
|
||||||
|
OttoQuery,
|
||||||
|
OttoResponse,
|
||||||
ProfileDetails,
|
ProfileDetails,
|
||||||
RefundRequest,
|
RefundRequest,
|
||||||
|
ReviewSubmissionRequest,
|
||||||
Schedule,
|
Schedule,
|
||||||
ScheduleCreatable,
|
ScheduleCreatable,
|
||||||
ScheduleID,
|
ScheduleID,
|
||||||
@@ -45,14 +51,11 @@ import {
|
|||||||
StoreSubmission,
|
StoreSubmission,
|
||||||
StoreSubmissionRequest,
|
StoreSubmissionRequest,
|
||||||
StoreSubmissionsResponse,
|
StoreSubmissionsResponse,
|
||||||
|
SubmissionStatus,
|
||||||
TransactionHistory,
|
TransactionHistory,
|
||||||
User,
|
User,
|
||||||
UserPasswordCredentials,
|
|
||||||
OttoQuery,
|
|
||||||
OttoResponse,
|
|
||||||
UserOnboarding,
|
UserOnboarding,
|
||||||
ReviewSubmissionRequest,
|
UserPasswordCredentials,
|
||||||
SubmissionStatus,
|
|
||||||
} from "./types";
|
} from "./types";
|
||||||
import { createBrowserClient } from "@supabase/ssr";
|
import { createBrowserClient } from "@supabase/ssr";
|
||||||
import getServerSupabase from "../supabase/getServerSupabase";
|
import getServerSupabase from "../supabase/getServerSupabase";
|
||||||
@@ -593,42 +596,63 @@ export default class BackendAPI {
|
|||||||
await this._request("PUT", `/library/agents/${libraryAgentId}`, params);
|
await this._request("PUT", `/library/agents/${libraryAgentId}`, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
listLibraryAgentPresets(params?: {
|
async listLibraryAgentPresets(params?: {
|
||||||
|
graph_id?: GraphID;
|
||||||
page?: number;
|
page?: number;
|
||||||
page_size?: number;
|
page_size?: number;
|
||||||
}): Promise<LibraryAgentPresetResponse> {
|
}): Promise<LibraryAgentPresetResponse> {
|
||||||
return this._get("/library/presets", params);
|
const response: LibraryAgentPresetResponse = await this._get(
|
||||||
|
"/library/presets",
|
||||||
|
params,
|
||||||
|
);
|
||||||
|
return {
|
||||||
|
...response,
|
||||||
|
presets: response.presets.map(parseLibraryAgentPresetTimestamp),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
getLibraryAgentPreset(presetId: string): Promise<LibraryAgentPreset> {
|
async getLibraryAgentPreset(
|
||||||
return this._get(`/library/presets/${presetId}`);
|
presetID: LibraryAgentPresetID,
|
||||||
}
|
|
||||||
|
|
||||||
createLibraryAgentPreset(
|
|
||||||
preset: CreateLibraryAgentPresetRequest,
|
|
||||||
): Promise<LibraryAgentPreset> {
|
): Promise<LibraryAgentPreset> {
|
||||||
return this._request("POST", "/library/presets", preset);
|
const preset = await this._get(`/library/presets/${presetID}`);
|
||||||
|
return parseLibraryAgentPresetTimestamp(preset);
|
||||||
}
|
}
|
||||||
|
|
||||||
updateLibraryAgentPreset(
|
async createLibraryAgentPreset(
|
||||||
presetId: string,
|
params:
|
||||||
preset: CreateLibraryAgentPresetRequest,
|
| LibraryAgentPresetCreatable
|
||||||
|
| LibraryAgentPresetCreatableFromGraphExecution,
|
||||||
): Promise<LibraryAgentPreset> {
|
): Promise<LibraryAgentPreset> {
|
||||||
return this._request("PUT", `/library/presets/${presetId}`, preset);
|
const new_preset = await this._request("POST", "/library/presets", params);
|
||||||
|
return parseLibraryAgentPresetTimestamp(new_preset);
|
||||||
}
|
}
|
||||||
|
|
||||||
async deleteLibraryAgentPreset(presetId: string): Promise<void> {
|
async updateLibraryAgentPreset(
|
||||||
await this._request("DELETE", `/library/presets/${presetId}`);
|
presetID: LibraryAgentPresetID,
|
||||||
|
partial_preset: LibraryAgentPresetUpdatable,
|
||||||
|
): Promise<LibraryAgentPreset> {
|
||||||
|
const updated_preset = await this._request(
|
||||||
|
"PATCH",
|
||||||
|
`/library/presets/${presetID}`,
|
||||||
|
partial_preset,
|
||||||
|
);
|
||||||
|
return parseLibraryAgentPresetTimestamp(updated_preset);
|
||||||
|
}
|
||||||
|
|
||||||
|
async deleteLibraryAgentPreset(
|
||||||
|
presetID: LibraryAgentPresetID,
|
||||||
|
): Promise<void> {
|
||||||
|
await this._request("DELETE", `/library/presets/${presetID}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
executeLibraryAgentPreset(
|
executeLibraryAgentPreset(
|
||||||
presetId: string,
|
presetID: LibraryAgentPresetID,
|
||||||
graphId: GraphID,
|
graphID: GraphID,
|
||||||
graphVersion: number,
|
graphVersion: number,
|
||||||
nodeInput: { [key: string]: any },
|
nodeInput: { [key: string]: any },
|
||||||
): Promise<{ id: string }> {
|
): Promise<{ id: GraphExecutionID }> {
|
||||||
return this._request("POST", `/library/presets/${presetId}/execute`, {
|
return this._request("POST", `/library/presets/${presetID}/execute`, {
|
||||||
graph_id: graphId,
|
graph_id: graphID,
|
||||||
graph_version: graphVersion,
|
graph_version: graphVersion,
|
||||||
node_input: nodeInput,
|
node_input: nodeInput,
|
||||||
});
|
});
|
||||||
@@ -1026,6 +1050,10 @@ function parseScheduleTimestamp(result: any): Schedule {
|
|||||||
return _parseObjectTimestamps<Schedule>(result, ["next_run_time"]);
|
return _parseObjectTimestamps<Schedule>(result, ["next_run_time"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function parseLibraryAgentPresetTimestamp(result: any): LibraryAgentPreset {
|
||||||
|
return _parseObjectTimestamps<LibraryAgentPreset>(result, ["updated_at"]);
|
||||||
|
}
|
||||||
|
|
||||||
function _parseObjectTimestamps<T>(obj: any, keys: (keyof T)[]): T {
|
function _parseObjectTimestamps<T>(obj: any, keys: (keyof T)[]): T {
|
||||||
const result = { ...obj };
|
const result = { ...obj };
|
||||||
keys.forEach(
|
keys.forEach(
|
||||||
|
|||||||
@@ -252,7 +252,7 @@ export type GraphExecutionMeta = {
|
|||||||
user_id: UserID;
|
user_id: UserID;
|
||||||
graph_id: GraphID;
|
graph_id: GraphID;
|
||||||
graph_version: number;
|
graph_version: number;
|
||||||
preset_id?: string;
|
preset_id?: LibraryAgentPresetID;
|
||||||
status: "QUEUED" | "RUNNING" | "COMPLETED" | "TERMINATED" | "FAILED";
|
status: "QUEUED" | "RUNNING" | "COMPLETED" | "TERMINATED" | "FAILED";
|
||||||
started_at: Date;
|
started_at: Date;
|
||||||
ended_at: Date;
|
ended_at: Date;
|
||||||
@@ -380,7 +380,8 @@ export enum AgentStatus {
|
|||||||
ERROR = "ERROR",
|
ERROR = "ERROR",
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface LibraryAgentResponse {
|
/* Mirror of backend/server/v2/library/model.py:LibraryAgentResponse */
|
||||||
|
export type LibraryAgentResponse = {
|
||||||
agents: LibraryAgent[];
|
agents: LibraryAgent[];
|
||||||
pagination: {
|
pagination: {
|
||||||
current_page: number;
|
current_page: number;
|
||||||
@@ -388,37 +389,54 @@ export interface LibraryAgentResponse {
|
|||||||
total_items: number;
|
total_items: number;
|
||||||
total_pages: number;
|
total_pages: number;
|
||||||
};
|
};
|
||||||
}
|
};
|
||||||
|
|
||||||
export interface LibraryAgentPreset {
|
/* Mirror of backend/server/v2/library/model.py:LibraryAgentPreset */
|
||||||
id: string;
|
export type LibraryAgentPreset = {
|
||||||
|
id: LibraryAgentPresetID;
|
||||||
updated_at: Date;
|
updated_at: Date;
|
||||||
graph_id: GraphID;
|
graph_id: GraphID;
|
||||||
graph_version: number;
|
graph_version: number;
|
||||||
|
inputs: { [key: string]: any };
|
||||||
name: string;
|
name: string;
|
||||||
description: string;
|
description: string;
|
||||||
is_active: boolean;
|
is_active: boolean;
|
||||||
inputs: { [key: string]: any };
|
};
|
||||||
}
|
|
||||||
|
|
||||||
export interface LibraryAgentPresetResponse {
|
export type LibraryAgentPresetID = Brand<string, "LibraryAgentPresetID">;
|
||||||
|
|
||||||
|
/* Mirror of backend/server/v2/library/model.py:LibraryAgentPresetResponse */
|
||||||
|
export type LibraryAgentPresetResponse = {
|
||||||
presets: LibraryAgentPreset[];
|
presets: LibraryAgentPreset[];
|
||||||
pagination: {
|
pagination: {
|
||||||
total: number;
|
total: number;
|
||||||
page: number;
|
page: number;
|
||||||
size: number;
|
size: number;
|
||||||
};
|
};
|
||||||
}
|
};
|
||||||
|
|
||||||
export interface CreateLibraryAgentPresetRequest {
|
/* Mirror of backend/server/v2/library/model.py:LibraryAgentPresetCreatable */
|
||||||
name: string;
|
export type LibraryAgentPresetCreatable = Omit<
|
||||||
description: string;
|
LibraryAgentPreset,
|
||||||
inputs: { [key: string]: any };
|
"id" | "updated_at" | "is_active"
|
||||||
graph_id: GraphID;
|
> & {
|
||||||
graph_version: number;
|
is_active?: boolean;
|
||||||
is_active: boolean;
|
};
|
||||||
}
|
|
||||||
|
|
||||||
|
/* Mirror of backend/server/v2/library/model.py:LibraryAgentPresetCreatableFromGraphExecution */
|
||||||
|
export type LibraryAgentPresetCreatableFromGraphExecution = Omit<
|
||||||
|
LibraryAgentPresetCreatable,
|
||||||
|
"graph_id" | "graph_version" | "inputs"
|
||||||
|
> & {
|
||||||
|
graph_execution_id: GraphExecutionID;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Mirror of backend/server/v2/library/model.py:LibraryAgentPresetUpdatable */
|
||||||
|
export type LibraryAgentPresetUpdatable = Partial<
|
||||||
|
Omit<LibraryAgentPresetCreatable, "graph_id" | "graph_version">
|
||||||
|
>;
|
||||||
|
|
||||||
|
/* Mirror of backend/server/v2/library/model.py:LibraryAgentSort */
|
||||||
export enum LibraryAgentSortEnum {
|
export enum LibraryAgentSortEnum {
|
||||||
CREATED_AT = "createdAt",
|
CREATED_AT = "createdAt",
|
||||||
UPDATED_AT = "updatedAt",
|
UPDATED_AT = "updatedAt",
|
||||||
|
|||||||
@@ -93,6 +93,7 @@ const config = {
|
|||||||
20: "5rem",
|
20: "5rem",
|
||||||
24: "6rem",
|
24: "6rem",
|
||||||
28: "7rem",
|
28: "7rem",
|
||||||
|
30: "7.5rem",
|
||||||
32: "8rem",
|
32: "8rem",
|
||||||
36: "9rem",
|
36: "9rem",
|
||||||
40: "10rem",
|
40: "10rem",
|
||||||
|
|||||||
Reference in New Issue
Block a user