From b7db95823f7e064dc2e944d42ec7b137f21ed2e2 Mon Sep 17 00:00:00 2001 From: rramakrishnan2 Date: Fri, 7 Mar 2025 16:01:45 -0800 Subject: [PATCH 1/2] feat: add resume run api #32 --- openapi.json | 125 +++++++++++++++++++++++++++++++ server/ap_server/models.py | 13 ++++ server/ap_server/routers/runs.py | 20 +++++ 3 files changed, 158 insertions(+) diff --git a/openapi.json b/openapi.json index dfb3e40..a52d648 100644 --- a/openapi.json +++ b/openapi.json @@ -1171,6 +1171,94 @@ } } }, + "/threads/{thread_id}/runs/{run_id}/resume": { + "post": { + "tags": [ + "Runs" + ], + "summary": "Resume Run", + "description": "Resume an existing run on a thread, return the run ID immediately. Don't wait for the final run output.", + "operationId": "resume_run_http_threads__thread_id__runs__run_id__resume_post", + "parameters": [ + { + "description": "The ID of the thread.", + "required": true, + "schema": { + "type": "string", + "format": "uuid", + "title": "Thread Id", + "description": "The ID of the thread." + }, + "name": "thread_id", + "in": "path" + }, + { + "description": "The ID of the run.", + "required": true, + "schema": { + "type": "string", + "format": "uuid", + "title": "Run Id", + "description": "The ID of the run." + }, + "name": "run_id", + "in": "path" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RunResumeStateful" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Run" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "409": { + "description": "Conflict", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + } + } + }, "/threads/{thread_id}/runs/{run_id}/cancel": { "post": { "tags": [ @@ -1963,6 +2051,43 @@ "title": "RunCreateStateful", "description": "Payload for creating a run." }, + "RunResumeStateful": { + "properties": { + "input": { + "anyOf": [ + { + "type": "object" + }, + { + "type": "array" + }, + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "title": "Input", + "description": "The input to the graph to resume it from an interrupted state." + }, + "after_seconds": { + "type": "integer", + "title": "After Seconds", + "description": "The number of seconds to wait before resuming the run. Use to resume runs in the future." + } + }, + "type": "object", + "required": [], + "title": "RunResumeStateful", + "description": "Payload for resuming a run." + }, "RunWaitResponse": { "type": "object", "properties": { diff --git a/server/ap_server/models.py b/server/ap_server/models.py index 822abfa..c3ee5e2 100644 --- a/server/ap_server/models.py +++ b/server/ap_server/models.py @@ -176,6 +176,19 @@ class RunCreateStateful(BaseModel): ) +class RunResumeStateful(BaseModel): + input: Optional[Union[Dict[str, Any], List, str, float, bool]] = Field( + None, + description="The input to the graph to resume it from an interrupted state.", + title="Input", + ) + after_seconds: Optional[int] = Field( + None, + description="The number of seconds to wait before resuming the run. Use to resume runs in the future.", + title="After Seconds", + ) + + class OnCompletion(Enum): delete = "delete" keep = "keep" diff --git a/server/ap_server/routers/runs.py b/server/ap_server/routers/runs.py index 9c8ed37..7794459 100644 --- a/server/ap_server/routers/runs.py +++ b/server/ap_server/routers/runs.py @@ -12,6 +12,7 @@ Optional, Run, RunCreateStateful, + RunResumeStateful, RunWaitResponse, ThreadsThreadIdRunsGetResponse, UUID, @@ -143,6 +144,25 @@ def cancel_run_http_threads__thread_id__runs__run_id__cancel_post( pass +@router.post( + "/threads/{thread_id}/runs/{run_id}/resume", + response_model=Run, + responses={ + "404": {"model": ErrorResponse}, + "409": {"model": ErrorResponse}, + "422": {"model": ErrorResponse}, + }, + tags=["Runs"], +) +def resume_run_http_threads__thread_id__runs__run_id__resume_post( + thread_id: UUID, run_id: UUID = ..., body: RunResumeStateful = ... +) -> Union[Run, ErrorResponse]: + """ + Resume Run + """ + pass + + @router.get( "/threads/{thread_id}/runs/{run_id}/stream", response_model=Any, From 12b0624838c476e74ca1e995f28e2cedc773c74c Mon Sep 17 00:00:00 2001 From: rramakrishnan2 Date: Fri, 4 Apr 2025 00:37:42 -0700 Subject: [PATCH 2/2] fix: forgot to add openapi spec --- openapi.json | 8 ++++++++ server/ap_server/models.py | 36 ++++++++++++++++++------------------ 2 files changed, 26 insertions(+), 18 deletions(-) diff --git a/openapi.json b/openapi.json index b21085b..39fd603 100644 --- a/openapi.json +++ b/openapi.json @@ -2104,6 +2104,14 @@ "title": "Input", "description": "The input to the graph to resume it from an interrupted state." }, + "messages": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Message" + }, + "title": "Messages", + "description": "The messages to pass an input to the agent." + }, "after_seconds": { "type": "integer", "title": "After Seconds", diff --git a/server/ap_server/models.py b/server/ap_server/models.py index 259846e..21dd3f3 100644 --- a/server/ap_server/models.py +++ b/server/ap_server/models.py @@ -143,24 +143,6 @@ class IfNotExists(Enum): reject = "reject" -class RunResumeStateful(BaseModel): - input: Optional[Union[Dict[str, Any], List, str, float, bool]] = Field( - None, - description="The input to the graph to resume it from an interrupted state.", - title="Input", - ) - after_seconds: Optional[int] = Field( - None, - description="The number of seconds to wait before resuming the run. Use to resume runs in the future.", - title="After Seconds", - ) - messages: Optional[List[Message]] = Field( - None, - description="The messages to pass as input to the agent while resuming it.", - title="Messages", - ) - - class OnCompletion(Enum): delete = "delete" keep = "keep" @@ -426,6 +408,24 @@ class RunCreateStateful(BaseModel): ) +class RunResumeStateful(BaseModel): + input: Optional[Union[Dict[str, Any], List, str, float, bool]] = Field( + None, + description="The input to the graph to resume it from an interrupted state.", + title="Input", + ) + messages: Optional[List[Message]] = Field( + None, + description="The messages to pass an input to the agent.", + title="Messages", + ) + after_seconds: Optional[int] = Field( + None, + description="The number of seconds to wait before resuming the run. Use to resume runs in the future.", + title="After Seconds", + ) + + class RunWaitResponse(BaseModel): run: Optional[Run] = Field(None, description="The run information.", title="Run") values: Optional[Dict[str, Any]] = Field(