update api endpoint function names & deprecate endpoints that are not used (#1931)

This commit is contained in:
Shuchang Zheng
2025-03-12 17:13:55 -07:00
committed by GitHub
parent 128ea617dd
commit f20bf94696

View File

@@ -25,7 +25,6 @@ from sqlalchemy.exc import OperationalError
from skyvern import analytics from skyvern import analytics
from skyvern.config import settings from skyvern.config import settings
from skyvern.exceptions import StepNotFound
from skyvern.forge import app from skyvern.forge import app
from skyvern.forge.prompts import prompt_engine from skyvern.forge.prompts import prompt_engine
from skyvern.forge.sdk.api.aws import aws_client from skyvern.forge.sdk.api.aws import aws_client
@@ -85,6 +84,27 @@ v2_router = APIRouter()
LOG = structlog.get_logger() LOG = structlog.get_logger()
class EntityType(str, Enum):
STEP = "step"
TASK = "task"
WORKFLOW_RUN = "workflow_run"
WORKFLOW_RUN_BLOCK = "workflow_run_block"
THOUGHT = "thought"
entity_type_to_param = {
EntityType.STEP: "step_id",
EntityType.TASK: "task_id",
EntityType.WORKFLOW_RUN: "workflow_run_id",
EntityType.WORKFLOW_RUN_BLOCK: "workflow_run_block_id",
EntityType.THOUGHT: "thought_id",
}
class AISuggestionType(str, Enum):
DATA_SCHEMA = "data_schema"
@base_router.post("/webhook", tags=["server"]) @base_router.post("/webhook", tags=["server"])
@base_router.post("/webhook/", tags=["server"], include_in_schema=False) @base_router.post("/webhook/", tags=["server"], include_in_schema=False)
async def webhook( async def webhook(
@@ -125,7 +145,7 @@ async def webhook(
@base_router.get("/heartbeat", tags=["server"]) @base_router.get("/heartbeat", tags=["server"])
@base_router.get("/heartbeat/", tags=["server"], include_in_schema=False) @base_router.get("/heartbeat/", tags=["server"], include_in_schema=False)
async def check_server_status() -> Response: async def heartbeat() -> Response:
""" """
Check if the server is running. Check if the server is running.
""" """
@@ -139,7 +159,7 @@ async def check_server_status() -> Response:
response_model=CreateTaskResponse, response_model=CreateTaskResponse,
include_in_schema=False, include_in_schema=False,
) )
async def create_agent_task( async def run_task(
request: Request, request: Request,
background_tasks: BackgroundTasks, background_tasks: BackgroundTasks,
task: TaskRequest, task: TaskRequest,
@@ -179,89 +199,6 @@ async def create_agent_task(
return CreateTaskResponse(task_id=created_task.task_id) return CreateTaskResponse(task_id=created_task.task_id)
@base_router.post(
"/tasks/{task_id}/steps/{step_id}",
tags=["agent"],
response_model=Step,
summary="Executes a specific step",
)
@base_router.post(
"/tasks/{task_id}/steps/{step_id}/",
tags=["agent"],
response_model=Step,
summary="Executes a specific step",
include_in_schema=False,
)
@base_router.post(
"/tasks/{task_id}/steps",
tags=["agent"],
response_model=Step,
summary="Executes the next step",
)
@base_router.post(
"/tasks/{task_id}/steps/",
tags=["agent"],
response_model=Step,
summary="Executes the next step",
include_in_schema=False,
)
async def execute_agent_task_step(
task_id: str,
step_id: str | None = None,
current_org: Organization = Depends(org_auth_service.get_current_org),
) -> Response:
analytics.capture("skyvern-oss-agent-task-step-execute")
task = await app.DATABASE.get_task(task_id, organization_id=current_org.organization_id)
if not task:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"No task found with id {task_id}",
)
# An empty step request means that the agent should execute the next step for the task.
if not step_id:
step = await app.DATABASE.get_latest_step(task_id=task_id, organization_id=current_org.organization_id)
if not step:
raise StepNotFound(current_org.organization_id, task_id)
LOG.info(
"Executing latest step since no step_id was provided",
task_id=task_id,
step_id=step.step_id,
step_order=step.order,
step_retry=step.retry_index,
)
if not step:
LOG.error(
"No steps found for task",
task_id=task_id,
)
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"No steps found for task {task_id}",
)
else:
step = await app.DATABASE.get_step(task_id, step_id, organization_id=current_org.organization_id)
if not step:
raise StepNotFound(current_org.organization_id, task_id, step_id)
LOG.info(
"Executing step",
task_id=task_id,
step_id=step.step_id,
step_order=step.order,
step_retry=step.retry_index,
)
if not step:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"No step found with id {step_id}",
)
step, _, _ = await app.agent.execute_step(current_org, task, step)
return Response(
content=step.model_dump_json(exclude_none=True) if step else "",
status_code=200,
media_type="application/json",
)
@base_router.get("/tasks/{task_id}", response_model=TaskResponse) @base_router.get("/tasks/{task_id}", response_model=TaskResponse)
@base_router.get("/tasks/{task_id}/", response_model=TaskResponse, include_in_schema=False) @base_router.get("/tasks/{task_id}/", response_model=TaskResponse, include_in_schema=False)
async def get_task( async def get_task(
@@ -391,32 +328,9 @@ async def retry_webhook(
return await app.agent.build_task_response(task=task_obj, last_step=latest_step) return await app.agent.build_task_response(task=task_obj, last_step=latest_step)
@base_router.get("/internal/tasks/{task_id}", response_model=list[Task])
@base_router.get("/internal/tasks/{task_id}/", response_model=list[Task], include_in_schema=False)
async def get_task_internal(
task_id: str,
current_org: Organization = Depends(org_auth_service.get_current_org),
) -> Response:
"""
Get all tasks.
:param page: Starting page, defaults to 1
:param page_size:
:return: List of tasks with pagination without steps populated. Steps can be populated by calling the
get_agent_task endpoint.
"""
analytics.capture("skyvern-oss-agent-task-get-internal")
task = await app.DATABASE.get_task(task_id, organization_id=current_org.organization_id)
if not task:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"Task not found {task_id}",
)
return ORJSONResponse(task.model_dump())
@base_router.get("/tasks", tags=["agent"], response_model=list[Task]) @base_router.get("/tasks", tags=["agent"], response_model=list[Task])
@base_router.get("/tasks/", tags=["agent"], response_model=list[Task], include_in_schema=False) @base_router.get("/tasks/", tags=["agent"], response_model=list[Task], include_in_schema=False)
async def get_agent_tasks( async def get_tasks(
page: int = Query(1, ge=1), page: int = Query(1, ge=1),
page_size: int = Query(10, ge=1), page_size: int = Query(10, ge=1),
task_status: Annotated[list[TaskStatus] | None, Query()] = None, task_status: Annotated[list[TaskStatus] | None, Query()] = None,
@@ -477,32 +391,6 @@ async def get_runs(
return ORJSONResponse([run.model_dump() for run in runs]) return ORJSONResponse([run.model_dump() for run in runs])
@base_router.get("/internal/tasks", tags=["agent"], response_model=list[Task])
@base_router.get(
"/internal/tasks/",
tags=["agent"],
response_model=list[Task],
include_in_schema=False,
)
async def get_agent_tasks_internal(
page: int = Query(1, ge=1),
page_size: int = Query(10, ge=1),
current_org: Organization = Depends(org_auth_service.get_current_org),
) -> Response:
"""
Get all tasks.
:param page: Starting page, defaults to 1
:param page_size: Page size, defaults to 10
:return: List of tasks with pagination without steps populated. Steps can be populated by calling the
get_agent_task endpoint.
"""
analytics.capture("skyvern-oss-agent-tasks-get-internal")
tasks = await app.DATABASE.get_tasks(
page, page_size, workflow_run_id=None, organization_id=current_org.organization_id
)
return ORJSONResponse([task.model_dump() for task in tasks])
@base_router.get("/tasks/{task_id}/steps", tags=["agent"], response_model=list[Step]) @base_router.get("/tasks/{task_id}/steps", tags=["agent"], response_model=list[Step])
@base_router.get( @base_router.get(
"/tasks/{task_id}/steps/", "/tasks/{task_id}/steps/",
@@ -510,7 +398,7 @@ async def get_agent_tasks_internal(
response_model=list[Step], response_model=list[Step],
include_in_schema=False, include_in_schema=False,
) )
async def get_agent_task_steps( async def get_steps(
task_id: str, task_id: str,
current_org: Organization = Depends(org_auth_service.get_current_org), current_org: Organization = Depends(org_auth_service.get_current_org),
) -> Response: ) -> Response:
@@ -524,23 +412,6 @@ async def get_agent_task_steps(
return ORJSONResponse([step.model_dump(exclude_none=True) for step in steps]) return ORJSONResponse([step.model_dump(exclude_none=True) for step in steps])
class EntityType(str, Enum):
STEP = "step"
TASK = "task"
WORKFLOW_RUN = "workflow_run"
WORKFLOW_RUN_BLOCK = "workflow_run_block"
THOUGHT = "thought"
entity_type_to_param = {
EntityType.STEP: "step_id",
EntityType.TASK: "task_id",
EntityType.WORKFLOW_RUN: "workflow_run_id",
EntityType.WORKFLOW_RUN_BLOCK: "workflow_run_block_id",
EntityType.THOUGHT: "thought_id",
}
@base_router.get( @base_router.get(
"/{entity_type}/{entity_id}/artifacts", "/{entity_type}/{entity_id}/artifacts",
tags=["agent"], tags=["agent"],
@@ -552,7 +423,7 @@ entity_type_to_param = {
response_model=list[Artifact], response_model=list[Artifact],
include_in_schema=False, include_in_schema=False,
) )
async def get_agent_entity_artifacts( async def get_artifacts(
entity_type: EntityType, entity_type: EntityType,
entity_id: str, entity_id: str,
current_org: Organization = Depends(org_auth_service.get_current_org), current_org: Organization = Depends(org_auth_service.get_current_org),
@@ -613,7 +484,7 @@ async def get_agent_entity_artifacts(
response_model=list[Artifact], response_model=list[Artifact],
include_in_schema=False, include_in_schema=False,
) )
async def get_agent_task_step_artifacts( async def get_step_artifacts(
task_id: str, task_id: str,
step_id: str, step_id: str,
current_org: Organization = Depends(org_auth_service.get_current_org), current_org: Organization = Depends(org_auth_service.get_current_org),
@@ -657,7 +528,7 @@ class ActionResultTmp(BaseModel):
response_model=list[Action], response_model=list[Action],
include_in_schema=False, include_in_schema=False,
) )
async def get_task_actions( async def get_actions(
task_id: str, task_id: str,
current_org: Organization = Depends(org_auth_service.get_current_org), current_org: Organization = Depends(org_auth_service.get_current_org),
) -> list[Action]: ) -> list[Action]:
@@ -672,10 +543,10 @@ async def get_task_actions(
response_model=RunWorkflowResponse, response_model=RunWorkflowResponse,
include_in_schema=False, include_in_schema=False,
) )
async def execute_workflow( async def run_workflow(
request: Request, request: Request,
background_tasks: BackgroundTasks, background_tasks: BackgroundTasks,
workflow_id: str, # this is the workflow_permanent_id workflow_id: str, # this is the workflow_permanent_id internally
workflow_request: WorkflowRequestBody, workflow_request: WorkflowRequestBody,
version: int | None = None, version: int | None = None,
current_org: Organization = Depends(org_auth_service.get_current_org), current_org: Organization = Depends(org_auth_service.get_current_org),
@@ -754,16 +625,16 @@ async def get_workflow_runs(
@base_router.get( @base_router.get(
"/workflows/{workflow_permanent_id}/runs", "/workflows/{workflow_id}/runs",
response_model=list[WorkflowRun], response_model=list[WorkflowRun],
) )
@base_router.get( @base_router.get(
"/workflows/{workflow_permanent_id}/runs/", "/workflows/{workflow_id}/runs/",
response_model=list[WorkflowRun], response_model=list[WorkflowRun],
include_in_schema=False, include_in_schema=False,
) )
async def get_workflow_runs_for_workflow_permanent_id( async def get_workflow_runs_by_id(
workflow_permanent_id: str, workflow_id: str,
page: int = Query(1, ge=1), page: int = Query(1, ge=1),
page_size: int = Query(10, ge=1), page_size: int = Query(10, ge=1),
status: Annotated[list[WorkflowRunStatus] | None, Query()] = None, status: Annotated[list[WorkflowRunStatus] | None, Query()] = None,
@@ -771,7 +642,7 @@ async def get_workflow_runs_for_workflow_permanent_id(
) -> list[WorkflowRun]: ) -> list[WorkflowRun]:
analytics.capture("skyvern-oss-agent-workflow-runs-get") analytics.capture("skyvern-oss-agent-workflow-runs-get")
return await app.WORKFLOW_SERVICE.get_workflow_runs_for_workflow_permanent_id( return await app.WORKFLOW_SERVICE.get_workflow_runs_for_workflow_permanent_id(
workflow_permanent_id=workflow_permanent_id, workflow_permanent_id=workflow_id,
organization_id=current_org.organization_id, organization_id=current_org.organization_id,
page=page, page=page,
page_size=page_size, page_size=page_size,
@@ -1032,13 +903,9 @@ async def get_workflow(
) )
class AISuggestionType(str, Enum):
DATA_SCHEMA = "data_schema"
@base_router.post("/suggest/{ai_suggestion_type}", include_in_schema=False) @base_router.post("/suggest/{ai_suggestion_type}", include_in_schema=False)
@base_router.post("/suggest/{ai_suggestion_type}/") @base_router.post("/suggest/{ai_suggestion_type}/")
async def make_ai_suggestion( async def suggest(
ai_suggestion_type: AISuggestionType, ai_suggestion_type: AISuggestionType,
data: AISuggestionRequest, data: AISuggestionRequest,
current_org: Organization = Depends(org_auth_service.get_current_org), current_org: Organization = Depends(org_auth_service.get_current_org),
@@ -1148,8 +1015,8 @@ async def get_organizations(
@base_router.get("/organizations/{organization_id}/apikeys/", include_in_schema=False) @base_router.get("/organizations/{organization_id}/apikeys/", include_in_schema=False)
@base_router.get("/organizations/{organization_id}/apikeys") @base_router.get("/organizations/{organization_id}/apikeys", include_in_schema=False)
async def get_org_api_keys( async def get_api_keys(
organization_id: str, organization_id: str,
current_org: Organization = Depends(org_auth_service.get_current_org), current_org: Organization = Depends(org_auth_service.get_current_org),
) -> GetOrganizationAPIKeysResponse: ) -> GetOrganizationAPIKeysResponse:
@@ -1162,7 +1029,7 @@ async def get_org_api_keys(
return GetOrganizationAPIKeysResponse(api_keys=api_keys) return GetOrganizationAPIKeysResponse(api_keys=api_keys)
async def validate_file_size(file: UploadFile) -> UploadFile: async def _validate_file_size(file: UploadFile) -> UploadFile:
try: try:
file.file.seek(0, 2) # Move the pointer to the end of the file file.file.seek(0, 2) # Move the pointer to the end of the file
size = file.file.tell() # Get the current position of the pointer, which represents the file size size = file.file.tell() # Get the current position of the pointer, which represents the file size
@@ -1181,7 +1048,7 @@ async def validate_file_size(file: UploadFile) -> UploadFile:
@base_router.post("/upload_file/", include_in_schema=False) @base_router.post("/upload_file/", include_in_schema=False)
@base_router.post("/upload_file") @base_router.post("/upload_file")
async def upload_file( async def upload_file(
file: UploadFile = Depends(validate_file_size), file: UploadFile = Depends(_validate_file_size),
current_org: Organization = Depends(org_auth_service.get_current_org), current_org: Organization = Depends(org_auth_service.get_current_org),
) -> Response: ) -> Response:
bucket = app.SETTINGS_MANAGER.AWS_S3_BUCKET_UPLOADS bucket = app.SETTINGS_MANAGER.AWS_S3_BUCKET_UPLOADS
@@ -1223,7 +1090,7 @@ async def upload_file(
@v2_router.post("/tasks") @v2_router.post("/tasks")
@v2_router.post("/tasks/", include_in_schema=False) @v2_router.post("/tasks/", include_in_schema=False)
async def create_task_v2( async def run_task_v2(
request: Request, request: Request,
background_tasks: BackgroundTasks, background_tasks: BackgroundTasks,
data: TaskV2Request, data: TaskV2Request,
@@ -1288,7 +1155,7 @@ async def get_task_v2(
response_model=BrowserSessionResponse, response_model=BrowserSessionResponse,
include_in_schema=False, include_in_schema=False,
) )
async def get_browser_session_by_id( async def get_browser_session(
browser_session_id: str, browser_session_id: str,
current_org: Organization = Depends(org_auth_service.get_current_org), current_org: Organization = Depends(org_auth_service.get_current_org),
) -> BrowserSessionResponse: ) -> BrowserSessionResponse:
@@ -1336,24 +1203,6 @@ async def create_browser_session(
return BrowserSessionResponse.from_browser_session(browser_session) return BrowserSessionResponse.from_browser_session(browser_session)
@base_router.post(
"/browser_sessions/close",
)
@base_router.post(
"/browser_sessions/close/",
include_in_schema=False,
)
async def close_browser_sessions(
current_org: Organization = Depends(org_auth_service.get_current_org),
) -> ORJSONResponse:
await app.PERSISTENT_SESSIONS_MANAGER.close_all_sessions(current_org.organization_id)
return ORJSONResponse(
content={"message": "All browser sessions closed"},
status_code=200,
media_type="application/json",
)
@base_router.post( @base_router.post(
"/browser_sessions/{session_id}/close", "/browser_sessions/{session_id}/close",
) )