feat(backend): Allow creating preset directly from graph execution

This commit is contained in:
Reinier van der Leer
2025-04-10 15:03:48 +02:00
parent 383b72a551
commit a18ca17f25
7 changed files with 82 additions and 14 deletions

View File

@@ -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.media as store_media
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.util.exceptions import NotFoundError
from backend.util.settings import Config
logger = logging.getLogger(__name__)
@@ -593,6 +595,44 @@ async def create_preset(
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,

View File

@@ -181,7 +181,20 @@ class LibraryAgentPresetCreatable(pydantic.BaseModel):
name: str
description: str
is_active: bool
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):

View File

@@ -9,6 +9,7 @@ import backend.executor
import backend.server.v2.library.db as db
import backend.server.v2.library.model as models
import backend.util.service
from backend.util.exceptions import NotFoundError
logger = logging.getLogger(__name__)
@@ -105,7 +106,10 @@ async def get_preset(
description="Create a new preset for the current user.",
)
async def create_preset(
preset: models.LibraryAgentPresetCreatable,
preset: (
models.LibraryAgentPresetCreatable
| models.LibraryAgentPresetCreatableFromGraphExecution
),
user_id: str = Depends(autogpt_auth_lib.depends.get_user_id),
) -> models.LibraryAgentPreset:
"""
@@ -122,7 +126,12 @@ async def create_preset(
HTTPException: If an error occurs while creating the preset.
"""
try:
return await db.create_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:
logger.exception(f"Exception occurred while creating preset: {e}")
raise HTTPException(

View File

@@ -257,16 +257,11 @@ export default function AgentRunsPage(): React.ReactElement {
const createPresetFromRun = useCallback(
async (run: GraphExecutionMeta) => {
// TODO: make a dedicated endpoint for this
const execution = await api.getGraphExecutionInfo(run.graph_id, run.id);
const createdPreset = await api.createLibraryAgentPreset({
/* FIXME: add dialog to enter name and description */
name: agent!.name,
description: agent!.description,
graph_id: execution.graph_id,
graph_version: execution.graph_version,
inputs: execution.inputs,
is_active: true,
graph_execution_id: run.id,
});
setAgentPresets((prev) => [...prev, createdPreset]);
},

View File

@@ -71,7 +71,6 @@ export default function AgentRunDraftView({
name: graph.name,
description: "", // TODO: add dialog for name + description
inputs: inputValues,
is_active: true,
})
).then(onSavePreset),
[

View File

@@ -25,6 +25,7 @@ import {
LibraryAgentID,
LibraryAgentPreset,
LibraryAgentPresetCreatable,
LibraryAgentPresetCreatableFromGraphExecution,
LibraryAgentPresetID,
LibraryAgentPresetResponse,
LibraryAgentPresetUpdatable,
@@ -618,9 +619,11 @@ export default class BackendAPI {
}
async createLibraryAgentPreset(
preset: LibraryAgentPresetCreatable,
params:
| LibraryAgentPresetCreatable
| LibraryAgentPresetCreatableFromGraphExecution,
): Promise<LibraryAgentPreset> {
const new_preset = await this._request("POST", "/library/presets", preset);
const new_preset = await this._request("POST", "/library/presets", params);
return parseLibraryAgentPresetTimestamp(new_preset);
}

View File

@@ -414,8 +414,17 @@ export type LibraryAgentPresetResponse = {
export type LibraryAgentPresetCreatable = Omit<
LibraryAgentPreset,
"id" | "updated_at"
>;
"id" | "updated_at" | "is_active"
> & {
is_active?: boolean;
};
export type LibraryAgentPresetCreatableFromGraphExecution = Omit<
LibraryAgentPresetCreatable,
"graph_id" | "graph_version" | "inputs"
> & {
graph_execution_id: GraphExecutionID;
};
export type LibraryAgentPresetUpdatable = Partial<
Omit<LibraryAgentPresetCreatable, "graph_id" | "graph_version">