From 0ef9c8f483269d203a3edc7b5805f48f4263eb2f Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 10 Apr 2026 00:54:59 +0000 Subject: [PATCH 01/56] feat(api): api update --- .stats.yml | 6 +++--- src/oz_agent_sdk/resources/agent/agent.py | 10 ---------- src/oz_agent_sdk/types/agent_run_params.py | 6 ------ tests/api_resources/test_agent.py | 2 -- 4 files changed, 3 insertions(+), 21 deletions(-) diff --git a/.stats.yml b/.stats.yml index 51b5464..11ad6be 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 14 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta%2Fwarp-api-8f9c749573846b07a55a3131b66456f0a592838c6bfc986ab30948df66cd6f11.yml -openapi_spec_hash: 59f1ac98ad6cf13b12c59196bcecffd7 -config_hash: 60052b2c1c0862014416821aba875574 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta%2Fwarp-api-a29592b2ba26cba9d89b95969d66506f49c08e140b76ce4aea4189e5c1dccc06.yml +openapi_spec_hash: 27a5de1f891104d5e47904ad8e4b4bd1 +config_hash: 40327fb76b7cce7b97f23de9b8d48efb diff --git a/src/oz_agent_sdk/resources/agent/agent.py b/src/oz_agent_sdk/resources/agent/agent.py index b720375..a0240ce 100644 --- a/src/oz_agent_sdk/resources/agent/agent.py +++ b/src/oz_agent_sdk/resources/agent/agent.py @@ -193,7 +193,6 @@ def get_artifact( def run( self, *, - agent_identity_uid: str | Omit = omit, attachments: Iterable[agent_run_params.Attachment] | Omit = omit, config: AmbientAgentConfigParam | Omit = omit, conversation_id: str | Omit = omit, @@ -216,9 +215,6 @@ def run( runs. Behavior is identical to POST /agent/run. Args: - agent_identity_uid: Optional agent identity UID to use as the execution principal for the run. This - is only valid for runs that are team owned. - attachments: Optional file attachments to include with the prompt (max 5). Attachments are uploaded to cloud storage and made available to the agent. @@ -260,7 +256,6 @@ def run( "/agent/runs", body=maybe_transform( { - "agent_identity_uid": agent_identity_uid, "attachments": attachments, "config": config, "conversation_id": conversation_id, @@ -422,7 +417,6 @@ async def get_artifact( async def run( self, *, - agent_identity_uid: str | Omit = omit, attachments: Iterable[agent_run_params.Attachment] | Omit = omit, config: AmbientAgentConfigParam | Omit = omit, conversation_id: str | Omit = omit, @@ -445,9 +439,6 @@ async def run( runs. Behavior is identical to POST /agent/run. Args: - agent_identity_uid: Optional agent identity UID to use as the execution principal for the run. This - is only valid for runs that are team owned. - attachments: Optional file attachments to include with the prompt (max 5). Attachments are uploaded to cloud storage and made available to the agent. @@ -489,7 +480,6 @@ async def run( "/agent/runs", body=await async_maybe_transform( { - "agent_identity_uid": agent_identity_uid, "attachments": attachments, "config": config, "conversation_id": conversation_id, diff --git a/src/oz_agent_sdk/types/agent_run_params.py b/src/oz_agent_sdk/types/agent_run_params.py index 5d185a5..2a346ed 100644 --- a/src/oz_agent_sdk/types/agent_run_params.py +++ b/src/oz_agent_sdk/types/agent_run_params.py @@ -14,12 +14,6 @@ class AgentRunParams(TypedDict, total=False): - agent_identity_uid: str - """ - Optional agent identity UID to use as the execution principal for the run. This - is only valid for runs that are team owned. - """ - attachments: Iterable[Attachment] """ Optional file attachments to include with the prompt (max 5). Attachments are diff --git a/tests/api_resources/test_agent.py b/tests/api_resources/test_agent.py index 70c07fb..b641c09 100644 --- a/tests/api_resources/test_agent.py +++ b/tests/api_resources/test_agent.py @@ -112,7 +112,6 @@ def test_method_run(self, client: OzAPI) -> None: @parametrize def test_method_run_with_all_params(self, client: OzAPI) -> None: agent = client.agent.run( - agent_identity_uid="agent_identity_uid", attachments=[ { "data": "U3RhaW5sZXNzIHJvY2tz", @@ -273,7 +272,6 @@ async def test_method_run(self, async_client: AsyncOzAPI) -> None: @parametrize async def test_method_run_with_all_params(self, async_client: AsyncOzAPI) -> None: agent = await async_client.agent.run( - agent_identity_uid="agent_identity_uid", attachments=[ { "data": "U3RhaW5sZXNzIHJvY2tz", From 6720ea9331a945cf2d030e20b8851a223697aab3 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 10 Apr 2026 14:53:43 +0000 Subject: [PATCH 02/56] fix: ensure file data are only sent as 1 parameter --- src/oz_agent_sdk/_utils/_utils.py | 5 +++-- tests/test_extract_files.py | 9 +++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/oz_agent_sdk/_utils/_utils.py b/src/oz_agent_sdk/_utils/_utils.py index eec7f4a..63b8cd6 100644 --- a/src/oz_agent_sdk/_utils/_utils.py +++ b/src/oz_agent_sdk/_utils/_utils.py @@ -86,8 +86,9 @@ def _extract_items( index += 1 if is_dict(obj): try: - # We are at the last entry in the path so we must remove the field - if (len(path)) == index: + # Remove the field if there are no more dict keys in the path, + # only "" traversal markers or end. + if all(p == "" for p in path[index:]): item = obj.pop(key) else: item = obj[key] diff --git a/tests/test_extract_files.py b/tests/test_extract_files.py index 95b71bd..f014004 100644 --- a/tests/test_extract_files.py +++ b/tests/test_extract_files.py @@ -35,6 +35,15 @@ def test_multiple_files() -> None: assert query == {"documents": [{}, {}]} +def test_top_level_file_array() -> None: + query = {"files": [b"file one", b"file two"], "title": "hello"} + assert extract_files(query, paths=[["files", ""]]) == [ + ("files[]", b"file one"), + ("files[]", b"file two"), + ] + assert query == {"title": "hello"} + + @pytest.mark.parametrize( "query,paths,expected", [ From 33cf04c0777d53059f8a3c73b925b468276aba2a Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 10 Apr 2026 20:19:07 +0000 Subject: [PATCH 03/56] feat: Add parent_run_id filter to List runs endpoint --- .stats.yml | 6 +++--- src/oz_agent_sdk/resources/agent/agent.py | 10 ++++++++++ src/oz_agent_sdk/resources/agent/runs.py | 10 ++++++++++ src/oz_agent_sdk/types/agent/run_list_params.py | 6 ++++++ src/oz_agent_sdk/types/agent_run_params.py | 6 ++++++ tests/api_resources/agent/test_runs.py | 2 ++ tests/api_resources/test_agent.py | 2 ++ 7 files changed, 39 insertions(+), 3 deletions(-) diff --git a/.stats.yml b/.stats.yml index 11ad6be..874109f 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 14 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta%2Fwarp-api-a29592b2ba26cba9d89b95969d66506f49c08e140b76ce4aea4189e5c1dccc06.yml -openapi_spec_hash: 27a5de1f891104d5e47904ad8e4b4bd1 -config_hash: 40327fb76b7cce7b97f23de9b8d48efb +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta%2Fwarp-api-96b15c5805e3554bc9eba7055a9b018fc3304f9b149f2c1f27e4cf4d6a1996d7.yml +openapi_spec_hash: b99e78f4bfe7de8864c15a803bb0bb0b +config_hash: 60052b2c1c0862014416821aba875574 diff --git a/src/oz_agent_sdk/resources/agent/agent.py b/src/oz_agent_sdk/resources/agent/agent.py index a0240ce..b720375 100644 --- a/src/oz_agent_sdk/resources/agent/agent.py +++ b/src/oz_agent_sdk/resources/agent/agent.py @@ -193,6 +193,7 @@ def get_artifact( def run( self, *, + agent_identity_uid: str | Omit = omit, attachments: Iterable[agent_run_params.Attachment] | Omit = omit, config: AmbientAgentConfigParam | Omit = omit, conversation_id: str | Omit = omit, @@ -215,6 +216,9 @@ def run( runs. Behavior is identical to POST /agent/run. Args: + agent_identity_uid: Optional agent identity UID to use as the execution principal for the run. This + is only valid for runs that are team owned. + attachments: Optional file attachments to include with the prompt (max 5). Attachments are uploaded to cloud storage and made available to the agent. @@ -256,6 +260,7 @@ def run( "/agent/runs", body=maybe_transform( { + "agent_identity_uid": agent_identity_uid, "attachments": attachments, "config": config, "conversation_id": conversation_id, @@ -417,6 +422,7 @@ async def get_artifact( async def run( self, *, + agent_identity_uid: str | Omit = omit, attachments: Iterable[agent_run_params.Attachment] | Omit = omit, config: AmbientAgentConfigParam | Omit = omit, conversation_id: str | Omit = omit, @@ -439,6 +445,9 @@ async def run( runs. Behavior is identical to POST /agent/run. Args: + agent_identity_uid: Optional agent identity UID to use as the execution principal for the run. This + is only valid for runs that are team owned. + attachments: Optional file attachments to include with the prompt (max 5). Attachments are uploaded to cloud storage and made available to the agent. @@ -480,6 +489,7 @@ async def run( "/agent/runs", body=await async_maybe_transform( { + "agent_identity_uid": agent_identity_uid, "attachments": attachments, "config": config, "conversation_id": conversation_id, diff --git a/src/oz_agent_sdk/resources/agent/runs.py b/src/oz_agent_sdk/resources/agent/runs.py index e6e55b5..00c3f49 100644 --- a/src/oz_agent_sdk/resources/agent/runs.py +++ b/src/oz_agent_sdk/resources/agent/runs.py @@ -87,6 +87,7 @@ def retrieve( def list( self, *, + ancestor_run_id: str | Omit = omit, artifact_type: Literal["PLAN", "PULL_REQUEST", "SCREENSHOT", "FILE"] | Omit = omit, created_after: Union[str, datetime] | Omit = omit, created_before: Union[str, datetime] | Omit = omit, @@ -119,6 +120,9 @@ def list( to `sort_by=updated_at` and `sort_order=desc`. Args: + ancestor_run_id: Filter runs by ancestor run ID. The referenced run must exist and be accessible + to the caller. + artifact_type: Filter runs by artifact type created_after: Filter runs created after this timestamp (RFC3339 format) @@ -182,6 +186,7 @@ def list( timeout=timeout, query=maybe_transform( { + "ancestor_run_id": ancestor_run_id, "artifact_type": artifact_type, "created_after": created_after, "created_before": created_before, @@ -307,6 +312,7 @@ async def retrieve( def list( self, *, + ancestor_run_id: str | Omit = omit, artifact_type: Literal["PLAN", "PULL_REQUEST", "SCREENSHOT", "FILE"] | Omit = omit, created_after: Union[str, datetime] | Omit = omit, created_before: Union[str, datetime] | Omit = omit, @@ -339,6 +345,9 @@ def list( to `sort_by=updated_at` and `sort_order=desc`. Args: + ancestor_run_id: Filter runs by ancestor run ID. The referenced run must exist and be accessible + to the caller. + artifact_type: Filter runs by artifact type created_after: Filter runs created after this timestamp (RFC3339 format) @@ -402,6 +411,7 @@ def list( timeout=timeout, query=maybe_transform( { + "ancestor_run_id": ancestor_run_id, "artifact_type": artifact_type, "created_after": created_after, "created_before": created_before, diff --git a/src/oz_agent_sdk/types/agent/run_list_params.py b/src/oz_agent_sdk/types/agent/run_list_params.py index 0b4e389..b53a299 100644 --- a/src/oz_agent_sdk/types/agent/run_list_params.py +++ b/src/oz_agent_sdk/types/agent/run_list_params.py @@ -14,6 +14,12 @@ class RunListParams(TypedDict, total=False): + ancestor_run_id: str + """Filter runs by ancestor run ID. + + The referenced run must exist and be accessible to the caller. + """ + artifact_type: Literal["PLAN", "PULL_REQUEST", "SCREENSHOT", "FILE"] """Filter runs by artifact type""" diff --git a/src/oz_agent_sdk/types/agent_run_params.py b/src/oz_agent_sdk/types/agent_run_params.py index 2a346ed..5d185a5 100644 --- a/src/oz_agent_sdk/types/agent_run_params.py +++ b/src/oz_agent_sdk/types/agent_run_params.py @@ -14,6 +14,12 @@ class AgentRunParams(TypedDict, total=False): + agent_identity_uid: str + """ + Optional agent identity UID to use as the execution principal for the run. This + is only valid for runs that are team owned. + """ + attachments: Iterable[Attachment] """ Optional file attachments to include with the prompt (max 5). Attachments are diff --git a/tests/api_resources/agent/test_runs.py b/tests/api_resources/agent/test_runs.py index bf257f8..cf95a65 100644 --- a/tests/api_resources/agent/test_runs.py +++ b/tests/api_resources/agent/test_runs.py @@ -71,6 +71,7 @@ def test_method_list(self, client: OzAPI) -> None: @parametrize def test_method_list_with_all_params(self, client: OzAPI) -> None: run = client.agent.runs.list( + ancestor_run_id="ancestor_run_id", artifact_type="PLAN", created_after=parse_datetime("2019-12-27T18:11:19.117Z"), created_before=parse_datetime("2019-12-27T18:11:19.117Z"), @@ -215,6 +216,7 @@ async def test_method_list(self, async_client: AsyncOzAPI) -> None: @parametrize async def test_method_list_with_all_params(self, async_client: AsyncOzAPI) -> None: run = await async_client.agent.runs.list( + ancestor_run_id="ancestor_run_id", artifact_type="PLAN", created_after=parse_datetime("2019-12-27T18:11:19.117Z"), created_before=parse_datetime("2019-12-27T18:11:19.117Z"), diff --git a/tests/api_resources/test_agent.py b/tests/api_resources/test_agent.py index b641c09..70c07fb 100644 --- a/tests/api_resources/test_agent.py +++ b/tests/api_resources/test_agent.py @@ -112,6 +112,7 @@ def test_method_run(self, client: OzAPI) -> None: @parametrize def test_method_run_with_all_params(self, client: OzAPI) -> None: agent = client.agent.run( + agent_identity_uid="agent_identity_uid", attachments=[ { "data": "U3RhaW5sZXNzIHJvY2tz", @@ -272,6 +273,7 @@ async def test_method_run(self, async_client: AsyncOzAPI) -> None: @parametrize async def test_method_run_with_all_params(self, async_client: AsyncOzAPI) -> None: agent = await async_client.agent.run( + agent_identity_uid="agent_identity_uid", attachments=[ { "data": "U3RhaW5sZXNzIHJvY2tz", From b9872f2642191ef6e1d4d5d3542a08f9e2784b9e Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 10 Apr 2026 21:45:08 +0000 Subject: [PATCH 04/56] feat(api): api update --- .stats.yml | 8 +- api.md | 3 + src/oz_agent_sdk/resources/agent/agent.py | 103 +++++++++++++++++- src/oz_agent_sdk/types/__init__.py | 3 + .../types/agent_list_environments_params.py | 16 +++ .../types/agent_list_environments_response.py | 13 +++ src/oz_agent_sdk/types/cloud_environment.py | 74 +++++++++++++ tests/api_resources/test_agent.py | 73 +++++++++++++ 8 files changed, 288 insertions(+), 5 deletions(-) create mode 100644 src/oz_agent_sdk/types/agent_list_environments_params.py create mode 100644 src/oz_agent_sdk/types/agent_list_environments_response.py create mode 100644 src/oz_agent_sdk/types/cloud_environment.py diff --git a/.stats.yml b/.stats.yml index 874109f..4aeb8c7 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 14 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta%2Fwarp-api-96b15c5805e3554bc9eba7055a9b018fc3304f9b149f2c1f27e4cf4d6a1996d7.yml -openapi_spec_hash: b99e78f4bfe7de8864c15a803bb0bb0b -config_hash: 60052b2c1c0862014416821aba875574 +configured_endpoints: 15 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta%2Fwarp-api-f0355372540013156ff6e59d0c3789492855d5438b4672cf7812025a41ed15be.yml +openapi_spec_hash: e7c9330454695ffbef5704cfba5acac6 +config_hash: 253e4b5ca01236d448980a78491c17c5 diff --git a/api.md b/api.md index 3ef6227..065cedb 100644 --- a/api.md +++ b/api.md @@ -7,6 +7,7 @@ from oz_agent_sdk.types import ( AgentSkill, AmbientAgentConfig, AwsProviderConfig, + CloudEnvironment, CloudEnvironmentConfig, Error, ErrorCode, @@ -16,6 +17,7 @@ from oz_agent_sdk.types import ( UserProfile, AgentListResponse, AgentGetArtifactResponse, + AgentListEnvironmentsResponse, AgentRunResponse, ) ``` @@ -24,6 +26,7 @@ Methods: - client.agent.list(\*\*params) -> AgentListResponse - client.agent.get_artifact(artifact_uid) -> AgentGetArtifactResponse +- client.agent.list_environments(\*\*params) -> AgentListEnvironmentsResponse - client.agent.run(\*\*params) -> AgentRunResponse ## Runs diff --git a/src/oz_agent_sdk/resources/agent/agent.py b/src/oz_agent_sdk/resources/agent/agent.py index b720375..b28ef9a 100644 --- a/src/oz_agent_sdk/resources/agent/agent.py +++ b/src/oz_agent_sdk/resources/agent/agent.py @@ -15,7 +15,7 @@ RunsResourceWithStreamingResponse, AsyncRunsResourceWithStreamingResponse, ) -from ...types import agent_run_params, agent_list_params +from ...types import agent_run_params, agent_list_params, agent_list_environments_params from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given from ..._utils import path_template, maybe_transform, async_maybe_transform from .sessions import ( @@ -47,6 +47,7 @@ from ...types.agent_list_response import AgentListResponse from ...types.ambient_agent_config_param import AmbientAgentConfigParam from ...types.agent_get_artifact_response import AgentGetArtifactResponse +from ...types.agent_list_environments_response import AgentListEnvironmentsResponse __all__ = ["AgentResource", "AsyncAgentResource"] @@ -190,6 +191,49 @@ def get_artifact( ), ) + def list_environments( + self, + *, + sort_by: Literal["name", "last_updated"] | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> AgentListEnvironmentsResponse: + """Retrieve cloud environments accessible to the authenticated principal. + + Returns + environments the caller owns, has been granted guest access to, or has accessed + via link sharing. + + Args: + sort_by: Sort order for the returned environments. + + - `name`: alphabetical by environment name + - `last_updated`: most recently updated first (default) + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._get( + "/agent/environments", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform({"sort_by": sort_by}, agent_list_environments_params.AgentListEnvironmentsParams), + ), + cast_to=AgentListEnvironmentsResponse, + ) + def run( self, *, @@ -419,6 +463,51 @@ async def get_artifact( ), ) + async def list_environments( + self, + *, + sort_by: Literal["name", "last_updated"] | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> AgentListEnvironmentsResponse: + """Retrieve cloud environments accessible to the authenticated principal. + + Returns + environments the caller owns, has been granted guest access to, or has accessed + via link sharing. + + Args: + sort_by: Sort order for the returned environments. + + - `name`: alphabetical by environment name + - `last_updated`: most recently updated first (default) + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return await self._get( + "/agent/environments", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=await async_maybe_transform( + {"sort_by": sort_by}, agent_list_environments_params.AgentListEnvironmentsParams + ), + ), + cast_to=AgentListEnvironmentsResponse, + ) + async def run( self, *, @@ -519,6 +608,9 @@ def __init__(self, agent: AgentResource) -> None: self.get_artifact = to_raw_response_wrapper( agent.get_artifact, ) + self.list_environments = to_raw_response_wrapper( + agent.list_environments, + ) self.run = to_raw_response_wrapper( agent.run, ) @@ -549,6 +641,9 @@ def __init__(self, agent: AsyncAgentResource) -> None: self.get_artifact = async_to_raw_response_wrapper( agent.get_artifact, ) + self.list_environments = async_to_raw_response_wrapper( + agent.list_environments, + ) self.run = async_to_raw_response_wrapper( agent.run, ) @@ -579,6 +674,9 @@ def __init__(self, agent: AgentResource) -> None: self.get_artifact = to_streamed_response_wrapper( agent.get_artifact, ) + self.list_environments = to_streamed_response_wrapper( + agent.list_environments, + ) self.run = to_streamed_response_wrapper( agent.run, ) @@ -609,6 +707,9 @@ def __init__(self, agent: AsyncAgentResource) -> None: self.get_artifact = async_to_streamed_response_wrapper( agent.get_artifact, ) + self.list_environments = async_to_streamed_response_wrapper( + agent.list_environments, + ) self.run = async_to_streamed_response_wrapper( agent.run, ) diff --git a/src/oz_agent_sdk/types/__init__.py b/src/oz_agent_sdk/types/__init__.py index 4c520a7..e27ca02 100644 --- a/src/oz_agent_sdk/types/__init__.py +++ b/src/oz_agent_sdk/types/__init__.py @@ -8,6 +8,7 @@ from .user_profile import UserProfile as UserProfile from .agent_run_params import AgentRunParams as AgentRunParams from .agent_list_params import AgentListParams as AgentListParams +from .cloud_environment import CloudEnvironment as CloudEnvironment from .mcp_server_config import McpServerConfig as McpServerConfig from .agent_run_response import AgentRunResponse as AgentRunResponse from .agent_list_response import AgentListResponse as AgentListResponse @@ -18,3 +19,5 @@ from .cloud_environment_config import CloudEnvironmentConfig as CloudEnvironmentConfig from .ambient_agent_config_param import AmbientAgentConfigParam as AmbientAgentConfigParam from .agent_get_artifact_response import AgentGetArtifactResponse as AgentGetArtifactResponse +from .agent_list_environments_params import AgentListEnvironmentsParams as AgentListEnvironmentsParams +from .agent_list_environments_response import AgentListEnvironmentsResponse as AgentListEnvironmentsResponse diff --git a/src/oz_agent_sdk/types/agent_list_environments_params.py b/src/oz_agent_sdk/types/agent_list_environments_params.py new file mode 100644 index 0000000..481c31d --- /dev/null +++ b/src/oz_agent_sdk/types/agent_list_environments_params.py @@ -0,0 +1,16 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Literal, TypedDict + +__all__ = ["AgentListEnvironmentsParams"] + + +class AgentListEnvironmentsParams(TypedDict, total=False): + sort_by: Literal["name", "last_updated"] + """Sort order for the returned environments. + + - `name`: alphabetical by environment name + - `last_updated`: most recently updated first (default) + """ diff --git a/src/oz_agent_sdk/types/agent_list_environments_response.py b/src/oz_agent_sdk/types/agent_list_environments_response.py new file mode 100644 index 0000000..103845a --- /dev/null +++ b/src/oz_agent_sdk/types/agent_list_environments_response.py @@ -0,0 +1,13 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List + +from .._models import BaseModel +from .cloud_environment import CloudEnvironment + +__all__ = ["AgentListEnvironmentsResponse"] + + +class AgentListEnvironmentsResponse(BaseModel): + environments: List[CloudEnvironment] + """List of accessible cloud environments""" diff --git a/src/oz_agent_sdk/types/cloud_environment.py b/src/oz_agent_sdk/types/cloud_environment.py new file mode 100644 index 0000000..4bde98c --- /dev/null +++ b/src/oz_agent_sdk/types/cloud_environment.py @@ -0,0 +1,74 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional +from datetime import datetime + +from .scope import Scope +from .._models import BaseModel +from .user_profile import UserProfile +from .agent.run_state import RunState +from .cloud_environment_config import CloudEnvironmentConfig + +__all__ = ["CloudEnvironment", "LastTaskCreated"] + + +class LastTaskCreated(BaseModel): + """Summary of the most recently created task for an environment""" + + id: str + """Unique identifier of the task""" + + created_at: datetime + """When the task was created (RFC3339)""" + + state: RunState + """Current state of the run: + + - QUEUED: Run is waiting to be picked up + - PENDING: Run is being prepared + - CLAIMED: Run has been claimed by a worker + - INPROGRESS: Run is actively being executed + - SUCCEEDED: Run completed successfully + - FAILED: Run failed + - BLOCKED: Run is blocked (e.g., awaiting user input or approval) + - ERROR: Run encountered an error + - CANCELLED: Run was cancelled by user + """ + + title: str + """Title of the task""" + + updated_at: datetime + """When the task was last updated (RFC3339)""" + + started_at: Optional[datetime] = None + """When the task started running (RFC3339), null if not yet started""" + + +class CloudEnvironment(BaseModel): + """A cloud environment for running agents""" + + config: CloudEnvironmentConfig + """Configuration for a cloud environment used by scheduled agents""" + + last_updated: datetime + """Timestamp when the environment was last updated (RFC3339)""" + + setup_failed: bool + """True when the most recent task failed during setup before it started running""" + + uid: str + """Unique identifier for the environment""" + + creator: Optional[UserProfile] = None + + last_editor: Optional[UserProfile] = None + + last_task_created: Optional[LastTaskCreated] = None + """Summary of the most recently created task for an environment""" + + last_task_run_timestamp: Optional[datetime] = None + """Timestamp of the most recent task run in this environment (RFC3339)""" + + scope: Optional[Scope] = None + """Ownership scope for a resource (team or personal)""" diff --git a/tests/api_resources/test_agent.py b/tests/api_resources/test_agent.py index 70c07fb..bb24171 100644 --- a/tests/api_resources/test_agent.py +++ b/tests/api_resources/test_agent.py @@ -13,6 +13,7 @@ AgentRunResponse, AgentListResponse, AgentGetArtifactResponse, + AgentListEnvironmentsResponse, ) base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") @@ -102,6 +103,42 @@ def test_path_params_get_artifact(self, client: OzAPI) -> None: "", ) + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_list_environments(self, client: OzAPI) -> None: + agent = client.agent.list_environments() + assert_matches_type(AgentListEnvironmentsResponse, agent, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_list_environments_with_all_params(self, client: OzAPI) -> None: + agent = client.agent.list_environments( + sort_by="name", + ) + assert_matches_type(AgentListEnvironmentsResponse, agent, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_list_environments(self, client: OzAPI) -> None: + response = client.agent.with_raw_response.list_environments() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + agent = response.parse() + assert_matches_type(AgentListEnvironmentsResponse, agent, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_list_environments(self, client: OzAPI) -> None: + with client.agent.with_streaming_response.list_environments() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + agent = response.parse() + assert_matches_type(AgentListEnvironmentsResponse, agent, path=["response"]) + + assert cast(Any, response.is_closed) is True + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_method_run(self, client: OzAPI) -> None: @@ -263,6 +300,42 @@ async def test_path_params_get_artifact(self, async_client: AsyncOzAPI) -> None: "", ) + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_list_environments(self, async_client: AsyncOzAPI) -> None: + agent = await async_client.agent.list_environments() + assert_matches_type(AgentListEnvironmentsResponse, agent, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_list_environments_with_all_params(self, async_client: AsyncOzAPI) -> None: + agent = await async_client.agent.list_environments( + sort_by="name", + ) + assert_matches_type(AgentListEnvironmentsResponse, agent, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_list_environments(self, async_client: AsyncOzAPI) -> None: + response = await async_client.agent.with_raw_response.list_environments() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + agent = await response.parse() + assert_matches_type(AgentListEnvironmentsResponse, agent, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_list_environments(self, async_client: AsyncOzAPI) -> None: + async with async_client.agent.with_streaming_response.list_environments() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + agent = await response.parse() + assert_matches_type(AgentListEnvironmentsResponse, agent, path=["response"]) + + assert cast(Any, response.is_closed) is True + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_method_run(self, async_client: AsyncOzAPI) -> None: From a6d82f1a71ad8e0ff5f10c43cc81938babc1444e Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 10 Apr 2026 22:12:55 +0000 Subject: [PATCH 05/56] feat(api): api update --- .stats.yml | 8 +- api.md | 3 - src/oz_agent_sdk/resources/agent/agent.py | 103 +----------------- src/oz_agent_sdk/resources/agent/runs.py | 10 -- src/oz_agent_sdk/types/__init__.py | 3 - .../types/agent/run_list_params.py | 6 - .../types/agent_list_environments_params.py | 16 --- .../types/agent_list_environments_response.py | 13 --- src/oz_agent_sdk/types/cloud_environment.py | 74 ------------- tests/api_resources/agent/test_runs.py | 2 - tests/api_resources/test_agent.py | 73 ------------- 11 files changed, 5 insertions(+), 306 deletions(-) delete mode 100644 src/oz_agent_sdk/types/agent_list_environments_params.py delete mode 100644 src/oz_agent_sdk/types/agent_list_environments_response.py delete mode 100644 src/oz_agent_sdk/types/cloud_environment.py diff --git a/.stats.yml b/.stats.yml index 4aeb8c7..51b5464 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 15 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta%2Fwarp-api-f0355372540013156ff6e59d0c3789492855d5438b4672cf7812025a41ed15be.yml -openapi_spec_hash: e7c9330454695ffbef5704cfba5acac6 -config_hash: 253e4b5ca01236d448980a78491c17c5 +configured_endpoints: 14 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta%2Fwarp-api-8f9c749573846b07a55a3131b66456f0a592838c6bfc986ab30948df66cd6f11.yml +openapi_spec_hash: 59f1ac98ad6cf13b12c59196bcecffd7 +config_hash: 60052b2c1c0862014416821aba875574 diff --git a/api.md b/api.md index 065cedb..3ef6227 100644 --- a/api.md +++ b/api.md @@ -7,7 +7,6 @@ from oz_agent_sdk.types import ( AgentSkill, AmbientAgentConfig, AwsProviderConfig, - CloudEnvironment, CloudEnvironmentConfig, Error, ErrorCode, @@ -17,7 +16,6 @@ from oz_agent_sdk.types import ( UserProfile, AgentListResponse, AgentGetArtifactResponse, - AgentListEnvironmentsResponse, AgentRunResponse, ) ``` @@ -26,7 +24,6 @@ Methods: - client.agent.list(\*\*params) -> AgentListResponse - client.agent.get_artifact(artifact_uid) -> AgentGetArtifactResponse -- client.agent.list_environments(\*\*params) -> AgentListEnvironmentsResponse - client.agent.run(\*\*params) -> AgentRunResponse ## Runs diff --git a/src/oz_agent_sdk/resources/agent/agent.py b/src/oz_agent_sdk/resources/agent/agent.py index b28ef9a..b720375 100644 --- a/src/oz_agent_sdk/resources/agent/agent.py +++ b/src/oz_agent_sdk/resources/agent/agent.py @@ -15,7 +15,7 @@ RunsResourceWithStreamingResponse, AsyncRunsResourceWithStreamingResponse, ) -from ...types import agent_run_params, agent_list_params, agent_list_environments_params +from ...types import agent_run_params, agent_list_params from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given from ..._utils import path_template, maybe_transform, async_maybe_transform from .sessions import ( @@ -47,7 +47,6 @@ from ...types.agent_list_response import AgentListResponse from ...types.ambient_agent_config_param import AmbientAgentConfigParam from ...types.agent_get_artifact_response import AgentGetArtifactResponse -from ...types.agent_list_environments_response import AgentListEnvironmentsResponse __all__ = ["AgentResource", "AsyncAgentResource"] @@ -191,49 +190,6 @@ def get_artifact( ), ) - def list_environments( - self, - *, - sort_by: Literal["name", "last_updated"] | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> AgentListEnvironmentsResponse: - """Retrieve cloud environments accessible to the authenticated principal. - - Returns - environments the caller owns, has been granted guest access to, or has accessed - via link sharing. - - Args: - sort_by: Sort order for the returned environments. - - - `name`: alphabetical by environment name - - `last_updated`: most recently updated first (default) - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - return self._get( - "/agent/environments", - options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - query=maybe_transform({"sort_by": sort_by}, agent_list_environments_params.AgentListEnvironmentsParams), - ), - cast_to=AgentListEnvironmentsResponse, - ) - def run( self, *, @@ -463,51 +419,6 @@ async def get_artifact( ), ) - async def list_environments( - self, - *, - sort_by: Literal["name", "last_updated"] | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> AgentListEnvironmentsResponse: - """Retrieve cloud environments accessible to the authenticated principal. - - Returns - environments the caller owns, has been granted guest access to, or has accessed - via link sharing. - - Args: - sort_by: Sort order for the returned environments. - - - `name`: alphabetical by environment name - - `last_updated`: most recently updated first (default) - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - return await self._get( - "/agent/environments", - options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - query=await async_maybe_transform( - {"sort_by": sort_by}, agent_list_environments_params.AgentListEnvironmentsParams - ), - ), - cast_to=AgentListEnvironmentsResponse, - ) - async def run( self, *, @@ -608,9 +519,6 @@ def __init__(self, agent: AgentResource) -> None: self.get_artifact = to_raw_response_wrapper( agent.get_artifact, ) - self.list_environments = to_raw_response_wrapper( - agent.list_environments, - ) self.run = to_raw_response_wrapper( agent.run, ) @@ -641,9 +549,6 @@ def __init__(self, agent: AsyncAgentResource) -> None: self.get_artifact = async_to_raw_response_wrapper( agent.get_artifact, ) - self.list_environments = async_to_raw_response_wrapper( - agent.list_environments, - ) self.run = async_to_raw_response_wrapper( agent.run, ) @@ -674,9 +579,6 @@ def __init__(self, agent: AgentResource) -> None: self.get_artifact = to_streamed_response_wrapper( agent.get_artifact, ) - self.list_environments = to_streamed_response_wrapper( - agent.list_environments, - ) self.run = to_streamed_response_wrapper( agent.run, ) @@ -707,9 +609,6 @@ def __init__(self, agent: AsyncAgentResource) -> None: self.get_artifact = async_to_streamed_response_wrapper( agent.get_artifact, ) - self.list_environments = async_to_streamed_response_wrapper( - agent.list_environments, - ) self.run = async_to_streamed_response_wrapper( agent.run, ) diff --git a/src/oz_agent_sdk/resources/agent/runs.py b/src/oz_agent_sdk/resources/agent/runs.py index 00c3f49..e6e55b5 100644 --- a/src/oz_agent_sdk/resources/agent/runs.py +++ b/src/oz_agent_sdk/resources/agent/runs.py @@ -87,7 +87,6 @@ def retrieve( def list( self, *, - ancestor_run_id: str | Omit = omit, artifact_type: Literal["PLAN", "PULL_REQUEST", "SCREENSHOT", "FILE"] | Omit = omit, created_after: Union[str, datetime] | Omit = omit, created_before: Union[str, datetime] | Omit = omit, @@ -120,9 +119,6 @@ def list( to `sort_by=updated_at` and `sort_order=desc`. Args: - ancestor_run_id: Filter runs by ancestor run ID. The referenced run must exist and be accessible - to the caller. - artifact_type: Filter runs by artifact type created_after: Filter runs created after this timestamp (RFC3339 format) @@ -186,7 +182,6 @@ def list( timeout=timeout, query=maybe_transform( { - "ancestor_run_id": ancestor_run_id, "artifact_type": artifact_type, "created_after": created_after, "created_before": created_before, @@ -312,7 +307,6 @@ async def retrieve( def list( self, *, - ancestor_run_id: str | Omit = omit, artifact_type: Literal["PLAN", "PULL_REQUEST", "SCREENSHOT", "FILE"] | Omit = omit, created_after: Union[str, datetime] | Omit = omit, created_before: Union[str, datetime] | Omit = omit, @@ -345,9 +339,6 @@ def list( to `sort_by=updated_at` and `sort_order=desc`. Args: - ancestor_run_id: Filter runs by ancestor run ID. The referenced run must exist and be accessible - to the caller. - artifact_type: Filter runs by artifact type created_after: Filter runs created after this timestamp (RFC3339 format) @@ -411,7 +402,6 @@ def list( timeout=timeout, query=maybe_transform( { - "ancestor_run_id": ancestor_run_id, "artifact_type": artifact_type, "created_after": created_after, "created_before": created_before, diff --git a/src/oz_agent_sdk/types/__init__.py b/src/oz_agent_sdk/types/__init__.py index e27ca02..4c520a7 100644 --- a/src/oz_agent_sdk/types/__init__.py +++ b/src/oz_agent_sdk/types/__init__.py @@ -8,7 +8,6 @@ from .user_profile import UserProfile as UserProfile from .agent_run_params import AgentRunParams as AgentRunParams from .agent_list_params import AgentListParams as AgentListParams -from .cloud_environment import CloudEnvironment as CloudEnvironment from .mcp_server_config import McpServerConfig as McpServerConfig from .agent_run_response import AgentRunResponse as AgentRunResponse from .agent_list_response import AgentListResponse as AgentListResponse @@ -19,5 +18,3 @@ from .cloud_environment_config import CloudEnvironmentConfig as CloudEnvironmentConfig from .ambient_agent_config_param import AmbientAgentConfigParam as AmbientAgentConfigParam from .agent_get_artifact_response import AgentGetArtifactResponse as AgentGetArtifactResponse -from .agent_list_environments_params import AgentListEnvironmentsParams as AgentListEnvironmentsParams -from .agent_list_environments_response import AgentListEnvironmentsResponse as AgentListEnvironmentsResponse diff --git a/src/oz_agent_sdk/types/agent/run_list_params.py b/src/oz_agent_sdk/types/agent/run_list_params.py index b53a299..0b4e389 100644 --- a/src/oz_agent_sdk/types/agent/run_list_params.py +++ b/src/oz_agent_sdk/types/agent/run_list_params.py @@ -14,12 +14,6 @@ class RunListParams(TypedDict, total=False): - ancestor_run_id: str - """Filter runs by ancestor run ID. - - The referenced run must exist and be accessible to the caller. - """ - artifact_type: Literal["PLAN", "PULL_REQUEST", "SCREENSHOT", "FILE"] """Filter runs by artifact type""" diff --git a/src/oz_agent_sdk/types/agent_list_environments_params.py b/src/oz_agent_sdk/types/agent_list_environments_params.py deleted file mode 100644 index 481c31d..0000000 --- a/src/oz_agent_sdk/types/agent_list_environments_params.py +++ /dev/null @@ -1,16 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing_extensions import Literal, TypedDict - -__all__ = ["AgentListEnvironmentsParams"] - - -class AgentListEnvironmentsParams(TypedDict, total=False): - sort_by: Literal["name", "last_updated"] - """Sort order for the returned environments. - - - `name`: alphabetical by environment name - - `last_updated`: most recently updated first (default) - """ diff --git a/src/oz_agent_sdk/types/agent_list_environments_response.py b/src/oz_agent_sdk/types/agent_list_environments_response.py deleted file mode 100644 index 103845a..0000000 --- a/src/oz_agent_sdk/types/agent_list_environments_response.py +++ /dev/null @@ -1,13 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import List - -from .._models import BaseModel -from .cloud_environment import CloudEnvironment - -__all__ = ["AgentListEnvironmentsResponse"] - - -class AgentListEnvironmentsResponse(BaseModel): - environments: List[CloudEnvironment] - """List of accessible cloud environments""" diff --git a/src/oz_agent_sdk/types/cloud_environment.py b/src/oz_agent_sdk/types/cloud_environment.py deleted file mode 100644 index 4bde98c..0000000 --- a/src/oz_agent_sdk/types/cloud_environment.py +++ /dev/null @@ -1,74 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import Optional -from datetime import datetime - -from .scope import Scope -from .._models import BaseModel -from .user_profile import UserProfile -from .agent.run_state import RunState -from .cloud_environment_config import CloudEnvironmentConfig - -__all__ = ["CloudEnvironment", "LastTaskCreated"] - - -class LastTaskCreated(BaseModel): - """Summary of the most recently created task for an environment""" - - id: str - """Unique identifier of the task""" - - created_at: datetime - """When the task was created (RFC3339)""" - - state: RunState - """Current state of the run: - - - QUEUED: Run is waiting to be picked up - - PENDING: Run is being prepared - - CLAIMED: Run has been claimed by a worker - - INPROGRESS: Run is actively being executed - - SUCCEEDED: Run completed successfully - - FAILED: Run failed - - BLOCKED: Run is blocked (e.g., awaiting user input or approval) - - ERROR: Run encountered an error - - CANCELLED: Run was cancelled by user - """ - - title: str - """Title of the task""" - - updated_at: datetime - """When the task was last updated (RFC3339)""" - - started_at: Optional[datetime] = None - """When the task started running (RFC3339), null if not yet started""" - - -class CloudEnvironment(BaseModel): - """A cloud environment for running agents""" - - config: CloudEnvironmentConfig - """Configuration for a cloud environment used by scheduled agents""" - - last_updated: datetime - """Timestamp when the environment was last updated (RFC3339)""" - - setup_failed: bool - """True when the most recent task failed during setup before it started running""" - - uid: str - """Unique identifier for the environment""" - - creator: Optional[UserProfile] = None - - last_editor: Optional[UserProfile] = None - - last_task_created: Optional[LastTaskCreated] = None - """Summary of the most recently created task for an environment""" - - last_task_run_timestamp: Optional[datetime] = None - """Timestamp of the most recent task run in this environment (RFC3339)""" - - scope: Optional[Scope] = None - """Ownership scope for a resource (team or personal)""" diff --git a/tests/api_resources/agent/test_runs.py b/tests/api_resources/agent/test_runs.py index cf95a65..bf257f8 100644 --- a/tests/api_resources/agent/test_runs.py +++ b/tests/api_resources/agent/test_runs.py @@ -71,7 +71,6 @@ def test_method_list(self, client: OzAPI) -> None: @parametrize def test_method_list_with_all_params(self, client: OzAPI) -> None: run = client.agent.runs.list( - ancestor_run_id="ancestor_run_id", artifact_type="PLAN", created_after=parse_datetime("2019-12-27T18:11:19.117Z"), created_before=parse_datetime("2019-12-27T18:11:19.117Z"), @@ -216,7 +215,6 @@ async def test_method_list(self, async_client: AsyncOzAPI) -> None: @parametrize async def test_method_list_with_all_params(self, async_client: AsyncOzAPI) -> None: run = await async_client.agent.runs.list( - ancestor_run_id="ancestor_run_id", artifact_type="PLAN", created_after=parse_datetime("2019-12-27T18:11:19.117Z"), created_before=parse_datetime("2019-12-27T18:11:19.117Z"), diff --git a/tests/api_resources/test_agent.py b/tests/api_resources/test_agent.py index bb24171..70c07fb 100644 --- a/tests/api_resources/test_agent.py +++ b/tests/api_resources/test_agent.py @@ -13,7 +13,6 @@ AgentRunResponse, AgentListResponse, AgentGetArtifactResponse, - AgentListEnvironmentsResponse, ) base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") @@ -103,42 +102,6 @@ def test_path_params_get_artifact(self, client: OzAPI) -> None: "", ) - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_method_list_environments(self, client: OzAPI) -> None: - agent = client.agent.list_environments() - assert_matches_type(AgentListEnvironmentsResponse, agent, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_method_list_environments_with_all_params(self, client: OzAPI) -> None: - agent = client.agent.list_environments( - sort_by="name", - ) - assert_matches_type(AgentListEnvironmentsResponse, agent, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_raw_response_list_environments(self, client: OzAPI) -> None: - response = client.agent.with_raw_response.list_environments() - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - agent = response.parse() - assert_matches_type(AgentListEnvironmentsResponse, agent, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_streaming_response_list_environments(self, client: OzAPI) -> None: - with client.agent.with_streaming_response.list_environments() as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - agent = response.parse() - assert_matches_type(AgentListEnvironmentsResponse, agent, path=["response"]) - - assert cast(Any, response.is_closed) is True - @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_method_run(self, client: OzAPI) -> None: @@ -300,42 +263,6 @@ async def test_path_params_get_artifact(self, async_client: AsyncOzAPI) -> None: "", ) - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_method_list_environments(self, async_client: AsyncOzAPI) -> None: - agent = await async_client.agent.list_environments() - assert_matches_type(AgentListEnvironmentsResponse, agent, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_method_list_environments_with_all_params(self, async_client: AsyncOzAPI) -> None: - agent = await async_client.agent.list_environments( - sort_by="name", - ) - assert_matches_type(AgentListEnvironmentsResponse, agent, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_raw_response_list_environments(self, async_client: AsyncOzAPI) -> None: - response = await async_client.agent.with_raw_response.list_environments() - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - agent = await response.parse() - assert_matches_type(AgentListEnvironmentsResponse, agent, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_streaming_response_list_environments(self, async_client: AsyncOzAPI) -> None: - async with async_client.agent.with_streaming_response.list_environments() as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - agent = await response.parse() - assert_matches_type(AgentListEnvironmentsResponse, agent, path=["response"]) - - assert cast(Any, response.is_closed) is True - @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_method_run(self, async_client: AsyncOzAPI) -> None: From 6032a0ccfe2ce669ce1f815ad853b912d4ca575e Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 13 Apr 2026 16:12:16 +0000 Subject: [PATCH 06/56] feat: Inject auth secrets via ambient agent config. --- .stats.yml | 4 +-- .../types/ambient_agent_config.py | 31 +++++++++++++------ .../types/ambient_agent_config_param.py | 31 +++++++++++++------ tests/api_resources/agent/test_schedules.py | 24 +++++--------- tests/api_resources/test_agent.py | 12 +++---- 5 files changed, 56 insertions(+), 46 deletions(-) diff --git a/.stats.yml b/.stats.yml index 51b5464..355c722 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 14 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta%2Fwarp-api-8f9c749573846b07a55a3131b66456f0a592838c6bfc986ab30948df66cd6f11.yml -openapi_spec_hash: 59f1ac98ad6cf13b12c59196bcecffd7 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta%2Fwarp-api-e84e9a84f73c707b6543dcb8052c7d6bec5a6dae80f1fe77aeedf9133e10a4b8.yml +openapi_spec_hash: ba9556a8fa64b9d1e88a27a2d467b835 config_hash: 60052b2c1c0862014416821aba875574 diff --git a/src/oz_agent_sdk/types/ambient_agent_config.py b/src/oz_agent_sdk/types/ambient_agent_config.py index abd16c1..69eaf3a 100644 --- a/src/oz_agent_sdk/types/ambient_agent_config.py +++ b/src/oz_agent_sdk/types/ambient_agent_config.py @@ -8,7 +8,7 @@ from .._models import BaseModel from .mcp_server_config import McpServerConfig -__all__ = ["AmbientAgentConfig", "Harness"] +__all__ = ["AmbientAgentConfig", "Harness", "HarnessAuthSecrets"] class Harness(BaseModel): @@ -17,15 +17,6 @@ class Harness(BaseModel): Default (nil/empty) uses Warp's built-in harness. """ - auth_secret_name: Optional[str] = None - """Name of a managed secret to use as the authentication credential for the - harness. - - The secret must exist within the caller's personal or team scope. The - environment variable injected into the agent is determined by the secret type - (e.g. ANTHROPIC_API_KEY for anthropic_api_key secrets). - """ - type: Optional[Literal["oz", "claude"]] = None """The harness type identifier. @@ -34,6 +25,20 @@ class Harness(BaseModel): """ +class HarnessAuthSecrets(BaseModel): + """ + Authentication secrets for third-party harnesses. + Only the secret for the harness specified gets injected into the environment. + """ + + claude_auth_secret_name: Optional[str] = None + """ + Name of a managed secret for Claude Code harness authentication. The secret must + exist within the caller's personal or team scope. Only applicable when harness + type is "claude". + """ + + class AmbientAgentConfig(BaseModel): """Configuration for a cloud agent run""" @@ -55,6 +60,12 @@ class AmbientAgentConfig(BaseModel): uses Warp's built-in harness. """ + harness_auth_secrets: Optional[HarnessAuthSecrets] = None + """ + Authentication secrets for third-party harnesses. Only the secret for the + harness specified gets injected into the environment. + """ + idle_timeout_minutes: Optional[int] = None """ Number of minutes to keep the agent environment alive after task completion. If diff --git a/src/oz_agent_sdk/types/ambient_agent_config_param.py b/src/oz_agent_sdk/types/ambient_agent_config_param.py index 24da607..8ea7901 100644 --- a/src/oz_agent_sdk/types/ambient_agent_config_param.py +++ b/src/oz_agent_sdk/types/ambient_agent_config_param.py @@ -7,7 +7,7 @@ from .mcp_server_config_param import McpServerConfigParam -__all__ = ["AmbientAgentConfigParam", "Harness"] +__all__ = ["AmbientAgentConfigParam", "Harness", "HarnessAuthSecrets"] class Harness(TypedDict, total=False): @@ -16,15 +16,6 @@ class Harness(TypedDict, total=False): Default (nil/empty) uses Warp's built-in harness. """ - auth_secret_name: str - """Name of a managed secret to use as the authentication credential for the - harness. - - The secret must exist within the caller's personal or team scope. The - environment variable injected into the agent is determined by the secret type - (e.g. ANTHROPIC_API_KEY for anthropic_api_key secrets). - """ - type: Literal["oz", "claude"] """The harness type identifier. @@ -33,6 +24,20 @@ class Harness(TypedDict, total=False): """ +class HarnessAuthSecrets(TypedDict, total=False): + """ + Authentication secrets for third-party harnesses. + Only the secret for the harness specified gets injected into the environment. + """ + + claude_auth_secret_name: str + """ + Name of a managed secret for Claude Code harness authentication. The secret must + exist within the caller's personal or team scope. Only applicable when harness + type is "claude". + """ + + class AmbientAgentConfigParam(TypedDict, total=False): """Configuration for a cloud agent run""" @@ -54,6 +59,12 @@ class AmbientAgentConfigParam(TypedDict, total=False): uses Warp's built-in harness. """ + harness_auth_secrets: HarnessAuthSecrets + """ + Authentication secrets for third-party harnesses. Only the secret for the + harness specified gets injected into the environment. + """ + idle_timeout_minutes: int """ Number of minutes to keep the agent environment alive after task completion. If diff --git a/tests/api_resources/agent/test_schedules.py b/tests/api_resources/agent/test_schedules.py index 9b22b45..51fbae1 100644 --- a/tests/api_resources/agent/test_schedules.py +++ b/tests/api_resources/agent/test_schedules.py @@ -40,10 +40,8 @@ def test_method_create_with_all_params(self, client: OzAPI) -> None: "base_prompt": "base_prompt", "computer_use_enabled": True, "environment_id": "environment_id", - "harness": { - "auth_secret_name": "auth_secret_name", - "type": "oz", - }, + "harness": {"type": "oz"}, + "harness_auth_secrets": {"claude_auth_secret_name": "claude_auth_secret_name"}, "idle_timeout_minutes": 1, "mcp_servers": { "foo": { @@ -159,10 +157,8 @@ def test_method_update_with_all_params(self, client: OzAPI) -> None: "base_prompt": "base_prompt", "computer_use_enabled": True, "environment_id": "environment_id", - "harness": { - "auth_secret_name": "auth_secret_name", - "type": "oz", - }, + "harness": {"type": "oz"}, + "harness_auth_secrets": {"claude_auth_secret_name": "claude_auth_secret_name"}, "idle_timeout_minutes": 1, "mcp_servers": { "foo": { @@ -405,10 +401,8 @@ async def test_method_create_with_all_params(self, async_client: AsyncOzAPI) -> "base_prompt": "base_prompt", "computer_use_enabled": True, "environment_id": "environment_id", - "harness": { - "auth_secret_name": "auth_secret_name", - "type": "oz", - }, + "harness": {"type": "oz"}, + "harness_auth_secrets": {"claude_auth_secret_name": "claude_auth_secret_name"}, "idle_timeout_minutes": 1, "mcp_servers": { "foo": { @@ -524,10 +518,8 @@ async def test_method_update_with_all_params(self, async_client: AsyncOzAPI) -> "base_prompt": "base_prompt", "computer_use_enabled": True, "environment_id": "environment_id", - "harness": { - "auth_secret_name": "auth_secret_name", - "type": "oz", - }, + "harness": {"type": "oz"}, + "harness_auth_secrets": {"claude_auth_secret_name": "claude_auth_secret_name"}, "idle_timeout_minutes": 1, "mcp_servers": { "foo": { diff --git a/tests/api_resources/test_agent.py b/tests/api_resources/test_agent.py index 70c07fb..af024da 100644 --- a/tests/api_resources/test_agent.py +++ b/tests/api_resources/test_agent.py @@ -124,10 +124,8 @@ def test_method_run_with_all_params(self, client: OzAPI) -> None: "base_prompt": "base_prompt", "computer_use_enabled": True, "environment_id": "environment_id", - "harness": { - "auth_secret_name": "auth_secret_name", - "type": "oz", - }, + "harness": {"type": "oz"}, + "harness_auth_secrets": {"claude_auth_secret_name": "claude_auth_secret_name"}, "idle_timeout_minutes": 1, "mcp_servers": { "foo": { @@ -285,10 +283,8 @@ async def test_method_run_with_all_params(self, async_client: AsyncOzAPI) -> Non "base_prompt": "base_prompt", "computer_use_enabled": True, "environment_id": "environment_id", - "harness": { - "auth_secret_name": "auth_secret_name", - "type": "oz", - }, + "harness": {"type": "oz"}, + "harness_auth_secrets": {"claude_auth_secret_name": "claude_auth_secret_name"}, "idle_timeout_minutes": 1, "mcp_servers": { "foo": { From cf288045d369ed927db45ac5e5ebd994ccebb547 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 13 Apr 2026 17:51:10 +0000 Subject: [PATCH 07/56] feat(api): api update --- .stats.yml | 4 +-- .../types/ambient_agent_config.py | 31 ++++++------------- .../types/ambient_agent_config_param.py | 31 ++++++------------- tests/api_resources/agent/test_schedules.py | 24 +++++++++----- tests/api_resources/test_agent.py | 12 ++++--- 5 files changed, 46 insertions(+), 56 deletions(-) diff --git a/.stats.yml b/.stats.yml index 355c722..51b5464 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 14 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta%2Fwarp-api-e84e9a84f73c707b6543dcb8052c7d6bec5a6dae80f1fe77aeedf9133e10a4b8.yml -openapi_spec_hash: ba9556a8fa64b9d1e88a27a2d467b835 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta%2Fwarp-api-8f9c749573846b07a55a3131b66456f0a592838c6bfc986ab30948df66cd6f11.yml +openapi_spec_hash: 59f1ac98ad6cf13b12c59196bcecffd7 config_hash: 60052b2c1c0862014416821aba875574 diff --git a/src/oz_agent_sdk/types/ambient_agent_config.py b/src/oz_agent_sdk/types/ambient_agent_config.py index 69eaf3a..abd16c1 100644 --- a/src/oz_agent_sdk/types/ambient_agent_config.py +++ b/src/oz_agent_sdk/types/ambient_agent_config.py @@ -8,7 +8,7 @@ from .._models import BaseModel from .mcp_server_config import McpServerConfig -__all__ = ["AmbientAgentConfig", "Harness", "HarnessAuthSecrets"] +__all__ = ["AmbientAgentConfig", "Harness"] class Harness(BaseModel): @@ -17,6 +17,15 @@ class Harness(BaseModel): Default (nil/empty) uses Warp's built-in harness. """ + auth_secret_name: Optional[str] = None + """Name of a managed secret to use as the authentication credential for the + harness. + + The secret must exist within the caller's personal or team scope. The + environment variable injected into the agent is determined by the secret type + (e.g. ANTHROPIC_API_KEY for anthropic_api_key secrets). + """ + type: Optional[Literal["oz", "claude"]] = None """The harness type identifier. @@ -25,20 +34,6 @@ class Harness(BaseModel): """ -class HarnessAuthSecrets(BaseModel): - """ - Authentication secrets for third-party harnesses. - Only the secret for the harness specified gets injected into the environment. - """ - - claude_auth_secret_name: Optional[str] = None - """ - Name of a managed secret for Claude Code harness authentication. The secret must - exist within the caller's personal or team scope. Only applicable when harness - type is "claude". - """ - - class AmbientAgentConfig(BaseModel): """Configuration for a cloud agent run""" @@ -60,12 +55,6 @@ class AmbientAgentConfig(BaseModel): uses Warp's built-in harness. """ - harness_auth_secrets: Optional[HarnessAuthSecrets] = None - """ - Authentication secrets for third-party harnesses. Only the secret for the - harness specified gets injected into the environment. - """ - idle_timeout_minutes: Optional[int] = None """ Number of minutes to keep the agent environment alive after task completion. If diff --git a/src/oz_agent_sdk/types/ambient_agent_config_param.py b/src/oz_agent_sdk/types/ambient_agent_config_param.py index 8ea7901..24da607 100644 --- a/src/oz_agent_sdk/types/ambient_agent_config_param.py +++ b/src/oz_agent_sdk/types/ambient_agent_config_param.py @@ -7,7 +7,7 @@ from .mcp_server_config_param import McpServerConfigParam -__all__ = ["AmbientAgentConfigParam", "Harness", "HarnessAuthSecrets"] +__all__ = ["AmbientAgentConfigParam", "Harness"] class Harness(TypedDict, total=False): @@ -16,6 +16,15 @@ class Harness(TypedDict, total=False): Default (nil/empty) uses Warp's built-in harness. """ + auth_secret_name: str + """Name of a managed secret to use as the authentication credential for the + harness. + + The secret must exist within the caller's personal or team scope. The + environment variable injected into the agent is determined by the secret type + (e.g. ANTHROPIC_API_KEY for anthropic_api_key secrets). + """ + type: Literal["oz", "claude"] """The harness type identifier. @@ -24,20 +33,6 @@ class Harness(TypedDict, total=False): """ -class HarnessAuthSecrets(TypedDict, total=False): - """ - Authentication secrets for third-party harnesses. - Only the secret for the harness specified gets injected into the environment. - """ - - claude_auth_secret_name: str - """ - Name of a managed secret for Claude Code harness authentication. The secret must - exist within the caller's personal or team scope. Only applicable when harness - type is "claude". - """ - - class AmbientAgentConfigParam(TypedDict, total=False): """Configuration for a cloud agent run""" @@ -59,12 +54,6 @@ class AmbientAgentConfigParam(TypedDict, total=False): uses Warp's built-in harness. """ - harness_auth_secrets: HarnessAuthSecrets - """ - Authentication secrets for third-party harnesses. Only the secret for the - harness specified gets injected into the environment. - """ - idle_timeout_minutes: int """ Number of minutes to keep the agent environment alive after task completion. If diff --git a/tests/api_resources/agent/test_schedules.py b/tests/api_resources/agent/test_schedules.py index 51fbae1..9b22b45 100644 --- a/tests/api_resources/agent/test_schedules.py +++ b/tests/api_resources/agent/test_schedules.py @@ -40,8 +40,10 @@ def test_method_create_with_all_params(self, client: OzAPI) -> None: "base_prompt": "base_prompt", "computer_use_enabled": True, "environment_id": "environment_id", - "harness": {"type": "oz"}, - "harness_auth_secrets": {"claude_auth_secret_name": "claude_auth_secret_name"}, + "harness": { + "auth_secret_name": "auth_secret_name", + "type": "oz", + }, "idle_timeout_minutes": 1, "mcp_servers": { "foo": { @@ -157,8 +159,10 @@ def test_method_update_with_all_params(self, client: OzAPI) -> None: "base_prompt": "base_prompt", "computer_use_enabled": True, "environment_id": "environment_id", - "harness": {"type": "oz"}, - "harness_auth_secrets": {"claude_auth_secret_name": "claude_auth_secret_name"}, + "harness": { + "auth_secret_name": "auth_secret_name", + "type": "oz", + }, "idle_timeout_minutes": 1, "mcp_servers": { "foo": { @@ -401,8 +405,10 @@ async def test_method_create_with_all_params(self, async_client: AsyncOzAPI) -> "base_prompt": "base_prompt", "computer_use_enabled": True, "environment_id": "environment_id", - "harness": {"type": "oz"}, - "harness_auth_secrets": {"claude_auth_secret_name": "claude_auth_secret_name"}, + "harness": { + "auth_secret_name": "auth_secret_name", + "type": "oz", + }, "idle_timeout_minutes": 1, "mcp_servers": { "foo": { @@ -518,8 +524,10 @@ async def test_method_update_with_all_params(self, async_client: AsyncOzAPI) -> "base_prompt": "base_prompt", "computer_use_enabled": True, "environment_id": "environment_id", - "harness": {"type": "oz"}, - "harness_auth_secrets": {"claude_auth_secret_name": "claude_auth_secret_name"}, + "harness": { + "auth_secret_name": "auth_secret_name", + "type": "oz", + }, "idle_timeout_minutes": 1, "mcp_servers": { "foo": { diff --git a/tests/api_resources/test_agent.py b/tests/api_resources/test_agent.py index af024da..70c07fb 100644 --- a/tests/api_resources/test_agent.py +++ b/tests/api_resources/test_agent.py @@ -124,8 +124,10 @@ def test_method_run_with_all_params(self, client: OzAPI) -> None: "base_prompt": "base_prompt", "computer_use_enabled": True, "environment_id": "environment_id", - "harness": {"type": "oz"}, - "harness_auth_secrets": {"claude_auth_secret_name": "claude_auth_secret_name"}, + "harness": { + "auth_secret_name": "auth_secret_name", + "type": "oz", + }, "idle_timeout_minutes": 1, "mcp_servers": { "foo": { @@ -283,8 +285,10 @@ async def test_method_run_with_all_params(self, async_client: AsyncOzAPI) -> Non "base_prompt": "base_prompt", "computer_use_enabled": True, "environment_id": "environment_id", - "harness": {"type": "oz"}, - "harness_auth_secrets": {"claude_auth_secret_name": "claude_auth_secret_name"}, + "harness": { + "auth_secret_name": "auth_secret_name", + "type": "oz", + }, "idle_timeout_minutes": 1, "mcp_servers": { "foo": { From 1ffc53b4d69eeb8060faac1903f1ba25f7a4c443 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 13 Apr 2026 21:20:42 +0000 Subject: [PATCH 08/56] feat(api): api update --- .stats.yml | 8 +- api.md | 3 + src/oz_agent_sdk/resources/agent/agent.py | 113 +++++++++++++++++- src/oz_agent_sdk/resources/agent/runs.py | 10 ++ src/oz_agent_sdk/types/__init__.py | 3 + src/oz_agent_sdk/types/agent/artifact_item.py | 9 ++ .../types/agent/run_list_params.py | 6 + .../types/agent_get_artifact_response.py | 43 ++++++- .../types/agent_list_environments_params.py | 16 +++ .../types/agent_list_environments_response.py | 13 ++ .../types/ambient_agent_config.py | 31 +++-- .../types/ambient_agent_config_param.py | 31 +++-- src/oz_agent_sdk/types/cloud_environment.py | 74 ++++++++++++ tests/api_resources/agent/test_runs.py | 2 + tests/api_resources/agent/test_schedules.py | 24 ++-- tests/api_resources/test_agent.py | 85 +++++++++++-- 16 files changed, 417 insertions(+), 54 deletions(-) create mode 100644 src/oz_agent_sdk/types/agent_list_environments_params.py create mode 100644 src/oz_agent_sdk/types/agent_list_environments_response.py create mode 100644 src/oz_agent_sdk/types/cloud_environment.py diff --git a/.stats.yml b/.stats.yml index 51b5464..0b3ef0b 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 14 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta%2Fwarp-api-8f9c749573846b07a55a3131b66456f0a592838c6bfc986ab30948df66cd6f11.yml -openapi_spec_hash: 59f1ac98ad6cf13b12c59196bcecffd7 -config_hash: 60052b2c1c0862014416821aba875574 +configured_endpoints: 15 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta%2Fwarp-api-abde9a81e648a7bbddbb7c7af07eb9202e584f78dea9cc79ff075da2ad66efd5.yml +openapi_spec_hash: db45809e85b0f85020a6b046c6eed90e +config_hash: 253e4b5ca01236d448980a78491c17c5 diff --git a/api.md b/api.md index 3ef6227..065cedb 100644 --- a/api.md +++ b/api.md @@ -7,6 +7,7 @@ from oz_agent_sdk.types import ( AgentSkill, AmbientAgentConfig, AwsProviderConfig, + CloudEnvironment, CloudEnvironmentConfig, Error, ErrorCode, @@ -16,6 +17,7 @@ from oz_agent_sdk.types import ( UserProfile, AgentListResponse, AgentGetArtifactResponse, + AgentListEnvironmentsResponse, AgentRunResponse, ) ``` @@ -24,6 +26,7 @@ Methods: - client.agent.list(\*\*params) -> AgentListResponse - client.agent.get_artifact(artifact_uid) -> AgentGetArtifactResponse +- client.agent.list_environments(\*\*params) -> AgentListEnvironmentsResponse - client.agent.run(\*\*params) -> AgentRunResponse ## Runs diff --git a/src/oz_agent_sdk/resources/agent/agent.py b/src/oz_agent_sdk/resources/agent/agent.py index b720375..d8d58ef 100644 --- a/src/oz_agent_sdk/resources/agent/agent.py +++ b/src/oz_agent_sdk/resources/agent/agent.py @@ -15,7 +15,7 @@ RunsResourceWithStreamingResponse, AsyncRunsResourceWithStreamingResponse, ) -from ...types import agent_run_params, agent_list_params +from ...types import agent_run_params, agent_list_params, agent_list_environments_params from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given from ..._utils import path_template, maybe_transform, async_maybe_transform from .sessions import ( @@ -47,6 +47,7 @@ from ...types.agent_list_response import AgentListResponse from ...types.ambient_agent_config_param import AmbientAgentConfigParam from ...types.agent_get_artifact_response import AgentGetArtifactResponse +from ...types.agent_list_environments_response import AgentListEnvironmentsResponse __all__ = ["AgentResource", "AsyncAgentResource"] @@ -163,8 +164,9 @@ def get_artifact( ) -> AgentGetArtifactResponse: """Retrieve an artifact by its UUID. - For supported downloadable artifacts, returns - a time-limited signed download URL. + For downloadable file-like artifacts, returns + a time-limited signed download URL. For plan artifacts, returns the current plan + content inline. Args: extra_headers: Send extra headers @@ -190,6 +192,49 @@ def get_artifact( ), ) + def list_environments( + self, + *, + sort_by: Literal["name", "last_updated"] | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> AgentListEnvironmentsResponse: + """Retrieve cloud environments accessible to the authenticated principal. + + Returns + environments the caller owns, has been granted guest access to, or has accessed + via link sharing. + + Args: + sort_by: Sort order for the returned environments. + + - `name`: alphabetical by environment name + - `last_updated`: most recently updated first (default) + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._get( + "/agent/environments", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform({"sort_by": sort_by}, agent_list_environments_params.AgentListEnvironmentsParams), + ), + cast_to=AgentListEnvironmentsResponse, + ) + def run( self, *, @@ -392,8 +437,9 @@ async def get_artifact( ) -> AgentGetArtifactResponse: """Retrieve an artifact by its UUID. - For supported downloadable artifacts, returns - a time-limited signed download URL. + For downloadable file-like artifacts, returns + a time-limited signed download URL. For plan artifacts, returns the current plan + content inline. Args: extra_headers: Send extra headers @@ -419,6 +465,51 @@ async def get_artifact( ), ) + async def list_environments( + self, + *, + sort_by: Literal["name", "last_updated"] | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> AgentListEnvironmentsResponse: + """Retrieve cloud environments accessible to the authenticated principal. + + Returns + environments the caller owns, has been granted guest access to, or has accessed + via link sharing. + + Args: + sort_by: Sort order for the returned environments. + + - `name`: alphabetical by environment name + - `last_updated`: most recently updated first (default) + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return await self._get( + "/agent/environments", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=await async_maybe_transform( + {"sort_by": sort_by}, agent_list_environments_params.AgentListEnvironmentsParams + ), + ), + cast_to=AgentListEnvironmentsResponse, + ) + async def run( self, *, @@ -519,6 +610,9 @@ def __init__(self, agent: AgentResource) -> None: self.get_artifact = to_raw_response_wrapper( agent.get_artifact, ) + self.list_environments = to_raw_response_wrapper( + agent.list_environments, + ) self.run = to_raw_response_wrapper( agent.run, ) @@ -549,6 +643,9 @@ def __init__(self, agent: AsyncAgentResource) -> None: self.get_artifact = async_to_raw_response_wrapper( agent.get_artifact, ) + self.list_environments = async_to_raw_response_wrapper( + agent.list_environments, + ) self.run = async_to_raw_response_wrapper( agent.run, ) @@ -579,6 +676,9 @@ def __init__(self, agent: AgentResource) -> None: self.get_artifact = to_streamed_response_wrapper( agent.get_artifact, ) + self.list_environments = to_streamed_response_wrapper( + agent.list_environments, + ) self.run = to_streamed_response_wrapper( agent.run, ) @@ -609,6 +709,9 @@ def __init__(self, agent: AsyncAgentResource) -> None: self.get_artifact = async_to_streamed_response_wrapper( agent.get_artifact, ) + self.list_environments = async_to_streamed_response_wrapper( + agent.list_environments, + ) self.run = async_to_streamed_response_wrapper( agent.run, ) diff --git a/src/oz_agent_sdk/resources/agent/runs.py b/src/oz_agent_sdk/resources/agent/runs.py index e6e55b5..00c3f49 100644 --- a/src/oz_agent_sdk/resources/agent/runs.py +++ b/src/oz_agent_sdk/resources/agent/runs.py @@ -87,6 +87,7 @@ def retrieve( def list( self, *, + ancestor_run_id: str | Omit = omit, artifact_type: Literal["PLAN", "PULL_REQUEST", "SCREENSHOT", "FILE"] | Omit = omit, created_after: Union[str, datetime] | Omit = omit, created_before: Union[str, datetime] | Omit = omit, @@ -119,6 +120,9 @@ def list( to `sort_by=updated_at` and `sort_order=desc`. Args: + ancestor_run_id: Filter runs by ancestor run ID. The referenced run must exist and be accessible + to the caller. + artifact_type: Filter runs by artifact type created_after: Filter runs created after this timestamp (RFC3339 format) @@ -182,6 +186,7 @@ def list( timeout=timeout, query=maybe_transform( { + "ancestor_run_id": ancestor_run_id, "artifact_type": artifact_type, "created_after": created_after, "created_before": created_before, @@ -307,6 +312,7 @@ async def retrieve( def list( self, *, + ancestor_run_id: str | Omit = omit, artifact_type: Literal["PLAN", "PULL_REQUEST", "SCREENSHOT", "FILE"] | Omit = omit, created_after: Union[str, datetime] | Omit = omit, created_before: Union[str, datetime] | Omit = omit, @@ -339,6 +345,9 @@ def list( to `sort_by=updated_at` and `sort_order=desc`. Args: + ancestor_run_id: Filter runs by ancestor run ID. The referenced run must exist and be accessible + to the caller. + artifact_type: Filter runs by artifact type created_after: Filter runs created after this timestamp (RFC3339 format) @@ -402,6 +411,7 @@ def list( timeout=timeout, query=maybe_transform( { + "ancestor_run_id": ancestor_run_id, "artifact_type": artifact_type, "created_after": created_after, "created_before": created_before, diff --git a/src/oz_agent_sdk/types/__init__.py b/src/oz_agent_sdk/types/__init__.py index 4c520a7..e27ca02 100644 --- a/src/oz_agent_sdk/types/__init__.py +++ b/src/oz_agent_sdk/types/__init__.py @@ -8,6 +8,7 @@ from .user_profile import UserProfile as UserProfile from .agent_run_params import AgentRunParams as AgentRunParams from .agent_list_params import AgentListParams as AgentListParams +from .cloud_environment import CloudEnvironment as CloudEnvironment from .mcp_server_config import McpServerConfig as McpServerConfig from .agent_run_response import AgentRunResponse as AgentRunResponse from .agent_list_response import AgentListResponse as AgentListResponse @@ -18,3 +19,5 @@ from .cloud_environment_config import CloudEnvironmentConfig as CloudEnvironmentConfig from .ambient_agent_config_param import AmbientAgentConfigParam as AmbientAgentConfigParam from .agent_get_artifact_response import AgentGetArtifactResponse as AgentGetArtifactResponse +from .agent_list_environments_params import AgentListEnvironmentsParams as AgentListEnvironmentsParams +from .agent_list_environments_response import AgentListEnvironmentsResponse as AgentListEnvironmentsResponse diff --git a/src/oz_agent_sdk/types/agent/artifact_item.py b/src/oz_agent_sdk/types/agent/artifact_item.py index 299379b..437b857 100644 --- a/src/oz_agent_sdk/types/agent/artifact_item.py +++ b/src/oz_agent_sdk/types/agent/artifact_item.py @@ -24,12 +24,21 @@ class PlanArtifactData(BaseModel): document_uid: str """Unique identifier for the plan document""" + artifact_uid: Optional[str] = None + """ + Unique identifier for the plan artifact, usable with the artifact retrieval + endpoint + """ + notebook_uid: Optional[str] = None """Unique identifier for the associated notebook""" title: Optional[str] = None """Title of the plan""" + url: Optional[str] = None + """URL to open the plan in Warp Drive""" + class PlanArtifact(BaseModel): artifact_type: Literal["PLAN"] diff --git a/src/oz_agent_sdk/types/agent/run_list_params.py b/src/oz_agent_sdk/types/agent/run_list_params.py index 0b4e389..b53a299 100644 --- a/src/oz_agent_sdk/types/agent/run_list_params.py +++ b/src/oz_agent_sdk/types/agent/run_list_params.py @@ -14,6 +14,12 @@ class RunListParams(TypedDict, total=False): + ancestor_run_id: str + """Filter runs by ancestor run ID. + + The referenced run must exist and be accessible to the caller. + """ + artifact_type: Literal["PLAN", "PULL_REQUEST", "SCREENSHOT", "FILE"] """Filter runs by artifact type""" diff --git a/src/oz_agent_sdk/types/agent_get_artifact_response.py b/src/oz_agent_sdk/types/agent_get_artifact_response.py index 30405bc..7e835c8 100644 --- a/src/oz_agent_sdk/types/agent_get_artifact_response.py +++ b/src/oz_agent_sdk/types/agent_get_artifact_response.py @@ -9,6 +9,8 @@ __all__ = [ "AgentGetArtifactResponse", + "PlanArtifactResponse", + "PlanArtifactResponseData", "ScreenshotArtifactResponse", "ScreenshotArtifactResponseData", "FileArtifactResponse", @@ -16,6 +18,44 @@ ] +class PlanArtifactResponseData(BaseModel): + """Response data for a plan artifact, including current markdown content.""" + + content: str + """Current markdown content of the plan""" + + content_type: str + """MIME type of the returned plan content""" + + document_uid: str + """Unique identifier for the plan document""" + + notebook_uid: str + """Unique identifier for the associated notebook""" + + title: Optional[str] = None + """Current title of the plan""" + + url: Optional[str] = None + """URL to open the plan in Warp Drive""" + + +class PlanArtifactResponse(BaseModel): + """Response for retrieving a plan artifact.""" + + artifact_type: Literal["PLAN"] + """Type of the artifact""" + + artifact_uid: str + """Unique identifier (UUID) for the artifact""" + + created_at: datetime + """Timestamp when the artifact was created (RFC3339)""" + + data: PlanArtifactResponseData + """Response data for a plan artifact, including current markdown content.""" + + class ScreenshotArtifactResponseData(BaseModel): """Response data for a screenshot artifact, including a signed download URL.""" @@ -90,5 +130,6 @@ class FileArtifactResponse(BaseModel): AgentGetArtifactResponse: TypeAlias = Annotated[ - Union[ScreenshotArtifactResponse, FileArtifactResponse], PropertyInfo(discriminator="artifact_type") + Union[PlanArtifactResponse, ScreenshotArtifactResponse, FileArtifactResponse], + PropertyInfo(discriminator="artifact_type"), ] diff --git a/src/oz_agent_sdk/types/agent_list_environments_params.py b/src/oz_agent_sdk/types/agent_list_environments_params.py new file mode 100644 index 0000000..481c31d --- /dev/null +++ b/src/oz_agent_sdk/types/agent_list_environments_params.py @@ -0,0 +1,16 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Literal, TypedDict + +__all__ = ["AgentListEnvironmentsParams"] + + +class AgentListEnvironmentsParams(TypedDict, total=False): + sort_by: Literal["name", "last_updated"] + """Sort order for the returned environments. + + - `name`: alphabetical by environment name + - `last_updated`: most recently updated first (default) + """ diff --git a/src/oz_agent_sdk/types/agent_list_environments_response.py b/src/oz_agent_sdk/types/agent_list_environments_response.py new file mode 100644 index 0000000..103845a --- /dev/null +++ b/src/oz_agent_sdk/types/agent_list_environments_response.py @@ -0,0 +1,13 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List + +from .._models import BaseModel +from .cloud_environment import CloudEnvironment + +__all__ = ["AgentListEnvironmentsResponse"] + + +class AgentListEnvironmentsResponse(BaseModel): + environments: List[CloudEnvironment] + """List of accessible cloud environments""" diff --git a/src/oz_agent_sdk/types/ambient_agent_config.py b/src/oz_agent_sdk/types/ambient_agent_config.py index abd16c1..69eaf3a 100644 --- a/src/oz_agent_sdk/types/ambient_agent_config.py +++ b/src/oz_agent_sdk/types/ambient_agent_config.py @@ -8,7 +8,7 @@ from .._models import BaseModel from .mcp_server_config import McpServerConfig -__all__ = ["AmbientAgentConfig", "Harness"] +__all__ = ["AmbientAgentConfig", "Harness", "HarnessAuthSecrets"] class Harness(BaseModel): @@ -17,15 +17,6 @@ class Harness(BaseModel): Default (nil/empty) uses Warp's built-in harness. """ - auth_secret_name: Optional[str] = None - """Name of a managed secret to use as the authentication credential for the - harness. - - The secret must exist within the caller's personal or team scope. The - environment variable injected into the agent is determined by the secret type - (e.g. ANTHROPIC_API_KEY for anthropic_api_key secrets). - """ - type: Optional[Literal["oz", "claude"]] = None """The harness type identifier. @@ -34,6 +25,20 @@ class Harness(BaseModel): """ +class HarnessAuthSecrets(BaseModel): + """ + Authentication secrets for third-party harnesses. + Only the secret for the harness specified gets injected into the environment. + """ + + claude_auth_secret_name: Optional[str] = None + """ + Name of a managed secret for Claude Code harness authentication. The secret must + exist within the caller's personal or team scope. Only applicable when harness + type is "claude". + """ + + class AmbientAgentConfig(BaseModel): """Configuration for a cloud agent run""" @@ -55,6 +60,12 @@ class AmbientAgentConfig(BaseModel): uses Warp's built-in harness. """ + harness_auth_secrets: Optional[HarnessAuthSecrets] = None + """ + Authentication secrets for third-party harnesses. Only the secret for the + harness specified gets injected into the environment. + """ + idle_timeout_minutes: Optional[int] = None """ Number of minutes to keep the agent environment alive after task completion. If diff --git a/src/oz_agent_sdk/types/ambient_agent_config_param.py b/src/oz_agent_sdk/types/ambient_agent_config_param.py index 24da607..8ea7901 100644 --- a/src/oz_agent_sdk/types/ambient_agent_config_param.py +++ b/src/oz_agent_sdk/types/ambient_agent_config_param.py @@ -7,7 +7,7 @@ from .mcp_server_config_param import McpServerConfigParam -__all__ = ["AmbientAgentConfigParam", "Harness"] +__all__ = ["AmbientAgentConfigParam", "Harness", "HarnessAuthSecrets"] class Harness(TypedDict, total=False): @@ -16,15 +16,6 @@ class Harness(TypedDict, total=False): Default (nil/empty) uses Warp's built-in harness. """ - auth_secret_name: str - """Name of a managed secret to use as the authentication credential for the - harness. - - The secret must exist within the caller's personal or team scope. The - environment variable injected into the agent is determined by the secret type - (e.g. ANTHROPIC_API_KEY for anthropic_api_key secrets). - """ - type: Literal["oz", "claude"] """The harness type identifier. @@ -33,6 +24,20 @@ class Harness(TypedDict, total=False): """ +class HarnessAuthSecrets(TypedDict, total=False): + """ + Authentication secrets for third-party harnesses. + Only the secret for the harness specified gets injected into the environment. + """ + + claude_auth_secret_name: str + """ + Name of a managed secret for Claude Code harness authentication. The secret must + exist within the caller's personal or team scope. Only applicable when harness + type is "claude". + """ + + class AmbientAgentConfigParam(TypedDict, total=False): """Configuration for a cloud agent run""" @@ -54,6 +59,12 @@ class AmbientAgentConfigParam(TypedDict, total=False): uses Warp's built-in harness. """ + harness_auth_secrets: HarnessAuthSecrets + """ + Authentication secrets for third-party harnesses. Only the secret for the + harness specified gets injected into the environment. + """ + idle_timeout_minutes: int """ Number of minutes to keep the agent environment alive after task completion. If diff --git a/src/oz_agent_sdk/types/cloud_environment.py b/src/oz_agent_sdk/types/cloud_environment.py new file mode 100644 index 0000000..4bde98c --- /dev/null +++ b/src/oz_agent_sdk/types/cloud_environment.py @@ -0,0 +1,74 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional +from datetime import datetime + +from .scope import Scope +from .._models import BaseModel +from .user_profile import UserProfile +from .agent.run_state import RunState +from .cloud_environment_config import CloudEnvironmentConfig + +__all__ = ["CloudEnvironment", "LastTaskCreated"] + + +class LastTaskCreated(BaseModel): + """Summary of the most recently created task for an environment""" + + id: str + """Unique identifier of the task""" + + created_at: datetime + """When the task was created (RFC3339)""" + + state: RunState + """Current state of the run: + + - QUEUED: Run is waiting to be picked up + - PENDING: Run is being prepared + - CLAIMED: Run has been claimed by a worker + - INPROGRESS: Run is actively being executed + - SUCCEEDED: Run completed successfully + - FAILED: Run failed + - BLOCKED: Run is blocked (e.g., awaiting user input or approval) + - ERROR: Run encountered an error + - CANCELLED: Run was cancelled by user + """ + + title: str + """Title of the task""" + + updated_at: datetime + """When the task was last updated (RFC3339)""" + + started_at: Optional[datetime] = None + """When the task started running (RFC3339), null if not yet started""" + + +class CloudEnvironment(BaseModel): + """A cloud environment for running agents""" + + config: CloudEnvironmentConfig + """Configuration for a cloud environment used by scheduled agents""" + + last_updated: datetime + """Timestamp when the environment was last updated (RFC3339)""" + + setup_failed: bool + """True when the most recent task failed during setup before it started running""" + + uid: str + """Unique identifier for the environment""" + + creator: Optional[UserProfile] = None + + last_editor: Optional[UserProfile] = None + + last_task_created: Optional[LastTaskCreated] = None + """Summary of the most recently created task for an environment""" + + last_task_run_timestamp: Optional[datetime] = None + """Timestamp of the most recent task run in this environment (RFC3339)""" + + scope: Optional[Scope] = None + """Ownership scope for a resource (team or personal)""" diff --git a/tests/api_resources/agent/test_runs.py b/tests/api_resources/agent/test_runs.py index bf257f8..cf95a65 100644 --- a/tests/api_resources/agent/test_runs.py +++ b/tests/api_resources/agent/test_runs.py @@ -71,6 +71,7 @@ def test_method_list(self, client: OzAPI) -> None: @parametrize def test_method_list_with_all_params(self, client: OzAPI) -> None: run = client.agent.runs.list( + ancestor_run_id="ancestor_run_id", artifact_type="PLAN", created_after=parse_datetime("2019-12-27T18:11:19.117Z"), created_before=parse_datetime("2019-12-27T18:11:19.117Z"), @@ -215,6 +216,7 @@ async def test_method_list(self, async_client: AsyncOzAPI) -> None: @parametrize async def test_method_list_with_all_params(self, async_client: AsyncOzAPI) -> None: run = await async_client.agent.runs.list( + ancestor_run_id="ancestor_run_id", artifact_type="PLAN", created_after=parse_datetime("2019-12-27T18:11:19.117Z"), created_before=parse_datetime("2019-12-27T18:11:19.117Z"), diff --git a/tests/api_resources/agent/test_schedules.py b/tests/api_resources/agent/test_schedules.py index 9b22b45..51fbae1 100644 --- a/tests/api_resources/agent/test_schedules.py +++ b/tests/api_resources/agent/test_schedules.py @@ -40,10 +40,8 @@ def test_method_create_with_all_params(self, client: OzAPI) -> None: "base_prompt": "base_prompt", "computer_use_enabled": True, "environment_id": "environment_id", - "harness": { - "auth_secret_name": "auth_secret_name", - "type": "oz", - }, + "harness": {"type": "oz"}, + "harness_auth_secrets": {"claude_auth_secret_name": "claude_auth_secret_name"}, "idle_timeout_minutes": 1, "mcp_servers": { "foo": { @@ -159,10 +157,8 @@ def test_method_update_with_all_params(self, client: OzAPI) -> None: "base_prompt": "base_prompt", "computer_use_enabled": True, "environment_id": "environment_id", - "harness": { - "auth_secret_name": "auth_secret_name", - "type": "oz", - }, + "harness": {"type": "oz"}, + "harness_auth_secrets": {"claude_auth_secret_name": "claude_auth_secret_name"}, "idle_timeout_minutes": 1, "mcp_servers": { "foo": { @@ -405,10 +401,8 @@ async def test_method_create_with_all_params(self, async_client: AsyncOzAPI) -> "base_prompt": "base_prompt", "computer_use_enabled": True, "environment_id": "environment_id", - "harness": { - "auth_secret_name": "auth_secret_name", - "type": "oz", - }, + "harness": {"type": "oz"}, + "harness_auth_secrets": {"claude_auth_secret_name": "claude_auth_secret_name"}, "idle_timeout_minutes": 1, "mcp_servers": { "foo": { @@ -524,10 +518,8 @@ async def test_method_update_with_all_params(self, async_client: AsyncOzAPI) -> "base_prompt": "base_prompt", "computer_use_enabled": True, "environment_id": "environment_id", - "harness": { - "auth_secret_name": "auth_secret_name", - "type": "oz", - }, + "harness": {"type": "oz"}, + "harness_auth_secrets": {"claude_auth_secret_name": "claude_auth_secret_name"}, "idle_timeout_minutes": 1, "mcp_servers": { "foo": { diff --git a/tests/api_resources/test_agent.py b/tests/api_resources/test_agent.py index 70c07fb..7f628ef 100644 --- a/tests/api_resources/test_agent.py +++ b/tests/api_resources/test_agent.py @@ -13,6 +13,7 @@ AgentRunResponse, AgentListResponse, AgentGetArtifactResponse, + AgentListEnvironmentsResponse, ) base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") @@ -102,6 +103,42 @@ def test_path_params_get_artifact(self, client: OzAPI) -> None: "", ) + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_list_environments(self, client: OzAPI) -> None: + agent = client.agent.list_environments() + assert_matches_type(AgentListEnvironmentsResponse, agent, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_list_environments_with_all_params(self, client: OzAPI) -> None: + agent = client.agent.list_environments( + sort_by="name", + ) + assert_matches_type(AgentListEnvironmentsResponse, agent, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_list_environments(self, client: OzAPI) -> None: + response = client.agent.with_raw_response.list_environments() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + agent = response.parse() + assert_matches_type(AgentListEnvironmentsResponse, agent, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_list_environments(self, client: OzAPI) -> None: + with client.agent.with_streaming_response.list_environments() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + agent = response.parse() + assert_matches_type(AgentListEnvironmentsResponse, agent, path=["response"]) + + assert cast(Any, response.is_closed) is True + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_method_run(self, client: OzAPI) -> None: @@ -124,10 +161,8 @@ def test_method_run_with_all_params(self, client: OzAPI) -> None: "base_prompt": "base_prompt", "computer_use_enabled": True, "environment_id": "environment_id", - "harness": { - "auth_secret_name": "auth_secret_name", - "type": "oz", - }, + "harness": {"type": "oz"}, + "harness_auth_secrets": {"claude_auth_secret_name": "claude_auth_secret_name"}, "idle_timeout_minutes": 1, "mcp_servers": { "foo": { @@ -263,6 +298,42 @@ async def test_path_params_get_artifact(self, async_client: AsyncOzAPI) -> None: "", ) + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_list_environments(self, async_client: AsyncOzAPI) -> None: + agent = await async_client.agent.list_environments() + assert_matches_type(AgentListEnvironmentsResponse, agent, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_list_environments_with_all_params(self, async_client: AsyncOzAPI) -> None: + agent = await async_client.agent.list_environments( + sort_by="name", + ) + assert_matches_type(AgentListEnvironmentsResponse, agent, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_list_environments(self, async_client: AsyncOzAPI) -> None: + response = await async_client.agent.with_raw_response.list_environments() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + agent = await response.parse() + assert_matches_type(AgentListEnvironmentsResponse, agent, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_list_environments(self, async_client: AsyncOzAPI) -> None: + async with async_client.agent.with_streaming_response.list_environments() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + agent = await response.parse() + assert_matches_type(AgentListEnvironmentsResponse, agent, path=["response"]) + + assert cast(Any, response.is_closed) is True + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_method_run(self, async_client: AsyncOzAPI) -> None: @@ -285,10 +356,8 @@ async def test_method_run_with_all_params(self, async_client: AsyncOzAPI) -> Non "base_prompt": "base_prompt", "computer_use_enabled": True, "environment_id": "environment_id", - "harness": { - "auth_secret_name": "auth_secret_name", - "type": "oz", - }, + "harness": {"type": "oz"}, + "harness_auth_secrets": {"claude_auth_secret_name": "claude_auth_secret_name"}, "idle_timeout_minutes": 1, "mcp_servers": { "foo": { From 2b7afabf4a54764ab162ac32f4dbe7fe4274ba72 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 13 Apr 2026 22:09:16 +0000 Subject: [PATCH 09/56] feat: Add system prompt to resolve-prompt for harnesses. --- .stats.yml | 4 +- src/oz_agent_sdk/resources/agent/agent.py | 10 ++--- src/oz_agent_sdk/types/agent/artifact_item.py | 9 ---- .../types/agent_get_artifact_response.py | 43 +------------------ 4 files changed, 7 insertions(+), 59 deletions(-) diff --git a/.stats.yml b/.stats.yml index 0b3ef0b..afc1d8d 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 15 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta%2Fwarp-api-abde9a81e648a7bbddbb7c7af07eb9202e584f78dea9cc79ff075da2ad66efd5.yml -openapi_spec_hash: db45809e85b0f85020a6b046c6eed90e +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta%2Fwarp-api-b9b7c97364a43696e42e7fe9071aa42e4e059d61bf5f0bd1f26826a90f9053b3.yml +openapi_spec_hash: 4b25aa8fac3a7adaa44c1cf833307b69 config_hash: 253e4b5ca01236d448980a78491c17c5 diff --git a/src/oz_agent_sdk/resources/agent/agent.py b/src/oz_agent_sdk/resources/agent/agent.py index d8d58ef..b28ef9a 100644 --- a/src/oz_agent_sdk/resources/agent/agent.py +++ b/src/oz_agent_sdk/resources/agent/agent.py @@ -164,9 +164,8 @@ def get_artifact( ) -> AgentGetArtifactResponse: """Retrieve an artifact by its UUID. - For downloadable file-like artifacts, returns - a time-limited signed download URL. For plan artifacts, returns the current plan - content inline. + For supported downloadable artifacts, returns + a time-limited signed download URL. Args: extra_headers: Send extra headers @@ -437,9 +436,8 @@ async def get_artifact( ) -> AgentGetArtifactResponse: """Retrieve an artifact by its UUID. - For downloadable file-like artifacts, returns - a time-limited signed download URL. For plan artifacts, returns the current plan - content inline. + For supported downloadable artifacts, returns + a time-limited signed download URL. Args: extra_headers: Send extra headers diff --git a/src/oz_agent_sdk/types/agent/artifact_item.py b/src/oz_agent_sdk/types/agent/artifact_item.py index 437b857..299379b 100644 --- a/src/oz_agent_sdk/types/agent/artifact_item.py +++ b/src/oz_agent_sdk/types/agent/artifact_item.py @@ -24,21 +24,12 @@ class PlanArtifactData(BaseModel): document_uid: str """Unique identifier for the plan document""" - artifact_uid: Optional[str] = None - """ - Unique identifier for the plan artifact, usable with the artifact retrieval - endpoint - """ - notebook_uid: Optional[str] = None """Unique identifier for the associated notebook""" title: Optional[str] = None """Title of the plan""" - url: Optional[str] = None - """URL to open the plan in Warp Drive""" - class PlanArtifact(BaseModel): artifact_type: Literal["PLAN"] diff --git a/src/oz_agent_sdk/types/agent_get_artifact_response.py b/src/oz_agent_sdk/types/agent_get_artifact_response.py index 7e835c8..30405bc 100644 --- a/src/oz_agent_sdk/types/agent_get_artifact_response.py +++ b/src/oz_agent_sdk/types/agent_get_artifact_response.py @@ -9,8 +9,6 @@ __all__ = [ "AgentGetArtifactResponse", - "PlanArtifactResponse", - "PlanArtifactResponseData", "ScreenshotArtifactResponse", "ScreenshotArtifactResponseData", "FileArtifactResponse", @@ -18,44 +16,6 @@ ] -class PlanArtifactResponseData(BaseModel): - """Response data for a plan artifact, including current markdown content.""" - - content: str - """Current markdown content of the plan""" - - content_type: str - """MIME type of the returned plan content""" - - document_uid: str - """Unique identifier for the plan document""" - - notebook_uid: str - """Unique identifier for the associated notebook""" - - title: Optional[str] = None - """Current title of the plan""" - - url: Optional[str] = None - """URL to open the plan in Warp Drive""" - - -class PlanArtifactResponse(BaseModel): - """Response for retrieving a plan artifact.""" - - artifact_type: Literal["PLAN"] - """Type of the artifact""" - - artifact_uid: str - """Unique identifier (UUID) for the artifact""" - - created_at: datetime - """Timestamp when the artifact was created (RFC3339)""" - - data: PlanArtifactResponseData - """Response data for a plan artifact, including current markdown content.""" - - class ScreenshotArtifactResponseData(BaseModel): """Response data for a screenshot artifact, including a signed download URL.""" @@ -130,6 +90,5 @@ class FileArtifactResponse(BaseModel): AgentGetArtifactResponse: TypeAlias = Annotated[ - Union[PlanArtifactResponse, ScreenshotArtifactResponse, FileArtifactResponse], - PropertyInfo(discriminator="artifact_type"), + Union[ScreenshotArtifactResponse, FileArtifactResponse], PropertyInfo(discriminator="artifact_type") ] From 9662dbe10cc5392271b3e56c35cb8ef95ec80eed Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 14 Apr 2026 01:08:17 +0000 Subject: [PATCH 10/56] feat: Add trigger URL to task source. --- .stats.yml | 4 ++-- src/oz_agent_sdk/types/agent/run_item.py | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index afc1d8d..aa98229 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 15 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta%2Fwarp-api-b9b7c97364a43696e42e7fe9071aa42e4e059d61bf5f0bd1f26826a90f9053b3.yml -openapi_spec_hash: 4b25aa8fac3a7adaa44c1cf833307b69 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta%2Fwarp-api-ae49b84ec5627699ad71bfbbf01d6ce76587b7cfbbfa10f124b397d0c59b0b82.yml +openapi_spec_hash: b965b21aa3f92e8b9111e50c1b9a8bf0 config_hash: 253e4b5ca01236d448980a78491c17c5 diff --git a/src/oz_agent_sdk/types/agent/run_item.py b/src/oz_agent_sdk/types/agent/run_item.py index d246450..61dd012 100644 --- a/src/oz_agent_sdk/types/agent/run_item.py +++ b/src/oz_agent_sdk/types/agent/run_item.py @@ -215,3 +215,6 @@ class RunItem(BaseModel): For terminal error states, includes structured error code and retryability info from the platform error catalog. """ + + trigger_url: Optional[str] = None + """URL to the run trigger (e.g. Slack thread, Linear issue, schedule)""" From ebd2c5520128722d88285aea9dd0caf3242d9a31 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 14 Apr 2026 14:43:22 +0000 Subject: [PATCH 11/56] feat(api): api update --- .stats.yml | 4 +- src/oz_agent_sdk/resources/agent/agent.py | 10 +++-- src/oz_agent_sdk/types/agent/artifact_item.py | 9 ++++ .../types/agent_get_artifact_response.py | 43 ++++++++++++++++++- 4 files changed, 59 insertions(+), 7 deletions(-) diff --git a/.stats.yml b/.stats.yml index aa98229..6fad0eb 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 15 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta%2Fwarp-api-ae49b84ec5627699ad71bfbbf01d6ce76587b7cfbbfa10f124b397d0c59b0b82.yml -openapi_spec_hash: b965b21aa3f92e8b9111e50c1b9a8bf0 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta%2Fwarp-api-8e7a3c9ef00ac517caaa193265398850b6925ab898aaf84e83e28c9f023c0ba8.yml +openapi_spec_hash: ebf53d80dd9066d5ac9401f1493544e3 config_hash: 253e4b5ca01236d448980a78491c17c5 diff --git a/src/oz_agent_sdk/resources/agent/agent.py b/src/oz_agent_sdk/resources/agent/agent.py index b28ef9a..d8d58ef 100644 --- a/src/oz_agent_sdk/resources/agent/agent.py +++ b/src/oz_agent_sdk/resources/agent/agent.py @@ -164,8 +164,9 @@ def get_artifact( ) -> AgentGetArtifactResponse: """Retrieve an artifact by its UUID. - For supported downloadable artifacts, returns - a time-limited signed download URL. + For downloadable file-like artifacts, returns + a time-limited signed download URL. For plan artifacts, returns the current plan + content inline. Args: extra_headers: Send extra headers @@ -436,8 +437,9 @@ async def get_artifact( ) -> AgentGetArtifactResponse: """Retrieve an artifact by its UUID. - For supported downloadable artifacts, returns - a time-limited signed download URL. + For downloadable file-like artifacts, returns + a time-limited signed download URL. For plan artifacts, returns the current plan + content inline. Args: extra_headers: Send extra headers diff --git a/src/oz_agent_sdk/types/agent/artifact_item.py b/src/oz_agent_sdk/types/agent/artifact_item.py index 299379b..437b857 100644 --- a/src/oz_agent_sdk/types/agent/artifact_item.py +++ b/src/oz_agent_sdk/types/agent/artifact_item.py @@ -24,12 +24,21 @@ class PlanArtifactData(BaseModel): document_uid: str """Unique identifier for the plan document""" + artifact_uid: Optional[str] = None + """ + Unique identifier for the plan artifact, usable with the artifact retrieval + endpoint + """ + notebook_uid: Optional[str] = None """Unique identifier for the associated notebook""" title: Optional[str] = None """Title of the plan""" + url: Optional[str] = None + """URL to open the plan in Warp Drive""" + class PlanArtifact(BaseModel): artifact_type: Literal["PLAN"] diff --git a/src/oz_agent_sdk/types/agent_get_artifact_response.py b/src/oz_agent_sdk/types/agent_get_artifact_response.py index 30405bc..7e835c8 100644 --- a/src/oz_agent_sdk/types/agent_get_artifact_response.py +++ b/src/oz_agent_sdk/types/agent_get_artifact_response.py @@ -9,6 +9,8 @@ __all__ = [ "AgentGetArtifactResponse", + "PlanArtifactResponse", + "PlanArtifactResponseData", "ScreenshotArtifactResponse", "ScreenshotArtifactResponseData", "FileArtifactResponse", @@ -16,6 +18,44 @@ ] +class PlanArtifactResponseData(BaseModel): + """Response data for a plan artifact, including current markdown content.""" + + content: str + """Current markdown content of the plan""" + + content_type: str + """MIME type of the returned plan content""" + + document_uid: str + """Unique identifier for the plan document""" + + notebook_uid: str + """Unique identifier for the associated notebook""" + + title: Optional[str] = None + """Current title of the plan""" + + url: Optional[str] = None + """URL to open the plan in Warp Drive""" + + +class PlanArtifactResponse(BaseModel): + """Response for retrieving a plan artifact.""" + + artifact_type: Literal["PLAN"] + """Type of the artifact""" + + artifact_uid: str + """Unique identifier (UUID) for the artifact""" + + created_at: datetime + """Timestamp when the artifact was created (RFC3339)""" + + data: PlanArtifactResponseData + """Response data for a plan artifact, including current markdown content.""" + + class ScreenshotArtifactResponseData(BaseModel): """Response data for a screenshot artifact, including a signed download URL.""" @@ -90,5 +130,6 @@ class FileArtifactResponse(BaseModel): AgentGetArtifactResponse: TypeAlias = Annotated[ - Union[ScreenshotArtifactResponse, FileArtifactResponse], PropertyInfo(discriminator="artifact_type") + Union[PlanArtifactResponse, ScreenshotArtifactResponse, FileArtifactResponse], + PropertyInfo(discriminator="artifact_type"), ] From ec0982ce786b2380ab89aa7298b28998c6eade46 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 15 Apr 2026 18:04:10 +0000 Subject: [PATCH 12/56] feat: Add worker_host to AgentListSource in OpenAPI spec --- .stats.yml | 4 ++-- src/oz_agent_sdk/types/agent_skill.py | 7 +++++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 6fad0eb..6163321 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 15 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta%2Fwarp-api-8e7a3c9ef00ac517caaa193265398850b6925ab898aaf84e83e28c9f023c0ba8.yml -openapi_spec_hash: ebf53d80dd9066d5ac9401f1493544e3 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta%2Fwarp-api-252ab435934e85d5f76957188c64906abf76a0351c5861383327cb1297a2ac8a.yml +openapi_spec_hash: ed801bb30428c1c66cb0af97e3f6ee9c config_hash: 253e4b5ca01236d448980a78491c17c5 diff --git a/src/oz_agent_sdk/types/agent_skill.py b/src/oz_agent_sdk/types/agent_skill.py index 9b3386f..b7b9ef4 100644 --- a/src/oz_agent_sdk/types/agent_skill.py +++ b/src/oz_agent_sdk/types/agent_skill.py @@ -26,6 +26,13 @@ class VariantSource(BaseModel): skill_path: str """Path to the skill definition file within the repository""" + worker_host: Optional[str] = None + """ + Self-hosted worker host that reported this skill. Present only for skills + discovered from self-hosted workers (as opposed to skills from GitHub repos + linked to environments). + """ + class Variant(BaseModel): id: str From f2dd099128bf4f98e304778556d55e80a4fd219c Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 15 Apr 2026 18:19:22 +0000 Subject: [PATCH 13/56] chore: update SDK settings --- .github/workflows/publish-pypi.yml | 5 ++--- .github/workflows/release-doctor.yml | 2 ++ .stats.yml | 2 +- bin/check-release-environment | 4 ++++ bin/publish-pypi | 6 +----- 5 files changed, 10 insertions(+), 9 deletions(-) diff --git a/.github/workflows/publish-pypi.yml b/.github/workflows/publish-pypi.yml index 74160e1..b2e5250 100644 --- a/.github/workflows/publish-pypi.yml +++ b/.github/workflows/publish-pypi.yml @@ -12,9 +12,6 @@ jobs: publish: name: publish runs-on: ubuntu-latest - permissions: - contents: read - id-token: write steps: - uses: actions/checkout@v6 @@ -27,3 +24,5 @@ jobs: - name: Publish to PyPI run: | bash ./bin/publish-pypi + env: + PYPI_TOKEN: ${{ secrets.OZ_API_PYPI_TOKEN || secrets.PYPI_TOKEN }} diff --git a/.github/workflows/release-doctor.yml b/.github/workflows/release-doctor.yml index bb0047d..94bd299 100644 --- a/.github/workflows/release-doctor.yml +++ b/.github/workflows/release-doctor.yml @@ -17,3 +17,5 @@ jobs: - name: Check release environment run: | bash ./bin/check-release-environment + env: + PYPI_TOKEN: ${{ secrets.OZ_API_PYPI_TOKEN || secrets.PYPI_TOKEN }} diff --git a/.stats.yml b/.stats.yml index 6163321..238dbfe 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 15 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta%2Fwarp-api-252ab435934e85d5f76957188c64906abf76a0351c5861383327cb1297a2ac8a.yml openapi_spec_hash: ed801bb30428c1c66cb0af97e3f6ee9c -config_hash: 253e4b5ca01236d448980a78491c17c5 +config_hash: b39effa64874ba589480760347b915be diff --git a/bin/check-release-environment b/bin/check-release-environment index 1e951e9..b845b0f 100644 --- a/bin/check-release-environment +++ b/bin/check-release-environment @@ -2,6 +2,10 @@ errors=() +if [ -z "${PYPI_TOKEN}" ]; then + errors+=("The PYPI_TOKEN secret has not been set. Please set it in either this repository's secrets or your organization secrets.") +fi + lenErrors=${#errors[@]} if [[ lenErrors -gt 0 ]]; then diff --git a/bin/publish-pypi b/bin/publish-pypi index 5895700..e72ca2f 100644 --- a/bin/publish-pypi +++ b/bin/publish-pypi @@ -4,8 +4,4 @@ set -eux rm -rf dist mkdir -p dist uv build -if [ -n "${PYPI_TOKEN:-}" ]; then - uv publish --token=$PYPI_TOKEN -else - uv publish -fi +uv publish --token=$PYPI_TOKEN From 66c852194f355cedca2b34b944c398e796f064ab Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 16 Apr 2026 13:56:22 +0000 Subject: [PATCH 14/56] feat(api): api update --- .github/workflows/publish-pypi.yml | 5 +++-- .github/workflows/release-doctor.yml | 2 -- .stats.yml | 6 +++--- bin/check-release-environment | 4 ---- bin/publish-pypi | 6 +++++- src/oz_agent_sdk/types/agent_skill.py | 7 ------- 6 files changed, 11 insertions(+), 19 deletions(-) diff --git a/.github/workflows/publish-pypi.yml b/.github/workflows/publish-pypi.yml index b2e5250..74160e1 100644 --- a/.github/workflows/publish-pypi.yml +++ b/.github/workflows/publish-pypi.yml @@ -12,6 +12,9 @@ jobs: publish: name: publish runs-on: ubuntu-latest + permissions: + contents: read + id-token: write steps: - uses: actions/checkout@v6 @@ -24,5 +27,3 @@ jobs: - name: Publish to PyPI run: | bash ./bin/publish-pypi - env: - PYPI_TOKEN: ${{ secrets.OZ_API_PYPI_TOKEN || secrets.PYPI_TOKEN }} diff --git a/.github/workflows/release-doctor.yml b/.github/workflows/release-doctor.yml index 94bd299..bb0047d 100644 --- a/.github/workflows/release-doctor.yml +++ b/.github/workflows/release-doctor.yml @@ -17,5 +17,3 @@ jobs: - name: Check release environment run: | bash ./bin/check-release-environment - env: - PYPI_TOKEN: ${{ secrets.OZ_API_PYPI_TOKEN || secrets.PYPI_TOKEN }} diff --git a/.stats.yml b/.stats.yml index 238dbfe..6fad0eb 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 15 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta%2Fwarp-api-252ab435934e85d5f76957188c64906abf76a0351c5861383327cb1297a2ac8a.yml -openapi_spec_hash: ed801bb30428c1c66cb0af97e3f6ee9c -config_hash: b39effa64874ba589480760347b915be +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta%2Fwarp-api-8e7a3c9ef00ac517caaa193265398850b6925ab898aaf84e83e28c9f023c0ba8.yml +openapi_spec_hash: ebf53d80dd9066d5ac9401f1493544e3 +config_hash: 253e4b5ca01236d448980a78491c17c5 diff --git a/bin/check-release-environment b/bin/check-release-environment index b845b0f..1e951e9 100644 --- a/bin/check-release-environment +++ b/bin/check-release-environment @@ -2,10 +2,6 @@ errors=() -if [ -z "${PYPI_TOKEN}" ]; then - errors+=("The PYPI_TOKEN secret has not been set. Please set it in either this repository's secrets or your organization secrets.") -fi - lenErrors=${#errors[@]} if [[ lenErrors -gt 0 ]]; then diff --git a/bin/publish-pypi b/bin/publish-pypi index e72ca2f..5895700 100644 --- a/bin/publish-pypi +++ b/bin/publish-pypi @@ -4,4 +4,8 @@ set -eux rm -rf dist mkdir -p dist uv build -uv publish --token=$PYPI_TOKEN +if [ -n "${PYPI_TOKEN:-}" ]; then + uv publish --token=$PYPI_TOKEN +else + uv publish +fi diff --git a/src/oz_agent_sdk/types/agent_skill.py b/src/oz_agent_sdk/types/agent_skill.py index b7b9ef4..9b3386f 100644 --- a/src/oz_agent_sdk/types/agent_skill.py +++ b/src/oz_agent_sdk/types/agent_skill.py @@ -26,13 +26,6 @@ class VariantSource(BaseModel): skill_path: str """Path to the skill definition file within the repository""" - worker_host: Optional[str] = None - """ - Self-hosted worker host that reported this skill. Present only for skills - discovered from self-hosted workers (as opposed to skills from GitHub repos - linked to environments). - """ - class Variant(BaseModel): id: str From 116f06e5c63e8d015e7dfea47fc22ede53ebb84e Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 16 Apr 2026 15:28:15 +0000 Subject: [PATCH 15/56] feat(api): api update --- .stats.yml | 4 ++-- src/oz_agent_sdk/types/agent_skill.py | 7 +++++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 6fad0eb..6163321 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 15 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta%2Fwarp-api-8e7a3c9ef00ac517caaa193265398850b6925ab898aaf84e83e28c9f023c0ba8.yml -openapi_spec_hash: ebf53d80dd9066d5ac9401f1493544e3 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta%2Fwarp-api-252ab435934e85d5f76957188c64906abf76a0351c5861383327cb1297a2ac8a.yml +openapi_spec_hash: ed801bb30428c1c66cb0af97e3f6ee9c config_hash: 253e4b5ca01236d448980a78491c17c5 diff --git a/src/oz_agent_sdk/types/agent_skill.py b/src/oz_agent_sdk/types/agent_skill.py index 9b3386f..b7b9ef4 100644 --- a/src/oz_agent_sdk/types/agent_skill.py +++ b/src/oz_agent_sdk/types/agent_skill.py @@ -26,6 +26,13 @@ class VariantSource(BaseModel): skill_path: str """Path to the skill definition file within the repository""" + worker_host: Optional[str] = None + """ + Self-hosted worker host that reported this skill. Present only for skills + discovered from self-hosted workers (as opposed to skills from GitHub repos + linked to environments). + """ + class Variant(BaseModel): id: str From 57d70b87bb24f3241d6b304ef4965553db6885fb Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 16 Apr 2026 20:21:05 +0000 Subject: [PATCH 16/56] codegen metadata --- .stats.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.stats.yml b/.stats.yml index 6163321..b124fdb 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 15 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta%2Fwarp-api-252ab435934e85d5f76957188c64906abf76a0351c5861383327cb1297a2ac8a.yml -openapi_spec_hash: ed801bb30428c1c66cb0af97e3f6ee9c -config_hash: 253e4b5ca01236d448980a78491c17c5 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta%2Fwarp-api-11fd464a4cf5b849a565d00039093093ef93acdb99679ae94b2908543a55097b.yml +openapi_spec_hash: 12840099351c5309d6cf8c4b92f028b3 +config_hash: 42666caf45e82675e80982d51e3b7727 From 8d537bcbe75b344427bd04e5406ab066769f580a Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 17 Apr 2026 15:42:06 +0000 Subject: [PATCH 17/56] feat: Update public API and graphql to support creating multiple service accounts and API keys --- .stats.yml | 8 +- api.md | 20 + src/oz_agent_sdk/resources/agent/agent.py | 31 ++ src/oz_agent_sdk/resources/agent/agent_.py | 402 ++++++++++++++++++ src/oz_agent_sdk/types/agent/__init__.py | 4 + .../types/agent/agent_create_params.py | 12 + .../types/agent/agent_response.py | 21 + .../types/agent/agent_update_params.py | 12 + .../agent/list_agent_identities_response.py | 12 + tests/api_resources/agent/test_agent_.py | 337 +++++++++++++++ 10 files changed, 855 insertions(+), 4 deletions(-) create mode 100644 src/oz_agent_sdk/resources/agent/agent_.py create mode 100644 src/oz_agent_sdk/types/agent/agent_create_params.py create mode 100644 src/oz_agent_sdk/types/agent/agent_response.py create mode 100644 src/oz_agent_sdk/types/agent/agent_update_params.py create mode 100644 src/oz_agent_sdk/types/agent/list_agent_identities_response.py create mode 100644 tests/api_resources/agent/test_agent_.py diff --git a/.stats.yml b/.stats.yml index b124fdb..2077b1f 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 15 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta%2Fwarp-api-11fd464a4cf5b849a565d00039093093ef93acdb99679ae94b2908543a55097b.yml -openapi_spec_hash: 12840099351c5309d6cf8c4b92f028b3 -config_hash: 42666caf45e82675e80982d51e3b7727 +configured_endpoints: 19 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta%2Fwarp-api-3226a0810ae5de980509e31910138990d93d2843918730249caed1436e677ec3.yml +openapi_spec_hash: 776a9087e0c342e9fcbd140e75936d75 +config_hash: c5fc921cc04f541a85f92299f365eba6 diff --git a/api.md b/api.md index 065cedb..918ca45 100644 --- a/api.md +++ b/api.md @@ -72,6 +72,26 @@ Methods: - client.agent.schedules.pause(schedule_id) -> ScheduledAgentItem - client.agent.schedules.resume(schedule_id) -> ScheduledAgentItem +## Agent + +Types: + +```python +from oz_agent_sdk.types.agent import ( + AgentResponse, + CreateAgentRequest, + ListAgentIdentitiesResponse, + UpdateAgentRequest, +) +``` + +Methods: + +- client.agent.agent.create(\*\*params) -> AgentResponse +- client.agent.agent.update(uid, \*\*params) -> AgentResponse +- client.agent.agent.list() -> ListAgentIdentitiesResponse +- client.agent.agent.delete(uid) -> None + ## Sessions Types: diff --git a/src/oz_agent_sdk/resources/agent/agent.py b/src/oz_agent_sdk/resources/agent/agent.py index d8d58ef..0b12e59 100644 --- a/src/oz_agent_sdk/resources/agent/agent.py +++ b/src/oz_agent_sdk/resources/agent/agent.py @@ -7,6 +7,7 @@ import httpx +from . import agent_ as agent from .runs import ( RunsResource, AsyncRunsResource, @@ -65,6 +66,11 @@ def schedules(self) -> SchedulesResource: """Operations for creating and managing scheduled agents""" return SchedulesResource(self._client) + @cached_property + def agent(self) -> agent.AgentResource: + """Operations for running and managing cloud agents""" + return agent.AgentResource(self._client) + @cached_property def sessions(self) -> SessionsResource: """Operations for running and managing cloud agents""" @@ -338,6 +344,11 @@ def schedules(self) -> AsyncSchedulesResource: """Operations for creating and managing scheduled agents""" return AsyncSchedulesResource(self._client) + @cached_property + def agent(self) -> agent.AsyncAgentResource: + """Operations for running and managing cloud agents""" + return agent.AsyncAgentResource(self._client) + @cached_property def sessions(self) -> AsyncSessionsResource: """Operations for running and managing cloud agents""" @@ -627,6 +638,11 @@ def schedules(self) -> SchedulesResourceWithRawResponse: """Operations for creating and managing scheduled agents""" return SchedulesResourceWithRawResponse(self._agent.schedules) + @cached_property + def agent(self) -> agent.AgentResourceWithRawResponse: + """Operations for running and managing cloud agents""" + return agent.AgentResourceWithRawResponse(self._agent.agent) + @cached_property def sessions(self) -> SessionsResourceWithRawResponse: """Operations for running and managing cloud agents""" @@ -660,6 +676,11 @@ def schedules(self) -> AsyncSchedulesResourceWithRawResponse: """Operations for creating and managing scheduled agents""" return AsyncSchedulesResourceWithRawResponse(self._agent.schedules) + @cached_property + def agent(self) -> agent.AsyncAgentResourceWithRawResponse: + """Operations for running and managing cloud agents""" + return agent.AsyncAgentResourceWithRawResponse(self._agent.agent) + @cached_property def sessions(self) -> AsyncSessionsResourceWithRawResponse: """Operations for running and managing cloud agents""" @@ -693,6 +714,11 @@ def schedules(self) -> SchedulesResourceWithStreamingResponse: """Operations for creating and managing scheduled agents""" return SchedulesResourceWithStreamingResponse(self._agent.schedules) + @cached_property + def agent(self) -> agent.AgentResourceWithStreamingResponse: + """Operations for running and managing cloud agents""" + return agent.AgentResourceWithStreamingResponse(self._agent.agent) + @cached_property def sessions(self) -> SessionsResourceWithStreamingResponse: """Operations for running and managing cloud agents""" @@ -726,6 +752,11 @@ def schedules(self) -> AsyncSchedulesResourceWithStreamingResponse: """Operations for creating and managing scheduled agents""" return AsyncSchedulesResourceWithStreamingResponse(self._agent.schedules) + @cached_property + def agent(self) -> agent.AsyncAgentResourceWithStreamingResponse: + """Operations for running and managing cloud agents""" + return agent.AsyncAgentResourceWithStreamingResponse(self._agent.agent) + @cached_property def sessions(self) -> AsyncSessionsResourceWithStreamingResponse: """Operations for running and managing cloud agents""" diff --git a/src/oz_agent_sdk/resources/agent/agent_.py b/src/oz_agent_sdk/resources/agent/agent_.py new file mode 100644 index 0000000..2c82516 --- /dev/null +++ b/src/oz_agent_sdk/resources/agent/agent_.py @@ -0,0 +1,402 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import httpx + +from ..._types import Body, Omit, Query, Headers, NoneType, NotGiven, omit, not_given +from ..._utils import path_template, maybe_transform, async_maybe_transform +from ..._compat import cached_property +from ..._resource import SyncAPIResource, AsyncAPIResource +from ..._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from ...types.agent import agent_create_params, agent_update_params +from ..._base_client import make_request_options +from ...types.agent.agent_response import AgentResponse +from ...types.agent.list_agent_identities_response import ListAgentIdentitiesResponse + +__all__ = ["AgentResource", "AsyncAgentResource"] + + +class AgentResource(SyncAPIResource): + """Operations for running and managing cloud agents""" + + @cached_property + def with_raw_response(self) -> AgentResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/warpdotdev/oz-sdk-python#accessing-raw-response-data-eg-headers + """ + return AgentResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AgentResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/warpdotdev/oz-sdk-python#with_streaming_response + """ + return AgentResourceWithStreamingResponse(self) + + def create( + self, + *, + name: str, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> AgentResponse: + """Create a new agent for the caller's team. + + Agents can be used as the execution + principal for team-owned runs. + + Args: + name: A name for the agent + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._post( + "/agent/identities", + body=maybe_transform({"name": name}, agent_create_params.AgentCreateParams), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=AgentResponse, + ) + + def update( + self, + uid: str, + *, + name: str | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> AgentResponse: + """ + Update an existing agent. + + Args: + name: The new name for the agent + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not uid: + raise ValueError(f"Expected a non-empty value for `uid` but received {uid!r}") + return self._put( + path_template("/agent/identities/{uid}", uid=uid), + body=maybe_transform({"name": name}, agent_update_params.AgentUpdateParams), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=AgentResponse, + ) + + def list( + self, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> ListAgentIdentitiesResponse: + """List all agents for the caller's team. + + Each agent includes an `available` flag + indicating whether it is within the team's plan limit and may be used for runs. + """ + return self._get( + "/agent/identities", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=ListAgentIdentitiesResponse, + ) + + def delete( + self, + uid: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> None: + """Delete an agent. + + All API keys associated with the agent are deleted atomically. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not uid: + raise ValueError(f"Expected a non-empty value for `uid` but received {uid!r}") + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + return self._delete( + path_template("/agent/identities/{uid}", uid=uid), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) + + +class AsyncAgentResource(AsyncAPIResource): + """Operations for running and managing cloud agents""" + + @cached_property + def with_raw_response(self) -> AsyncAgentResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/warpdotdev/oz-sdk-python#accessing-raw-response-data-eg-headers + """ + return AsyncAgentResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncAgentResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/warpdotdev/oz-sdk-python#with_streaming_response + """ + return AsyncAgentResourceWithStreamingResponse(self) + + async def create( + self, + *, + name: str, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> AgentResponse: + """Create a new agent for the caller's team. + + Agents can be used as the execution + principal for team-owned runs. + + Args: + name: A name for the agent + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return await self._post( + "/agent/identities", + body=await async_maybe_transform({"name": name}, agent_create_params.AgentCreateParams), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=AgentResponse, + ) + + async def update( + self, + uid: str, + *, + name: str | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> AgentResponse: + """ + Update an existing agent. + + Args: + name: The new name for the agent + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not uid: + raise ValueError(f"Expected a non-empty value for `uid` but received {uid!r}") + return await self._put( + path_template("/agent/identities/{uid}", uid=uid), + body=await async_maybe_transform({"name": name}, agent_update_params.AgentUpdateParams), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=AgentResponse, + ) + + async def list( + self, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> ListAgentIdentitiesResponse: + """List all agents for the caller's team. + + Each agent includes an `available` flag + indicating whether it is within the team's plan limit and may be used for runs. + """ + return await self._get( + "/agent/identities", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=ListAgentIdentitiesResponse, + ) + + async def delete( + self, + uid: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> None: + """Delete an agent. + + All API keys associated with the agent are deleted atomically. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not uid: + raise ValueError(f"Expected a non-empty value for `uid` but received {uid!r}") + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + return await self._delete( + path_template("/agent/identities/{uid}", uid=uid), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) + + +class AgentResourceWithRawResponse: + def __init__(self, agent: AgentResource) -> None: + self._agent = agent + + self.create = to_raw_response_wrapper( + agent.create, + ) + self.update = to_raw_response_wrapper( + agent.update, + ) + self.list = to_raw_response_wrapper( + agent.list, + ) + self.delete = to_raw_response_wrapper( + agent.delete, + ) + + +class AsyncAgentResourceWithRawResponse: + def __init__(self, agent: AsyncAgentResource) -> None: + self._agent = agent + + self.create = async_to_raw_response_wrapper( + agent.create, + ) + self.update = async_to_raw_response_wrapper( + agent.update, + ) + self.list = async_to_raw_response_wrapper( + agent.list, + ) + self.delete = async_to_raw_response_wrapper( + agent.delete, + ) + + +class AgentResourceWithStreamingResponse: + def __init__(self, agent: AgentResource) -> None: + self._agent = agent + + self.create = to_streamed_response_wrapper( + agent.create, + ) + self.update = to_streamed_response_wrapper( + agent.update, + ) + self.list = to_streamed_response_wrapper( + agent.list, + ) + self.delete = to_streamed_response_wrapper( + agent.delete, + ) + + +class AsyncAgentResourceWithStreamingResponse: + def __init__(self, agent: AsyncAgentResource) -> None: + self._agent = agent + + self.create = async_to_streamed_response_wrapper( + agent.create, + ) + self.update = async_to_streamed_response_wrapper( + agent.update, + ) + self.list = async_to_streamed_response_wrapper( + agent.list, + ) + self.delete = async_to_streamed_response_wrapper( + agent.delete, + ) diff --git a/src/oz_agent_sdk/types/agent/__init__.py b/src/oz_agent_sdk/types/agent/__init__.py index 1176974..ca0f9d8 100644 --- a/src/oz_agent_sdk/types/agent/__init__.py +++ b/src/oz_agent_sdk/types/agent/__init__.py @@ -5,8 +5,11 @@ from .run_item import RunItem as RunItem from .run_state import RunState as RunState from .artifact_item import ArtifactItem as ArtifactItem +from .agent_response import AgentResponse as AgentResponse from .run_list_params import RunListParams as RunListParams from .run_source_type import RunSourceType as RunSourceType +from .agent_create_params import AgentCreateParams as AgentCreateParams +from .agent_update_params import AgentUpdateParams as AgentUpdateParams from .run_cancel_response import RunCancelResponse as RunCancelResponse from .scheduled_agent_item import ScheduledAgentItem as ScheduledAgentItem from .schedule_create_params import ScheduleCreateParams as ScheduleCreateParams @@ -14,4 +17,5 @@ from .schedule_update_params import ScheduleUpdateParams as ScheduleUpdateParams from .schedule_delete_response import ScheduleDeleteResponse as ScheduleDeleteResponse from .scheduled_agent_history_item import ScheduledAgentHistoryItem as ScheduledAgentHistoryItem +from .list_agent_identities_response import ListAgentIdentitiesResponse as ListAgentIdentitiesResponse from .session_check_redirect_response import SessionCheckRedirectResponse as SessionCheckRedirectResponse diff --git a/src/oz_agent_sdk/types/agent/agent_create_params.py b/src/oz_agent_sdk/types/agent/agent_create_params.py new file mode 100644 index 0000000..5f0a737 --- /dev/null +++ b/src/oz_agent_sdk/types/agent/agent_create_params.py @@ -0,0 +1,12 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Required, TypedDict + +__all__ = ["AgentCreateParams"] + + +class AgentCreateParams(TypedDict, total=False): + name: Required[str] + """A name for the agent""" diff --git a/src/oz_agent_sdk/types/agent/agent_response.py b/src/oz_agent_sdk/types/agent/agent_response.py new file mode 100644 index 0000000..d748157 --- /dev/null +++ b/src/oz_agent_sdk/types/agent/agent_response.py @@ -0,0 +1,21 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from datetime import datetime + +from ..._models import BaseModel + +__all__ = ["AgentResponse"] + + +class AgentResponse(BaseModel): + available: bool + """Whether this agent is within the team's plan limit and can be used for runs""" + + created_at: datetime + """When the agent was created (RFC3339)""" + + name: str + """Name of the agent""" + + uid: str + """Unique identifier for the agent""" diff --git a/src/oz_agent_sdk/types/agent/agent_update_params.py b/src/oz_agent_sdk/types/agent/agent_update_params.py new file mode 100644 index 0000000..e5aecdd --- /dev/null +++ b/src/oz_agent_sdk/types/agent/agent_update_params.py @@ -0,0 +1,12 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import TypedDict + +__all__ = ["AgentUpdateParams"] + + +class AgentUpdateParams(TypedDict, total=False): + name: str + """The new name for the agent""" diff --git a/src/oz_agent_sdk/types/agent/list_agent_identities_response.py b/src/oz_agent_sdk/types/agent/list_agent_identities_response.py new file mode 100644 index 0000000..d796e6f --- /dev/null +++ b/src/oz_agent_sdk/types/agent/list_agent_identities_response.py @@ -0,0 +1,12 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List + +from ..._models import BaseModel +from .agent_response import AgentResponse + +__all__ = ["ListAgentIdentitiesResponse"] + + +class ListAgentIdentitiesResponse(BaseModel): + agents: List[AgentResponse] diff --git a/tests/api_resources/agent/test_agent_.py b/tests/api_resources/agent/test_agent_.py new file mode 100644 index 0000000..9bbc914 --- /dev/null +++ b/tests/api_resources/agent/test_agent_.py @@ -0,0 +1,337 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +from typing import Any, cast + +import pytest + +from tests.utils import assert_matches_type +from oz_agent_sdk import OzAPI, AsyncOzAPI +from oz_agent_sdk.types.agent import ( + AgentResponse, + ListAgentIdentitiesResponse, +) + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestAgent: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_create(self, client: OzAPI) -> None: + agent = client.agent.agent.create( + name="name", + ) + assert_matches_type(AgentResponse, agent, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_create(self, client: OzAPI) -> None: + response = client.agent.agent.with_raw_response.create( + name="name", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + agent = response.parse() + assert_matches_type(AgentResponse, agent, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_create(self, client: OzAPI) -> None: + with client.agent.agent.with_streaming_response.create( + name="name", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + agent = response.parse() + assert_matches_type(AgentResponse, agent, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_update(self, client: OzAPI) -> None: + agent = client.agent.agent.update( + uid="uid", + ) + assert_matches_type(AgentResponse, agent, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_update_with_all_params(self, client: OzAPI) -> None: + agent = client.agent.agent.update( + uid="uid", + name="name", + ) + assert_matches_type(AgentResponse, agent, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_update(self, client: OzAPI) -> None: + response = client.agent.agent.with_raw_response.update( + uid="uid", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + agent = response.parse() + assert_matches_type(AgentResponse, agent, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_update(self, client: OzAPI) -> None: + with client.agent.agent.with_streaming_response.update( + uid="uid", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + agent = response.parse() + assert_matches_type(AgentResponse, agent, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_path_params_update(self, client: OzAPI) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `uid` but received ''"): + client.agent.agent.with_raw_response.update( + uid="", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_list(self, client: OzAPI) -> None: + agent = client.agent.agent.list() + assert_matches_type(ListAgentIdentitiesResponse, agent, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_list(self, client: OzAPI) -> None: + response = client.agent.agent.with_raw_response.list() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + agent = response.parse() + assert_matches_type(ListAgentIdentitiesResponse, agent, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_list(self, client: OzAPI) -> None: + with client.agent.agent.with_streaming_response.list() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + agent = response.parse() + assert_matches_type(ListAgentIdentitiesResponse, agent, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_delete(self, client: OzAPI) -> None: + agent = client.agent.agent.delete( + "uid", + ) + assert agent is None + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_delete(self, client: OzAPI) -> None: + response = client.agent.agent.with_raw_response.delete( + "uid", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + agent = response.parse() + assert agent is None + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_delete(self, client: OzAPI) -> None: + with client.agent.agent.with_streaming_response.delete( + "uid", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + agent = response.parse() + assert agent is None + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_path_params_delete(self, client: OzAPI) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `uid` but received ''"): + client.agent.agent.with_raw_response.delete( + "", + ) + + +class TestAsyncAgent: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_create(self, async_client: AsyncOzAPI) -> None: + agent = await async_client.agent.agent.create( + name="name", + ) + assert_matches_type(AgentResponse, agent, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_create(self, async_client: AsyncOzAPI) -> None: + response = await async_client.agent.agent.with_raw_response.create( + name="name", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + agent = await response.parse() + assert_matches_type(AgentResponse, agent, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_create(self, async_client: AsyncOzAPI) -> None: + async with async_client.agent.agent.with_streaming_response.create( + name="name", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + agent = await response.parse() + assert_matches_type(AgentResponse, agent, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_update(self, async_client: AsyncOzAPI) -> None: + agent = await async_client.agent.agent.update( + uid="uid", + ) + assert_matches_type(AgentResponse, agent, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_update_with_all_params(self, async_client: AsyncOzAPI) -> None: + agent = await async_client.agent.agent.update( + uid="uid", + name="name", + ) + assert_matches_type(AgentResponse, agent, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_update(self, async_client: AsyncOzAPI) -> None: + response = await async_client.agent.agent.with_raw_response.update( + uid="uid", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + agent = await response.parse() + assert_matches_type(AgentResponse, agent, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_update(self, async_client: AsyncOzAPI) -> None: + async with async_client.agent.agent.with_streaming_response.update( + uid="uid", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + agent = await response.parse() + assert_matches_type(AgentResponse, agent, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_path_params_update(self, async_client: AsyncOzAPI) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `uid` but received ''"): + await async_client.agent.agent.with_raw_response.update( + uid="", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_list(self, async_client: AsyncOzAPI) -> None: + agent = await async_client.agent.agent.list() + assert_matches_type(ListAgentIdentitiesResponse, agent, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_list(self, async_client: AsyncOzAPI) -> None: + response = await async_client.agent.agent.with_raw_response.list() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + agent = await response.parse() + assert_matches_type(ListAgentIdentitiesResponse, agent, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_list(self, async_client: AsyncOzAPI) -> None: + async with async_client.agent.agent.with_streaming_response.list() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + agent = await response.parse() + assert_matches_type(ListAgentIdentitiesResponse, agent, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_delete(self, async_client: AsyncOzAPI) -> None: + agent = await async_client.agent.agent.delete( + "uid", + ) + assert agent is None + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_delete(self, async_client: AsyncOzAPI) -> None: + response = await async_client.agent.agent.with_raw_response.delete( + "uid", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + agent = await response.parse() + assert agent is None + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_delete(self, async_client: AsyncOzAPI) -> None: + async with async_client.agent.agent.with_streaming_response.delete( + "uid", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + agent = await response.parse() + assert agent is None + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_path_params_delete(self, async_client: AsyncOzAPI) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `uid` but received ''"): + await async_client.agent.agent.with_raw_response.delete( + "", + ) From b8e42cc08805eef08a3462088ba0e32cf79dac8c Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 17 Apr 2026 17:33:30 +0000 Subject: [PATCH 18/56] perf(client): optimize file structure copying in multipart requests --- src/oz_agent_sdk/_files.py | 56 +++++++++++++++- src/oz_agent_sdk/_utils/__init__.py | 1 - src/oz_agent_sdk/_utils/_utils.py | 15 ----- tests/test_deepcopy.py | 58 ----------------- tests/test_files.py | 99 ++++++++++++++++++++++++++++- 5 files changed, 151 insertions(+), 78 deletions(-) delete mode 100644 tests/test_deepcopy.py diff --git a/src/oz_agent_sdk/_files.py b/src/oz_agent_sdk/_files.py index cc14c14..0fdce17 100644 --- a/src/oz_agent_sdk/_files.py +++ b/src/oz_agent_sdk/_files.py @@ -3,8 +3,8 @@ import io import os import pathlib -from typing import overload -from typing_extensions import TypeGuard +from typing import Sequence, cast, overload +from typing_extensions import TypeVar, TypeGuard import anyio @@ -17,7 +17,9 @@ HttpxFileContent, HttpxRequestFiles, ) -from ._utils import is_tuple_t, is_mapping_t, is_sequence_t +from ._utils import is_list, is_mapping, is_tuple_t, is_mapping_t, is_sequence_t + +_T = TypeVar("_T") def is_base64_file_input(obj: object) -> TypeGuard[Base64FileInput]: @@ -121,3 +123,51 @@ async def async_read_file_content(file: FileContent) -> HttpxFileContent: return await anyio.Path(file).read_bytes() return file + + +def deepcopy_with_paths(item: _T, paths: Sequence[Sequence[str]]) -> _T: + """Copy only the containers along the given paths. + + Used to guard against mutation by extract_files without copying the entire structure. + Only dicts and lists that lie on a path are copied; everything else + is returned by reference. + + For example, given paths=[["foo", "files", "file"]] and the structure: + { + "foo": { + "bar": {"baz": {}}, + "files": {"file": } + } + } + The root dict, "foo", and "files" are copied (they lie on the path). + "bar" and "baz" are returned by reference (off the path). + """ + return _deepcopy_with_paths(item, paths, 0) + + +def _deepcopy_with_paths(item: _T, paths: Sequence[Sequence[str]], index: int) -> _T: + if not paths: + return item + if is_mapping(item): + key_to_paths: dict[str, list[Sequence[str]]] = {} + for path in paths: + if index < len(path): + key_to_paths.setdefault(path[index], []).append(path) + + # if no path continues through this mapping, it won't be mutated and copying it is redundant + if not key_to_paths: + return item + + result = dict(item) + for key, subpaths in key_to_paths.items(): + if key in result: + result[key] = _deepcopy_with_paths(result[key], subpaths, index + 1) + return cast(_T, result) + if is_list(item): + array_paths = [path for path in paths if index < len(path) and path[index] == ""] + + # if no path expects a list here, nothing will be mutated inside it - return by reference + if not array_paths: + return cast(_T, item) + return cast(_T, [_deepcopy_with_paths(entry, array_paths, index + 1) for entry in item]) + return item diff --git a/src/oz_agent_sdk/_utils/__init__.py b/src/oz_agent_sdk/_utils/__init__.py index 10cb66d..1c090e5 100644 --- a/src/oz_agent_sdk/_utils/__init__.py +++ b/src/oz_agent_sdk/_utils/__init__.py @@ -24,7 +24,6 @@ coerce_integer as coerce_integer, file_from_path as file_from_path, strip_not_given as strip_not_given, - deepcopy_minimal as deepcopy_minimal, get_async_library as get_async_library, maybe_coerce_float as maybe_coerce_float, get_required_header as get_required_header, diff --git a/src/oz_agent_sdk/_utils/_utils.py b/src/oz_agent_sdk/_utils/_utils.py index 63b8cd6..771859f 100644 --- a/src/oz_agent_sdk/_utils/_utils.py +++ b/src/oz_agent_sdk/_utils/_utils.py @@ -177,21 +177,6 @@ def is_iterable(obj: object) -> TypeGuard[Iterable[object]]: return isinstance(obj, Iterable) -def deepcopy_minimal(item: _T) -> _T: - """Minimal reimplementation of copy.deepcopy() that will only copy certain object types: - - - mappings, e.g. `dict` - - list - - This is done for performance reasons. - """ - if is_mapping(item): - return cast(_T, {k: deepcopy_minimal(v) for k, v in item.items()}) - if is_list(item): - return cast(_T, [deepcopy_minimal(entry) for entry in item]) - return item - - # copied from https://github.com/Rapptz/RoboDanny def human_join(seq: Sequence[str], *, delim: str = ", ", final: str = "or") -> str: size = len(seq) diff --git a/tests/test_deepcopy.py b/tests/test_deepcopy.py deleted file mode 100644 index 009b9b9..0000000 --- a/tests/test_deepcopy.py +++ /dev/null @@ -1,58 +0,0 @@ -from oz_agent_sdk._utils import deepcopy_minimal - - -def assert_different_identities(obj1: object, obj2: object) -> None: - assert obj1 == obj2 - assert id(obj1) != id(obj2) - - -def test_simple_dict() -> None: - obj1 = {"foo": "bar"} - obj2 = deepcopy_minimal(obj1) - assert_different_identities(obj1, obj2) - - -def test_nested_dict() -> None: - obj1 = {"foo": {"bar": True}} - obj2 = deepcopy_minimal(obj1) - assert_different_identities(obj1, obj2) - assert_different_identities(obj1["foo"], obj2["foo"]) - - -def test_complex_nested_dict() -> None: - obj1 = {"foo": {"bar": [{"hello": "world"}]}} - obj2 = deepcopy_minimal(obj1) - assert_different_identities(obj1, obj2) - assert_different_identities(obj1["foo"], obj2["foo"]) - assert_different_identities(obj1["foo"]["bar"], obj2["foo"]["bar"]) - assert_different_identities(obj1["foo"]["bar"][0], obj2["foo"]["bar"][0]) - - -def test_simple_list() -> None: - obj1 = ["a", "b", "c"] - obj2 = deepcopy_minimal(obj1) - assert_different_identities(obj1, obj2) - - -def test_nested_list() -> None: - obj1 = ["a", [1, 2, 3]] - obj2 = deepcopy_minimal(obj1) - assert_different_identities(obj1, obj2) - assert_different_identities(obj1[1], obj2[1]) - - -class MyObject: ... - - -def test_ignores_other_types() -> None: - # custom classes - my_obj = MyObject() - obj1 = {"foo": my_obj} - obj2 = deepcopy_minimal(obj1) - assert_different_identities(obj1, obj2) - assert obj1["foo"] is my_obj - - # tuples - obj3 = ("a", "b") - obj4 = deepcopy_minimal(obj3) - assert obj3 is obj4 diff --git a/tests/test_files.py b/tests/test_files.py index a1255cc..26486e1 100644 --- a/tests/test_files.py +++ b/tests/test_files.py @@ -4,7 +4,8 @@ import pytest from dirty_equals import IsDict, IsList, IsBytes, IsTuple -from oz_agent_sdk._files import to_httpx_files, async_to_httpx_files +from oz_agent_sdk._files import to_httpx_files, deepcopy_with_paths, async_to_httpx_files +from oz_agent_sdk._utils import extract_files readme_path = Path(__file__).parent.parent.joinpath("README.md") @@ -49,3 +50,99 @@ def test_string_not_allowed() -> None: "file": "foo", # type: ignore } ) + + +def assert_different_identities(obj1: object, obj2: object) -> None: + assert obj1 == obj2 + assert obj1 is not obj2 + + +class TestDeepcopyWithPaths: + def test_copies_top_level_dict(self) -> None: + original = {"file": b"data", "other": "value"} + result = deepcopy_with_paths(original, [["file"]]) + assert_different_identities(result, original) + + def test_file_value_is_same_reference(self) -> None: + file_bytes = b"contents" + original = {"file": file_bytes} + result = deepcopy_with_paths(original, [["file"]]) + assert_different_identities(result, original) + assert result["file"] is file_bytes + + def test_list_popped_wholesale(self) -> None: + files = [b"f1", b"f2"] + original = {"files": files, "title": "t"} + result = deepcopy_with_paths(original, [["files", ""]]) + assert_different_identities(result, original) + result_files = result["files"] + assert isinstance(result_files, list) + assert_different_identities(result_files, files) + + def test_nested_array_path_copies_list_and_elements(self) -> None: + elem1 = {"file": b"f1", "extra": 1} + elem2 = {"file": b"f2", "extra": 2} + original = {"items": [elem1, elem2]} + result = deepcopy_with_paths(original, [["items", "", "file"]]) + assert_different_identities(result, original) + result_items = result["items"] + assert isinstance(result_items, list) + assert_different_identities(result_items, original["items"]) + assert_different_identities(result_items[0], elem1) + assert_different_identities(result_items[1], elem2) + + def test_empty_paths_returns_same_object(self) -> None: + original = {"foo": "bar"} + result = deepcopy_with_paths(original, []) + assert result is original + + def test_multiple_paths(self) -> None: + f1 = b"file1" + f2 = b"file2" + original = {"a": f1, "b": f2, "c": "unchanged"} + result = deepcopy_with_paths(original, [["a"], ["b"]]) + assert_different_identities(result, original) + assert result["a"] is f1 + assert result["b"] is f2 + assert result["c"] is original["c"] + + def test_extract_files_does_not_mutate_original_top_level(self) -> None: + file_bytes = b"contents" + original = {"file": file_bytes, "other": "value"} + + copied = deepcopy_with_paths(original, [["file"]]) + extracted = extract_files(copied, paths=[["file"]]) + + assert extracted == [("file", file_bytes)] + assert original == {"file": file_bytes, "other": "value"} + assert copied == {"other": "value"} + + def test_extract_files_does_not_mutate_original_nested_array_path(self) -> None: + file1 = b"f1" + file2 = b"f2" + original = { + "items": [ + {"file": file1, "extra": 1}, + {"file": file2, "extra": 2}, + ], + "title": "example", + } + + copied = deepcopy_with_paths(original, [["items", "", "file"]]) + extracted = extract_files(copied, paths=[["items", "", "file"]]) + + assert extracted == [("items[][file]", file1), ("items[][file]", file2)] + assert original == { + "items": [ + {"file": file1, "extra": 1}, + {"file": file2, "extra": 2}, + ], + "title": "example", + } + assert copied == { + "items": [ + {"extra": 1}, + {"extra": 2}, + ], + "title": "example", + } From 7f419faa01908e1b4a613ec2bdd708aed1a05871 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 17 Apr 2026 19:46:56 +0000 Subject: [PATCH 19/56] feat(api): api update --- .stats.yml | 8 +- api.md | 20 - src/oz_agent_sdk/resources/agent/agent.py | 31 -- src/oz_agent_sdk/resources/agent/agent_.py | 402 ------------------ src/oz_agent_sdk/types/agent/__init__.py | 4 - .../types/agent/agent_create_params.py | 12 - .../types/agent/agent_response.py | 21 - .../types/agent/agent_update_params.py | 12 - .../agent/list_agent_identities_response.py | 12 - tests/api_resources/agent/test_agent_.py | 337 --------------- 10 files changed, 4 insertions(+), 855 deletions(-) delete mode 100644 src/oz_agent_sdk/resources/agent/agent_.py delete mode 100644 src/oz_agent_sdk/types/agent/agent_create_params.py delete mode 100644 src/oz_agent_sdk/types/agent/agent_response.py delete mode 100644 src/oz_agent_sdk/types/agent/agent_update_params.py delete mode 100644 src/oz_agent_sdk/types/agent/list_agent_identities_response.py delete mode 100644 tests/api_resources/agent/test_agent_.py diff --git a/.stats.yml b/.stats.yml index 2077b1f..6163321 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 19 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta%2Fwarp-api-3226a0810ae5de980509e31910138990d93d2843918730249caed1436e677ec3.yml -openapi_spec_hash: 776a9087e0c342e9fcbd140e75936d75 -config_hash: c5fc921cc04f541a85f92299f365eba6 +configured_endpoints: 15 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta%2Fwarp-api-252ab435934e85d5f76957188c64906abf76a0351c5861383327cb1297a2ac8a.yml +openapi_spec_hash: ed801bb30428c1c66cb0af97e3f6ee9c +config_hash: 253e4b5ca01236d448980a78491c17c5 diff --git a/api.md b/api.md index 918ca45..065cedb 100644 --- a/api.md +++ b/api.md @@ -72,26 +72,6 @@ Methods: - client.agent.schedules.pause(schedule_id) -> ScheduledAgentItem - client.agent.schedules.resume(schedule_id) -> ScheduledAgentItem -## Agent - -Types: - -```python -from oz_agent_sdk.types.agent import ( - AgentResponse, - CreateAgentRequest, - ListAgentIdentitiesResponse, - UpdateAgentRequest, -) -``` - -Methods: - -- client.agent.agent.create(\*\*params) -> AgentResponse -- client.agent.agent.update(uid, \*\*params) -> AgentResponse -- client.agent.agent.list() -> ListAgentIdentitiesResponse -- client.agent.agent.delete(uid) -> None - ## Sessions Types: diff --git a/src/oz_agent_sdk/resources/agent/agent.py b/src/oz_agent_sdk/resources/agent/agent.py index 0b12e59..d8d58ef 100644 --- a/src/oz_agent_sdk/resources/agent/agent.py +++ b/src/oz_agent_sdk/resources/agent/agent.py @@ -7,7 +7,6 @@ import httpx -from . import agent_ as agent from .runs import ( RunsResource, AsyncRunsResource, @@ -66,11 +65,6 @@ def schedules(self) -> SchedulesResource: """Operations for creating and managing scheduled agents""" return SchedulesResource(self._client) - @cached_property - def agent(self) -> agent.AgentResource: - """Operations for running and managing cloud agents""" - return agent.AgentResource(self._client) - @cached_property def sessions(self) -> SessionsResource: """Operations for running and managing cloud agents""" @@ -344,11 +338,6 @@ def schedules(self) -> AsyncSchedulesResource: """Operations for creating and managing scheduled agents""" return AsyncSchedulesResource(self._client) - @cached_property - def agent(self) -> agent.AsyncAgentResource: - """Operations for running and managing cloud agents""" - return agent.AsyncAgentResource(self._client) - @cached_property def sessions(self) -> AsyncSessionsResource: """Operations for running and managing cloud agents""" @@ -638,11 +627,6 @@ def schedules(self) -> SchedulesResourceWithRawResponse: """Operations for creating and managing scheduled agents""" return SchedulesResourceWithRawResponse(self._agent.schedules) - @cached_property - def agent(self) -> agent.AgentResourceWithRawResponse: - """Operations for running and managing cloud agents""" - return agent.AgentResourceWithRawResponse(self._agent.agent) - @cached_property def sessions(self) -> SessionsResourceWithRawResponse: """Operations for running and managing cloud agents""" @@ -676,11 +660,6 @@ def schedules(self) -> AsyncSchedulesResourceWithRawResponse: """Operations for creating and managing scheduled agents""" return AsyncSchedulesResourceWithRawResponse(self._agent.schedules) - @cached_property - def agent(self) -> agent.AsyncAgentResourceWithRawResponse: - """Operations for running and managing cloud agents""" - return agent.AsyncAgentResourceWithRawResponse(self._agent.agent) - @cached_property def sessions(self) -> AsyncSessionsResourceWithRawResponse: """Operations for running and managing cloud agents""" @@ -714,11 +693,6 @@ def schedules(self) -> SchedulesResourceWithStreamingResponse: """Operations for creating and managing scheduled agents""" return SchedulesResourceWithStreamingResponse(self._agent.schedules) - @cached_property - def agent(self) -> agent.AgentResourceWithStreamingResponse: - """Operations for running and managing cloud agents""" - return agent.AgentResourceWithStreamingResponse(self._agent.agent) - @cached_property def sessions(self) -> SessionsResourceWithStreamingResponse: """Operations for running and managing cloud agents""" @@ -752,11 +726,6 @@ def schedules(self) -> AsyncSchedulesResourceWithStreamingResponse: """Operations for creating and managing scheduled agents""" return AsyncSchedulesResourceWithStreamingResponse(self._agent.schedules) - @cached_property - def agent(self) -> agent.AsyncAgentResourceWithStreamingResponse: - """Operations for running and managing cloud agents""" - return agent.AsyncAgentResourceWithStreamingResponse(self._agent.agent) - @cached_property def sessions(self) -> AsyncSessionsResourceWithStreamingResponse: """Operations for running and managing cloud agents""" diff --git a/src/oz_agent_sdk/resources/agent/agent_.py b/src/oz_agent_sdk/resources/agent/agent_.py deleted file mode 100644 index 2c82516..0000000 --- a/src/oz_agent_sdk/resources/agent/agent_.py +++ /dev/null @@ -1,402 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -import httpx - -from ..._types import Body, Omit, Query, Headers, NoneType, NotGiven, omit, not_given -from ..._utils import path_template, maybe_transform, async_maybe_transform -from ..._compat import cached_property -from ..._resource import SyncAPIResource, AsyncAPIResource -from ..._response import ( - to_raw_response_wrapper, - to_streamed_response_wrapper, - async_to_raw_response_wrapper, - async_to_streamed_response_wrapper, -) -from ...types.agent import agent_create_params, agent_update_params -from ..._base_client import make_request_options -from ...types.agent.agent_response import AgentResponse -from ...types.agent.list_agent_identities_response import ListAgentIdentitiesResponse - -__all__ = ["AgentResource", "AsyncAgentResource"] - - -class AgentResource(SyncAPIResource): - """Operations for running and managing cloud agents""" - - @cached_property - def with_raw_response(self) -> AgentResourceWithRawResponse: - """ - This property can be used as a prefix for any HTTP method call to return - the raw response object instead of the parsed content. - - For more information, see https://www.github.com/warpdotdev/oz-sdk-python#accessing-raw-response-data-eg-headers - """ - return AgentResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> AgentResourceWithStreamingResponse: - """ - An alternative to `.with_raw_response` that doesn't eagerly read the response body. - - For more information, see https://www.github.com/warpdotdev/oz-sdk-python#with_streaming_response - """ - return AgentResourceWithStreamingResponse(self) - - def create( - self, - *, - name: str, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> AgentResponse: - """Create a new agent for the caller's team. - - Agents can be used as the execution - principal for team-owned runs. - - Args: - name: A name for the agent - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - return self._post( - "/agent/identities", - body=maybe_transform({"name": name}, agent_create_params.AgentCreateParams), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=AgentResponse, - ) - - def update( - self, - uid: str, - *, - name: str | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> AgentResponse: - """ - Update an existing agent. - - Args: - name: The new name for the agent - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not uid: - raise ValueError(f"Expected a non-empty value for `uid` but received {uid!r}") - return self._put( - path_template("/agent/identities/{uid}", uid=uid), - body=maybe_transform({"name": name}, agent_update_params.AgentUpdateParams), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=AgentResponse, - ) - - def list( - self, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> ListAgentIdentitiesResponse: - """List all agents for the caller's team. - - Each agent includes an `available` flag - indicating whether it is within the team's plan limit and may be used for runs. - """ - return self._get( - "/agent/identities", - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=ListAgentIdentitiesResponse, - ) - - def delete( - self, - uid: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> None: - """Delete an agent. - - All API keys associated with the agent are deleted atomically. - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not uid: - raise ValueError(f"Expected a non-empty value for `uid` but received {uid!r}") - extra_headers = {"Accept": "*/*", **(extra_headers or {})} - return self._delete( - path_template("/agent/identities/{uid}", uid=uid), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=NoneType, - ) - - -class AsyncAgentResource(AsyncAPIResource): - """Operations for running and managing cloud agents""" - - @cached_property - def with_raw_response(self) -> AsyncAgentResourceWithRawResponse: - """ - This property can be used as a prefix for any HTTP method call to return - the raw response object instead of the parsed content. - - For more information, see https://www.github.com/warpdotdev/oz-sdk-python#accessing-raw-response-data-eg-headers - """ - return AsyncAgentResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> AsyncAgentResourceWithStreamingResponse: - """ - An alternative to `.with_raw_response` that doesn't eagerly read the response body. - - For more information, see https://www.github.com/warpdotdev/oz-sdk-python#with_streaming_response - """ - return AsyncAgentResourceWithStreamingResponse(self) - - async def create( - self, - *, - name: str, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> AgentResponse: - """Create a new agent for the caller's team. - - Agents can be used as the execution - principal for team-owned runs. - - Args: - name: A name for the agent - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - return await self._post( - "/agent/identities", - body=await async_maybe_transform({"name": name}, agent_create_params.AgentCreateParams), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=AgentResponse, - ) - - async def update( - self, - uid: str, - *, - name: str | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> AgentResponse: - """ - Update an existing agent. - - Args: - name: The new name for the agent - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not uid: - raise ValueError(f"Expected a non-empty value for `uid` but received {uid!r}") - return await self._put( - path_template("/agent/identities/{uid}", uid=uid), - body=await async_maybe_transform({"name": name}, agent_update_params.AgentUpdateParams), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=AgentResponse, - ) - - async def list( - self, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> ListAgentIdentitiesResponse: - """List all agents for the caller's team. - - Each agent includes an `available` flag - indicating whether it is within the team's plan limit and may be used for runs. - """ - return await self._get( - "/agent/identities", - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=ListAgentIdentitiesResponse, - ) - - async def delete( - self, - uid: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> None: - """Delete an agent. - - All API keys associated with the agent are deleted atomically. - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not uid: - raise ValueError(f"Expected a non-empty value for `uid` but received {uid!r}") - extra_headers = {"Accept": "*/*", **(extra_headers or {})} - return await self._delete( - path_template("/agent/identities/{uid}", uid=uid), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=NoneType, - ) - - -class AgentResourceWithRawResponse: - def __init__(self, agent: AgentResource) -> None: - self._agent = agent - - self.create = to_raw_response_wrapper( - agent.create, - ) - self.update = to_raw_response_wrapper( - agent.update, - ) - self.list = to_raw_response_wrapper( - agent.list, - ) - self.delete = to_raw_response_wrapper( - agent.delete, - ) - - -class AsyncAgentResourceWithRawResponse: - def __init__(self, agent: AsyncAgentResource) -> None: - self._agent = agent - - self.create = async_to_raw_response_wrapper( - agent.create, - ) - self.update = async_to_raw_response_wrapper( - agent.update, - ) - self.list = async_to_raw_response_wrapper( - agent.list, - ) - self.delete = async_to_raw_response_wrapper( - agent.delete, - ) - - -class AgentResourceWithStreamingResponse: - def __init__(self, agent: AgentResource) -> None: - self._agent = agent - - self.create = to_streamed_response_wrapper( - agent.create, - ) - self.update = to_streamed_response_wrapper( - agent.update, - ) - self.list = to_streamed_response_wrapper( - agent.list, - ) - self.delete = to_streamed_response_wrapper( - agent.delete, - ) - - -class AsyncAgentResourceWithStreamingResponse: - def __init__(self, agent: AsyncAgentResource) -> None: - self._agent = agent - - self.create = async_to_streamed_response_wrapper( - agent.create, - ) - self.update = async_to_streamed_response_wrapper( - agent.update, - ) - self.list = async_to_streamed_response_wrapper( - agent.list, - ) - self.delete = async_to_streamed_response_wrapper( - agent.delete, - ) diff --git a/src/oz_agent_sdk/types/agent/__init__.py b/src/oz_agent_sdk/types/agent/__init__.py index ca0f9d8..1176974 100644 --- a/src/oz_agent_sdk/types/agent/__init__.py +++ b/src/oz_agent_sdk/types/agent/__init__.py @@ -5,11 +5,8 @@ from .run_item import RunItem as RunItem from .run_state import RunState as RunState from .artifact_item import ArtifactItem as ArtifactItem -from .agent_response import AgentResponse as AgentResponse from .run_list_params import RunListParams as RunListParams from .run_source_type import RunSourceType as RunSourceType -from .agent_create_params import AgentCreateParams as AgentCreateParams -from .agent_update_params import AgentUpdateParams as AgentUpdateParams from .run_cancel_response import RunCancelResponse as RunCancelResponse from .scheduled_agent_item import ScheduledAgentItem as ScheduledAgentItem from .schedule_create_params import ScheduleCreateParams as ScheduleCreateParams @@ -17,5 +14,4 @@ from .schedule_update_params import ScheduleUpdateParams as ScheduleUpdateParams from .schedule_delete_response import ScheduleDeleteResponse as ScheduleDeleteResponse from .scheduled_agent_history_item import ScheduledAgentHistoryItem as ScheduledAgentHistoryItem -from .list_agent_identities_response import ListAgentIdentitiesResponse as ListAgentIdentitiesResponse from .session_check_redirect_response import SessionCheckRedirectResponse as SessionCheckRedirectResponse diff --git a/src/oz_agent_sdk/types/agent/agent_create_params.py b/src/oz_agent_sdk/types/agent/agent_create_params.py deleted file mode 100644 index 5f0a737..0000000 --- a/src/oz_agent_sdk/types/agent/agent_create_params.py +++ /dev/null @@ -1,12 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing_extensions import Required, TypedDict - -__all__ = ["AgentCreateParams"] - - -class AgentCreateParams(TypedDict, total=False): - name: Required[str] - """A name for the agent""" diff --git a/src/oz_agent_sdk/types/agent/agent_response.py b/src/oz_agent_sdk/types/agent/agent_response.py deleted file mode 100644 index d748157..0000000 --- a/src/oz_agent_sdk/types/agent/agent_response.py +++ /dev/null @@ -1,21 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from datetime import datetime - -from ..._models import BaseModel - -__all__ = ["AgentResponse"] - - -class AgentResponse(BaseModel): - available: bool - """Whether this agent is within the team's plan limit and can be used for runs""" - - created_at: datetime - """When the agent was created (RFC3339)""" - - name: str - """Name of the agent""" - - uid: str - """Unique identifier for the agent""" diff --git a/src/oz_agent_sdk/types/agent/agent_update_params.py b/src/oz_agent_sdk/types/agent/agent_update_params.py deleted file mode 100644 index e5aecdd..0000000 --- a/src/oz_agent_sdk/types/agent/agent_update_params.py +++ /dev/null @@ -1,12 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing_extensions import TypedDict - -__all__ = ["AgentUpdateParams"] - - -class AgentUpdateParams(TypedDict, total=False): - name: str - """The new name for the agent""" diff --git a/src/oz_agent_sdk/types/agent/list_agent_identities_response.py b/src/oz_agent_sdk/types/agent/list_agent_identities_response.py deleted file mode 100644 index d796e6f..0000000 --- a/src/oz_agent_sdk/types/agent/list_agent_identities_response.py +++ /dev/null @@ -1,12 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import List - -from ..._models import BaseModel -from .agent_response import AgentResponse - -__all__ = ["ListAgentIdentitiesResponse"] - - -class ListAgentIdentitiesResponse(BaseModel): - agents: List[AgentResponse] diff --git a/tests/api_resources/agent/test_agent_.py b/tests/api_resources/agent/test_agent_.py deleted file mode 100644 index 9bbc914..0000000 --- a/tests/api_resources/agent/test_agent_.py +++ /dev/null @@ -1,337 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -import os -from typing import Any, cast - -import pytest - -from tests.utils import assert_matches_type -from oz_agent_sdk import OzAPI, AsyncOzAPI -from oz_agent_sdk.types.agent import ( - AgentResponse, - ListAgentIdentitiesResponse, -) - -base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") - - -class TestAgent: - parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_method_create(self, client: OzAPI) -> None: - agent = client.agent.agent.create( - name="name", - ) - assert_matches_type(AgentResponse, agent, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_raw_response_create(self, client: OzAPI) -> None: - response = client.agent.agent.with_raw_response.create( - name="name", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - agent = response.parse() - assert_matches_type(AgentResponse, agent, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_streaming_response_create(self, client: OzAPI) -> None: - with client.agent.agent.with_streaming_response.create( - name="name", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - agent = response.parse() - assert_matches_type(AgentResponse, agent, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_method_update(self, client: OzAPI) -> None: - agent = client.agent.agent.update( - uid="uid", - ) - assert_matches_type(AgentResponse, agent, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_method_update_with_all_params(self, client: OzAPI) -> None: - agent = client.agent.agent.update( - uid="uid", - name="name", - ) - assert_matches_type(AgentResponse, agent, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_raw_response_update(self, client: OzAPI) -> None: - response = client.agent.agent.with_raw_response.update( - uid="uid", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - agent = response.parse() - assert_matches_type(AgentResponse, agent, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_streaming_response_update(self, client: OzAPI) -> None: - with client.agent.agent.with_streaming_response.update( - uid="uid", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - agent = response.parse() - assert_matches_type(AgentResponse, agent, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_path_params_update(self, client: OzAPI) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `uid` but received ''"): - client.agent.agent.with_raw_response.update( - uid="", - ) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_method_list(self, client: OzAPI) -> None: - agent = client.agent.agent.list() - assert_matches_type(ListAgentIdentitiesResponse, agent, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_raw_response_list(self, client: OzAPI) -> None: - response = client.agent.agent.with_raw_response.list() - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - agent = response.parse() - assert_matches_type(ListAgentIdentitiesResponse, agent, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_streaming_response_list(self, client: OzAPI) -> None: - with client.agent.agent.with_streaming_response.list() as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - agent = response.parse() - assert_matches_type(ListAgentIdentitiesResponse, agent, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_method_delete(self, client: OzAPI) -> None: - agent = client.agent.agent.delete( - "uid", - ) - assert agent is None - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_raw_response_delete(self, client: OzAPI) -> None: - response = client.agent.agent.with_raw_response.delete( - "uid", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - agent = response.parse() - assert agent is None - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_streaming_response_delete(self, client: OzAPI) -> None: - with client.agent.agent.with_streaming_response.delete( - "uid", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - agent = response.parse() - assert agent is None - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_path_params_delete(self, client: OzAPI) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `uid` but received ''"): - client.agent.agent.with_raw_response.delete( - "", - ) - - -class TestAsyncAgent: - parametrize = pytest.mark.parametrize( - "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] - ) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_method_create(self, async_client: AsyncOzAPI) -> None: - agent = await async_client.agent.agent.create( - name="name", - ) - assert_matches_type(AgentResponse, agent, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_raw_response_create(self, async_client: AsyncOzAPI) -> None: - response = await async_client.agent.agent.with_raw_response.create( - name="name", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - agent = await response.parse() - assert_matches_type(AgentResponse, agent, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_streaming_response_create(self, async_client: AsyncOzAPI) -> None: - async with async_client.agent.agent.with_streaming_response.create( - name="name", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - agent = await response.parse() - assert_matches_type(AgentResponse, agent, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_method_update(self, async_client: AsyncOzAPI) -> None: - agent = await async_client.agent.agent.update( - uid="uid", - ) - assert_matches_type(AgentResponse, agent, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_method_update_with_all_params(self, async_client: AsyncOzAPI) -> None: - agent = await async_client.agent.agent.update( - uid="uid", - name="name", - ) - assert_matches_type(AgentResponse, agent, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_raw_response_update(self, async_client: AsyncOzAPI) -> None: - response = await async_client.agent.agent.with_raw_response.update( - uid="uid", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - agent = await response.parse() - assert_matches_type(AgentResponse, agent, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_streaming_response_update(self, async_client: AsyncOzAPI) -> None: - async with async_client.agent.agent.with_streaming_response.update( - uid="uid", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - agent = await response.parse() - assert_matches_type(AgentResponse, agent, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_path_params_update(self, async_client: AsyncOzAPI) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `uid` but received ''"): - await async_client.agent.agent.with_raw_response.update( - uid="", - ) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_method_list(self, async_client: AsyncOzAPI) -> None: - agent = await async_client.agent.agent.list() - assert_matches_type(ListAgentIdentitiesResponse, agent, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_raw_response_list(self, async_client: AsyncOzAPI) -> None: - response = await async_client.agent.agent.with_raw_response.list() - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - agent = await response.parse() - assert_matches_type(ListAgentIdentitiesResponse, agent, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_streaming_response_list(self, async_client: AsyncOzAPI) -> None: - async with async_client.agent.agent.with_streaming_response.list() as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - agent = await response.parse() - assert_matches_type(ListAgentIdentitiesResponse, agent, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_method_delete(self, async_client: AsyncOzAPI) -> None: - agent = await async_client.agent.agent.delete( - "uid", - ) - assert agent is None - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_raw_response_delete(self, async_client: AsyncOzAPI) -> None: - response = await async_client.agent.agent.with_raw_response.delete( - "uid", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - agent = await response.parse() - assert agent is None - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_streaming_response_delete(self, async_client: AsyncOzAPI) -> None: - async with async_client.agent.agent.with_streaming_response.delete( - "uid", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - agent = await response.parse() - assert agent is None - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_path_params_delete(self, async_client: AsyncOzAPI) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `uid` but received ''"): - await async_client.agent.agent.with_raw_response.delete( - "", - ) From f94b38b2ffaf344a198e89ad7ace1d7b8e93c300 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 17 Apr 2026 20:00:18 +0000 Subject: [PATCH 20/56] feat(api): api update --- .stats.yml | 8 +- api.md | 20 + src/oz_agent_sdk/resources/agent/agent.py | 31 ++ src/oz_agent_sdk/resources/agent/agent_.py | 402 ++++++++++++++++++ src/oz_agent_sdk/types/agent/__init__.py | 4 + .../types/agent/agent_create_params.py | 12 + .../types/agent/agent_response.py | 21 + .../types/agent/agent_update_params.py | 12 + .../agent/list_agent_identities_response.py | 12 + tests/api_resources/agent/test_agent_.py | 337 +++++++++++++++ 10 files changed, 855 insertions(+), 4 deletions(-) create mode 100644 src/oz_agent_sdk/resources/agent/agent_.py create mode 100644 src/oz_agent_sdk/types/agent/agent_create_params.py create mode 100644 src/oz_agent_sdk/types/agent/agent_response.py create mode 100644 src/oz_agent_sdk/types/agent/agent_update_params.py create mode 100644 src/oz_agent_sdk/types/agent/list_agent_identities_response.py create mode 100644 tests/api_resources/agent/test_agent_.py diff --git a/.stats.yml b/.stats.yml index 6163321..f4077c2 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 15 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta%2Fwarp-api-252ab435934e85d5f76957188c64906abf76a0351c5861383327cb1297a2ac8a.yml -openapi_spec_hash: ed801bb30428c1c66cb0af97e3f6ee9c -config_hash: 253e4b5ca01236d448980a78491c17c5 +configured_endpoints: 19 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta%2Fwarp-api-d8d008dde648ff6cf158203be9805315cf281f1f354a81bfc38c3eaf58952999.yml +openapi_spec_hash: 4e16bd26f8ac5f53ca2e663aabc6a1d1 +config_hash: c5fc921cc04f541a85f92299f365eba6 diff --git a/api.md b/api.md index 065cedb..918ca45 100644 --- a/api.md +++ b/api.md @@ -72,6 +72,26 @@ Methods: - client.agent.schedules.pause(schedule_id) -> ScheduledAgentItem - client.agent.schedules.resume(schedule_id) -> ScheduledAgentItem +## Agent + +Types: + +```python +from oz_agent_sdk.types.agent import ( + AgentResponse, + CreateAgentRequest, + ListAgentIdentitiesResponse, + UpdateAgentRequest, +) +``` + +Methods: + +- client.agent.agent.create(\*\*params) -> AgentResponse +- client.agent.agent.update(uid, \*\*params) -> AgentResponse +- client.agent.agent.list() -> ListAgentIdentitiesResponse +- client.agent.agent.delete(uid) -> None + ## Sessions Types: diff --git a/src/oz_agent_sdk/resources/agent/agent.py b/src/oz_agent_sdk/resources/agent/agent.py index d8d58ef..0b12e59 100644 --- a/src/oz_agent_sdk/resources/agent/agent.py +++ b/src/oz_agent_sdk/resources/agent/agent.py @@ -7,6 +7,7 @@ import httpx +from . import agent_ as agent from .runs import ( RunsResource, AsyncRunsResource, @@ -65,6 +66,11 @@ def schedules(self) -> SchedulesResource: """Operations for creating and managing scheduled agents""" return SchedulesResource(self._client) + @cached_property + def agent(self) -> agent.AgentResource: + """Operations for running and managing cloud agents""" + return agent.AgentResource(self._client) + @cached_property def sessions(self) -> SessionsResource: """Operations for running and managing cloud agents""" @@ -338,6 +344,11 @@ def schedules(self) -> AsyncSchedulesResource: """Operations for creating and managing scheduled agents""" return AsyncSchedulesResource(self._client) + @cached_property + def agent(self) -> agent.AsyncAgentResource: + """Operations for running and managing cloud agents""" + return agent.AsyncAgentResource(self._client) + @cached_property def sessions(self) -> AsyncSessionsResource: """Operations for running and managing cloud agents""" @@ -627,6 +638,11 @@ def schedules(self) -> SchedulesResourceWithRawResponse: """Operations for creating and managing scheduled agents""" return SchedulesResourceWithRawResponse(self._agent.schedules) + @cached_property + def agent(self) -> agent.AgentResourceWithRawResponse: + """Operations for running and managing cloud agents""" + return agent.AgentResourceWithRawResponse(self._agent.agent) + @cached_property def sessions(self) -> SessionsResourceWithRawResponse: """Operations for running and managing cloud agents""" @@ -660,6 +676,11 @@ def schedules(self) -> AsyncSchedulesResourceWithRawResponse: """Operations for creating and managing scheduled agents""" return AsyncSchedulesResourceWithRawResponse(self._agent.schedules) + @cached_property + def agent(self) -> agent.AsyncAgentResourceWithRawResponse: + """Operations for running and managing cloud agents""" + return agent.AsyncAgentResourceWithRawResponse(self._agent.agent) + @cached_property def sessions(self) -> AsyncSessionsResourceWithRawResponse: """Operations for running and managing cloud agents""" @@ -693,6 +714,11 @@ def schedules(self) -> SchedulesResourceWithStreamingResponse: """Operations for creating and managing scheduled agents""" return SchedulesResourceWithStreamingResponse(self._agent.schedules) + @cached_property + def agent(self) -> agent.AgentResourceWithStreamingResponse: + """Operations for running and managing cloud agents""" + return agent.AgentResourceWithStreamingResponse(self._agent.agent) + @cached_property def sessions(self) -> SessionsResourceWithStreamingResponse: """Operations for running and managing cloud agents""" @@ -726,6 +752,11 @@ def schedules(self) -> AsyncSchedulesResourceWithStreamingResponse: """Operations for creating and managing scheduled agents""" return AsyncSchedulesResourceWithStreamingResponse(self._agent.schedules) + @cached_property + def agent(self) -> agent.AsyncAgentResourceWithStreamingResponse: + """Operations for running and managing cloud agents""" + return agent.AsyncAgentResourceWithStreamingResponse(self._agent.agent) + @cached_property def sessions(self) -> AsyncSessionsResourceWithStreamingResponse: """Operations for running and managing cloud agents""" diff --git a/src/oz_agent_sdk/resources/agent/agent_.py b/src/oz_agent_sdk/resources/agent/agent_.py new file mode 100644 index 0000000..2c82516 --- /dev/null +++ b/src/oz_agent_sdk/resources/agent/agent_.py @@ -0,0 +1,402 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import httpx + +from ..._types import Body, Omit, Query, Headers, NoneType, NotGiven, omit, not_given +from ..._utils import path_template, maybe_transform, async_maybe_transform +from ..._compat import cached_property +from ..._resource import SyncAPIResource, AsyncAPIResource +from ..._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from ...types.agent import agent_create_params, agent_update_params +from ..._base_client import make_request_options +from ...types.agent.agent_response import AgentResponse +from ...types.agent.list_agent_identities_response import ListAgentIdentitiesResponse + +__all__ = ["AgentResource", "AsyncAgentResource"] + + +class AgentResource(SyncAPIResource): + """Operations for running and managing cloud agents""" + + @cached_property + def with_raw_response(self) -> AgentResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/warpdotdev/oz-sdk-python#accessing-raw-response-data-eg-headers + """ + return AgentResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AgentResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/warpdotdev/oz-sdk-python#with_streaming_response + """ + return AgentResourceWithStreamingResponse(self) + + def create( + self, + *, + name: str, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> AgentResponse: + """Create a new agent for the caller's team. + + Agents can be used as the execution + principal for team-owned runs. + + Args: + name: A name for the agent + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._post( + "/agent/identities", + body=maybe_transform({"name": name}, agent_create_params.AgentCreateParams), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=AgentResponse, + ) + + def update( + self, + uid: str, + *, + name: str | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> AgentResponse: + """ + Update an existing agent. + + Args: + name: The new name for the agent + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not uid: + raise ValueError(f"Expected a non-empty value for `uid` but received {uid!r}") + return self._put( + path_template("/agent/identities/{uid}", uid=uid), + body=maybe_transform({"name": name}, agent_update_params.AgentUpdateParams), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=AgentResponse, + ) + + def list( + self, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> ListAgentIdentitiesResponse: + """List all agents for the caller's team. + + Each agent includes an `available` flag + indicating whether it is within the team's plan limit and may be used for runs. + """ + return self._get( + "/agent/identities", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=ListAgentIdentitiesResponse, + ) + + def delete( + self, + uid: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> None: + """Delete an agent. + + All API keys associated with the agent are deleted atomically. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not uid: + raise ValueError(f"Expected a non-empty value for `uid` but received {uid!r}") + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + return self._delete( + path_template("/agent/identities/{uid}", uid=uid), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) + + +class AsyncAgentResource(AsyncAPIResource): + """Operations for running and managing cloud agents""" + + @cached_property + def with_raw_response(self) -> AsyncAgentResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/warpdotdev/oz-sdk-python#accessing-raw-response-data-eg-headers + """ + return AsyncAgentResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncAgentResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/warpdotdev/oz-sdk-python#with_streaming_response + """ + return AsyncAgentResourceWithStreamingResponse(self) + + async def create( + self, + *, + name: str, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> AgentResponse: + """Create a new agent for the caller's team. + + Agents can be used as the execution + principal for team-owned runs. + + Args: + name: A name for the agent + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return await self._post( + "/agent/identities", + body=await async_maybe_transform({"name": name}, agent_create_params.AgentCreateParams), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=AgentResponse, + ) + + async def update( + self, + uid: str, + *, + name: str | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> AgentResponse: + """ + Update an existing agent. + + Args: + name: The new name for the agent + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not uid: + raise ValueError(f"Expected a non-empty value for `uid` but received {uid!r}") + return await self._put( + path_template("/agent/identities/{uid}", uid=uid), + body=await async_maybe_transform({"name": name}, agent_update_params.AgentUpdateParams), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=AgentResponse, + ) + + async def list( + self, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> ListAgentIdentitiesResponse: + """List all agents for the caller's team. + + Each agent includes an `available` flag + indicating whether it is within the team's plan limit and may be used for runs. + """ + return await self._get( + "/agent/identities", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=ListAgentIdentitiesResponse, + ) + + async def delete( + self, + uid: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> None: + """Delete an agent. + + All API keys associated with the agent are deleted atomically. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not uid: + raise ValueError(f"Expected a non-empty value for `uid` but received {uid!r}") + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + return await self._delete( + path_template("/agent/identities/{uid}", uid=uid), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) + + +class AgentResourceWithRawResponse: + def __init__(self, agent: AgentResource) -> None: + self._agent = agent + + self.create = to_raw_response_wrapper( + agent.create, + ) + self.update = to_raw_response_wrapper( + agent.update, + ) + self.list = to_raw_response_wrapper( + agent.list, + ) + self.delete = to_raw_response_wrapper( + agent.delete, + ) + + +class AsyncAgentResourceWithRawResponse: + def __init__(self, agent: AsyncAgentResource) -> None: + self._agent = agent + + self.create = async_to_raw_response_wrapper( + agent.create, + ) + self.update = async_to_raw_response_wrapper( + agent.update, + ) + self.list = async_to_raw_response_wrapper( + agent.list, + ) + self.delete = async_to_raw_response_wrapper( + agent.delete, + ) + + +class AgentResourceWithStreamingResponse: + def __init__(self, agent: AgentResource) -> None: + self._agent = agent + + self.create = to_streamed_response_wrapper( + agent.create, + ) + self.update = to_streamed_response_wrapper( + agent.update, + ) + self.list = to_streamed_response_wrapper( + agent.list, + ) + self.delete = to_streamed_response_wrapper( + agent.delete, + ) + + +class AsyncAgentResourceWithStreamingResponse: + def __init__(self, agent: AsyncAgentResource) -> None: + self._agent = agent + + self.create = async_to_streamed_response_wrapper( + agent.create, + ) + self.update = async_to_streamed_response_wrapper( + agent.update, + ) + self.list = async_to_streamed_response_wrapper( + agent.list, + ) + self.delete = async_to_streamed_response_wrapper( + agent.delete, + ) diff --git a/src/oz_agent_sdk/types/agent/__init__.py b/src/oz_agent_sdk/types/agent/__init__.py index 1176974..ca0f9d8 100644 --- a/src/oz_agent_sdk/types/agent/__init__.py +++ b/src/oz_agent_sdk/types/agent/__init__.py @@ -5,8 +5,11 @@ from .run_item import RunItem as RunItem from .run_state import RunState as RunState from .artifact_item import ArtifactItem as ArtifactItem +from .agent_response import AgentResponse as AgentResponse from .run_list_params import RunListParams as RunListParams from .run_source_type import RunSourceType as RunSourceType +from .agent_create_params import AgentCreateParams as AgentCreateParams +from .agent_update_params import AgentUpdateParams as AgentUpdateParams from .run_cancel_response import RunCancelResponse as RunCancelResponse from .scheduled_agent_item import ScheduledAgentItem as ScheduledAgentItem from .schedule_create_params import ScheduleCreateParams as ScheduleCreateParams @@ -14,4 +17,5 @@ from .schedule_update_params import ScheduleUpdateParams as ScheduleUpdateParams from .schedule_delete_response import ScheduleDeleteResponse as ScheduleDeleteResponse from .scheduled_agent_history_item import ScheduledAgentHistoryItem as ScheduledAgentHistoryItem +from .list_agent_identities_response import ListAgentIdentitiesResponse as ListAgentIdentitiesResponse from .session_check_redirect_response import SessionCheckRedirectResponse as SessionCheckRedirectResponse diff --git a/src/oz_agent_sdk/types/agent/agent_create_params.py b/src/oz_agent_sdk/types/agent/agent_create_params.py new file mode 100644 index 0000000..5f0a737 --- /dev/null +++ b/src/oz_agent_sdk/types/agent/agent_create_params.py @@ -0,0 +1,12 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Required, TypedDict + +__all__ = ["AgentCreateParams"] + + +class AgentCreateParams(TypedDict, total=False): + name: Required[str] + """A name for the agent""" diff --git a/src/oz_agent_sdk/types/agent/agent_response.py b/src/oz_agent_sdk/types/agent/agent_response.py new file mode 100644 index 0000000..d748157 --- /dev/null +++ b/src/oz_agent_sdk/types/agent/agent_response.py @@ -0,0 +1,21 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from datetime import datetime + +from ..._models import BaseModel + +__all__ = ["AgentResponse"] + + +class AgentResponse(BaseModel): + available: bool + """Whether this agent is within the team's plan limit and can be used for runs""" + + created_at: datetime + """When the agent was created (RFC3339)""" + + name: str + """Name of the agent""" + + uid: str + """Unique identifier for the agent""" diff --git a/src/oz_agent_sdk/types/agent/agent_update_params.py b/src/oz_agent_sdk/types/agent/agent_update_params.py new file mode 100644 index 0000000..e5aecdd --- /dev/null +++ b/src/oz_agent_sdk/types/agent/agent_update_params.py @@ -0,0 +1,12 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import TypedDict + +__all__ = ["AgentUpdateParams"] + + +class AgentUpdateParams(TypedDict, total=False): + name: str + """The new name for the agent""" diff --git a/src/oz_agent_sdk/types/agent/list_agent_identities_response.py b/src/oz_agent_sdk/types/agent/list_agent_identities_response.py new file mode 100644 index 0000000..d796e6f --- /dev/null +++ b/src/oz_agent_sdk/types/agent/list_agent_identities_response.py @@ -0,0 +1,12 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List + +from ..._models import BaseModel +from .agent_response import AgentResponse + +__all__ = ["ListAgentIdentitiesResponse"] + + +class ListAgentIdentitiesResponse(BaseModel): + agents: List[AgentResponse] diff --git a/tests/api_resources/agent/test_agent_.py b/tests/api_resources/agent/test_agent_.py new file mode 100644 index 0000000..9bbc914 --- /dev/null +++ b/tests/api_resources/agent/test_agent_.py @@ -0,0 +1,337 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +from typing import Any, cast + +import pytest + +from tests.utils import assert_matches_type +from oz_agent_sdk import OzAPI, AsyncOzAPI +from oz_agent_sdk.types.agent import ( + AgentResponse, + ListAgentIdentitiesResponse, +) + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestAgent: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_create(self, client: OzAPI) -> None: + agent = client.agent.agent.create( + name="name", + ) + assert_matches_type(AgentResponse, agent, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_create(self, client: OzAPI) -> None: + response = client.agent.agent.with_raw_response.create( + name="name", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + agent = response.parse() + assert_matches_type(AgentResponse, agent, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_create(self, client: OzAPI) -> None: + with client.agent.agent.with_streaming_response.create( + name="name", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + agent = response.parse() + assert_matches_type(AgentResponse, agent, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_update(self, client: OzAPI) -> None: + agent = client.agent.agent.update( + uid="uid", + ) + assert_matches_type(AgentResponse, agent, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_update_with_all_params(self, client: OzAPI) -> None: + agent = client.agent.agent.update( + uid="uid", + name="name", + ) + assert_matches_type(AgentResponse, agent, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_update(self, client: OzAPI) -> None: + response = client.agent.agent.with_raw_response.update( + uid="uid", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + agent = response.parse() + assert_matches_type(AgentResponse, agent, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_update(self, client: OzAPI) -> None: + with client.agent.agent.with_streaming_response.update( + uid="uid", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + agent = response.parse() + assert_matches_type(AgentResponse, agent, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_path_params_update(self, client: OzAPI) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `uid` but received ''"): + client.agent.agent.with_raw_response.update( + uid="", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_list(self, client: OzAPI) -> None: + agent = client.agent.agent.list() + assert_matches_type(ListAgentIdentitiesResponse, agent, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_list(self, client: OzAPI) -> None: + response = client.agent.agent.with_raw_response.list() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + agent = response.parse() + assert_matches_type(ListAgentIdentitiesResponse, agent, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_list(self, client: OzAPI) -> None: + with client.agent.agent.with_streaming_response.list() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + agent = response.parse() + assert_matches_type(ListAgentIdentitiesResponse, agent, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_delete(self, client: OzAPI) -> None: + agent = client.agent.agent.delete( + "uid", + ) + assert agent is None + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_delete(self, client: OzAPI) -> None: + response = client.agent.agent.with_raw_response.delete( + "uid", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + agent = response.parse() + assert agent is None + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_delete(self, client: OzAPI) -> None: + with client.agent.agent.with_streaming_response.delete( + "uid", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + agent = response.parse() + assert agent is None + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_path_params_delete(self, client: OzAPI) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `uid` but received ''"): + client.agent.agent.with_raw_response.delete( + "", + ) + + +class TestAsyncAgent: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_create(self, async_client: AsyncOzAPI) -> None: + agent = await async_client.agent.agent.create( + name="name", + ) + assert_matches_type(AgentResponse, agent, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_create(self, async_client: AsyncOzAPI) -> None: + response = await async_client.agent.agent.with_raw_response.create( + name="name", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + agent = await response.parse() + assert_matches_type(AgentResponse, agent, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_create(self, async_client: AsyncOzAPI) -> None: + async with async_client.agent.agent.with_streaming_response.create( + name="name", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + agent = await response.parse() + assert_matches_type(AgentResponse, agent, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_update(self, async_client: AsyncOzAPI) -> None: + agent = await async_client.agent.agent.update( + uid="uid", + ) + assert_matches_type(AgentResponse, agent, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_update_with_all_params(self, async_client: AsyncOzAPI) -> None: + agent = await async_client.agent.agent.update( + uid="uid", + name="name", + ) + assert_matches_type(AgentResponse, agent, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_update(self, async_client: AsyncOzAPI) -> None: + response = await async_client.agent.agent.with_raw_response.update( + uid="uid", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + agent = await response.parse() + assert_matches_type(AgentResponse, agent, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_update(self, async_client: AsyncOzAPI) -> None: + async with async_client.agent.agent.with_streaming_response.update( + uid="uid", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + agent = await response.parse() + assert_matches_type(AgentResponse, agent, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_path_params_update(self, async_client: AsyncOzAPI) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `uid` but received ''"): + await async_client.agent.agent.with_raw_response.update( + uid="", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_list(self, async_client: AsyncOzAPI) -> None: + agent = await async_client.agent.agent.list() + assert_matches_type(ListAgentIdentitiesResponse, agent, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_list(self, async_client: AsyncOzAPI) -> None: + response = await async_client.agent.agent.with_raw_response.list() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + agent = await response.parse() + assert_matches_type(ListAgentIdentitiesResponse, agent, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_list(self, async_client: AsyncOzAPI) -> None: + async with async_client.agent.agent.with_streaming_response.list() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + agent = await response.parse() + assert_matches_type(ListAgentIdentitiesResponse, agent, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_delete(self, async_client: AsyncOzAPI) -> None: + agent = await async_client.agent.agent.delete( + "uid", + ) + assert agent is None + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_delete(self, async_client: AsyncOzAPI) -> None: + response = await async_client.agent.agent.with_raw_response.delete( + "uid", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + agent = await response.parse() + assert agent is None + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_delete(self, async_client: AsyncOzAPI) -> None: + async with async_client.agent.agent.with_streaming_response.delete( + "uid", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + agent = await response.parse() + assert agent is None + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_path_params_delete(self, async_client: AsyncOzAPI) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `uid` but received ''"): + await async_client.agent.agent.with_raw_response.delete( + "", + ) From e19c37d4e58f2fb986300c8136208997fac112e1 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 17 Apr 2026 20:16:18 +0000 Subject: [PATCH 21/56] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index f4077c2..fd4484e 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 19 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta%2Fwarp-api-d8d008dde648ff6cf158203be9805315cf281f1f354a81bfc38c3eaf58952999.yml -openapi_spec_hash: 4e16bd26f8ac5f53ca2e663aabc6a1d1 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta%2Fwarp-api-caba3084bc4ae52a6847df96dd0f8fe0a3b2bc9801ff4d2935092ae7e2c794f7.yml +openapi_spec_hash: d3dd12a5a9bffb132239a2a206890602 config_hash: c5fc921cc04f541a85f92299f365eba6 From 7808d6b2ceec43e444fd3dbcc59d0719038f8796 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 21 Apr 2026 16:25:12 +0000 Subject: [PATCH 22/56] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index fd4484e..13fbe4a 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 19 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta%2Fwarp-api-caba3084bc4ae52a6847df96dd0f8fe0a3b2bc9801ff4d2935092ae7e2c794f7.yml -openapi_spec_hash: d3dd12a5a9bffb132239a2a206890602 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta%2Fwarp-api-4db59eaf2017b748c39a5690eeec7d7a4c37b6358c46c9223c4e4fb03e7d6897.yml +openapi_spec_hash: e0d929d48abff1f167b0d7c034b430de config_hash: c5fc921cc04f541a85f92299f365eba6 From df940e09b23d2cc3d314407a8826f722b9428dca Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 21 Apr 2026 19:45:28 +0000 Subject: [PATCH 23/56] feat: Add API support for public access on oz session link --- .stats.yml | 4 +-- .../types/ambient_agent_config.py | 34 ++++++++++++++++++- .../types/ambient_agent_config_param.py | 34 ++++++++++++++++++- tests/api_resources/agent/test_schedules.py | 4 +++ tests/api_resources/test_agent.py | 2 ++ 5 files changed, 74 insertions(+), 4 deletions(-) diff --git a/.stats.yml b/.stats.yml index 13fbe4a..5651ce9 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 19 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta%2Fwarp-api-4db59eaf2017b748c39a5690eeec7d7a4c37b6358c46c9223c4e4fb03e7d6897.yml -openapi_spec_hash: e0d929d48abff1f167b0d7c034b430de +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta%2Fwarp-api-a3668b4e18010f399c438348f52d536f65eb30027149e8860fa0c92242e19027.yml +openapi_spec_hash: 5a89788631afcdccbdc361645c9a6c80 config_hash: c5fc921cc04f541a85f92299f365eba6 diff --git a/src/oz_agent_sdk/types/ambient_agent_config.py b/src/oz_agent_sdk/types/ambient_agent_config.py index 69eaf3a..4ef39e6 100644 --- a/src/oz_agent_sdk/types/ambient_agent_config.py +++ b/src/oz_agent_sdk/types/ambient_agent_config.py @@ -8,7 +8,7 @@ from .._models import BaseModel from .mcp_server_config import McpServerConfig -__all__ = ["AmbientAgentConfig", "Harness", "HarnessAuthSecrets"] +__all__ = ["AmbientAgentConfig", "Harness", "HarnessAuthSecrets", "SessionSharing"] class Harness(BaseModel): @@ -39,6 +39,28 @@ class HarnessAuthSecrets(BaseModel): """ +class SessionSharing(BaseModel): + """ + Configures sharing behavior for the run's shared session. + When set, the worker emits `--share public:` and the bundled Warp + client applies an anyone-with-link ACL to the shared session once it has + bootstrapped. The same ACL is mirrored onto the backing conversation so + link viewers can read the conversation without being on the run's team. + Subject to the workspace-level anyone-with-link sharing setting. + """ + + public_access: Optional[Literal["VIEWER", "EDITOR"]] = None + """ + Grants anyone-with-link access at the specified level to the run's shared + session and backing conversation. + + - VIEWER: link viewers can read the session and conversation. + - EDITOR: link viewers can also interact with the session. Anonymous + (unauthenticated) reads are not supported in this release; link viewers must + still be authenticated Warp users. + """ + + class AmbientAgentConfig(BaseModel): """Configuration for a cloud agent run""" @@ -87,6 +109,16 @@ class AmbientAgentConfig(BaseModel): and track them via the name query parameter on GET /agent/runs. """ + session_sharing: Optional[SessionSharing] = None + """ + Configures sharing behavior for the run's shared session. When set, the worker + emits `--share public:` and the bundled Warp client applies an + anyone-with-link ACL to the shared session once it has bootstrapped. The same + ACL is mirrored onto the backing conversation so link viewers can read the + conversation without being on the run's team. Subject to the workspace-level + anyone-with-link sharing setting. + """ + skill_spec: Optional[str] = None """ Skill specification identifying which agent skill to use. Format: diff --git a/src/oz_agent_sdk/types/ambient_agent_config_param.py b/src/oz_agent_sdk/types/ambient_agent_config_param.py index 8ea7901..fd61d3d 100644 --- a/src/oz_agent_sdk/types/ambient_agent_config_param.py +++ b/src/oz_agent_sdk/types/ambient_agent_config_param.py @@ -7,7 +7,7 @@ from .mcp_server_config_param import McpServerConfigParam -__all__ = ["AmbientAgentConfigParam", "Harness", "HarnessAuthSecrets"] +__all__ = ["AmbientAgentConfigParam", "Harness", "HarnessAuthSecrets", "SessionSharing"] class Harness(TypedDict, total=False): @@ -38,6 +38,28 @@ class HarnessAuthSecrets(TypedDict, total=False): """ +class SessionSharing(TypedDict, total=False): + """ + Configures sharing behavior for the run's shared session. + When set, the worker emits `--share public:` and the bundled Warp + client applies an anyone-with-link ACL to the shared session once it has + bootstrapped. The same ACL is mirrored onto the backing conversation so + link viewers can read the conversation without being on the run's team. + Subject to the workspace-level anyone-with-link sharing setting. + """ + + public_access: Literal["VIEWER", "EDITOR"] + """ + Grants anyone-with-link access at the specified level to the run's shared + session and backing conversation. + + - VIEWER: link viewers can read the session and conversation. + - EDITOR: link viewers can also interact with the session. Anonymous + (unauthenticated) reads are not supported in this release; link viewers must + still be authenticated Warp users. + """ + + class AmbientAgentConfigParam(TypedDict, total=False): """Configuration for a cloud agent run""" @@ -86,6 +108,16 @@ class AmbientAgentConfigParam(TypedDict, total=False): and track them via the name query parameter on GET /agent/runs. """ + session_sharing: SessionSharing + """ + Configures sharing behavior for the run's shared session. When set, the worker + emits `--share public:` and the bundled Warp client applies an + anyone-with-link ACL to the shared session once it has bootstrapped. The same + ACL is mirrored onto the backing conversation so link viewers can read the + conversation without being on the run's team. Subject to the workspace-level + anyone-with-link sharing setting. + """ + skill_spec: str """ Skill specification identifying which agent skill to use. Format: diff --git a/tests/api_resources/agent/test_schedules.py b/tests/api_resources/agent/test_schedules.py index 51fbae1..a4818ee 100644 --- a/tests/api_resources/agent/test_schedules.py +++ b/tests/api_resources/agent/test_schedules.py @@ -55,6 +55,7 @@ def test_method_create_with_all_params(self, client: OzAPI) -> None: }, "model_id": "model_id", "name": "name", + "session_sharing": {"public_access": "VIEWER"}, "skill_spec": "skill_spec", "worker_host": "worker_host", }, @@ -172,6 +173,7 @@ def test_method_update_with_all_params(self, client: OzAPI) -> None: }, "model_id": "model_id", "name": "name", + "session_sharing": {"public_access": "VIEWER"}, "skill_spec": "skill_spec", "worker_host": "worker_host", }, @@ -416,6 +418,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncOzAPI) -> }, "model_id": "model_id", "name": "name", + "session_sharing": {"public_access": "VIEWER"}, "skill_spec": "skill_spec", "worker_host": "worker_host", }, @@ -533,6 +536,7 @@ async def test_method_update_with_all_params(self, async_client: AsyncOzAPI) -> }, "model_id": "model_id", "name": "name", + "session_sharing": {"public_access": "VIEWER"}, "skill_spec": "skill_spec", "worker_host": "worker_host", }, diff --git a/tests/api_resources/test_agent.py b/tests/api_resources/test_agent.py index 7f628ef..78b54a4 100644 --- a/tests/api_resources/test_agent.py +++ b/tests/api_resources/test_agent.py @@ -176,6 +176,7 @@ def test_method_run_with_all_params(self, client: OzAPI) -> None: }, "model_id": "model_id", "name": "name", + "session_sharing": {"public_access": "VIEWER"}, "skill_spec": "skill_spec", "worker_host": "worker_host", }, @@ -371,6 +372,7 @@ async def test_method_run_with_all_params(self, async_client: AsyncOzAPI) -> Non }, "model_id": "model_id", "name": "name", + "session_sharing": {"public_access": "VIEWER"}, "skill_spec": "skill_spec", "worker_host": "worker_host", }, From e5aea2192017b1758d7b32d1e855015ce29e93ca Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 21 Apr 2026 21:25:56 +0000 Subject: [PATCH 24/56] feat(api): api update --- .stats.yml | 4 +-- .../types/ambient_agent_config.py | 34 +------------------ .../types/ambient_agent_config_param.py | 34 +------------------ tests/api_resources/agent/test_schedules.py | 4 --- tests/api_resources/test_agent.py | 2 -- 5 files changed, 4 insertions(+), 74 deletions(-) diff --git a/.stats.yml b/.stats.yml index 5651ce9..fd4484e 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 19 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta%2Fwarp-api-a3668b4e18010f399c438348f52d536f65eb30027149e8860fa0c92242e19027.yml -openapi_spec_hash: 5a89788631afcdccbdc361645c9a6c80 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta%2Fwarp-api-caba3084bc4ae52a6847df96dd0f8fe0a3b2bc9801ff4d2935092ae7e2c794f7.yml +openapi_spec_hash: d3dd12a5a9bffb132239a2a206890602 config_hash: c5fc921cc04f541a85f92299f365eba6 diff --git a/src/oz_agent_sdk/types/ambient_agent_config.py b/src/oz_agent_sdk/types/ambient_agent_config.py index 4ef39e6..69eaf3a 100644 --- a/src/oz_agent_sdk/types/ambient_agent_config.py +++ b/src/oz_agent_sdk/types/ambient_agent_config.py @@ -8,7 +8,7 @@ from .._models import BaseModel from .mcp_server_config import McpServerConfig -__all__ = ["AmbientAgentConfig", "Harness", "HarnessAuthSecrets", "SessionSharing"] +__all__ = ["AmbientAgentConfig", "Harness", "HarnessAuthSecrets"] class Harness(BaseModel): @@ -39,28 +39,6 @@ class HarnessAuthSecrets(BaseModel): """ -class SessionSharing(BaseModel): - """ - Configures sharing behavior for the run's shared session. - When set, the worker emits `--share public:` and the bundled Warp - client applies an anyone-with-link ACL to the shared session once it has - bootstrapped. The same ACL is mirrored onto the backing conversation so - link viewers can read the conversation without being on the run's team. - Subject to the workspace-level anyone-with-link sharing setting. - """ - - public_access: Optional[Literal["VIEWER", "EDITOR"]] = None - """ - Grants anyone-with-link access at the specified level to the run's shared - session and backing conversation. - - - VIEWER: link viewers can read the session and conversation. - - EDITOR: link viewers can also interact with the session. Anonymous - (unauthenticated) reads are not supported in this release; link viewers must - still be authenticated Warp users. - """ - - class AmbientAgentConfig(BaseModel): """Configuration for a cloud agent run""" @@ -109,16 +87,6 @@ class AmbientAgentConfig(BaseModel): and track them via the name query parameter on GET /agent/runs. """ - session_sharing: Optional[SessionSharing] = None - """ - Configures sharing behavior for the run's shared session. When set, the worker - emits `--share public:` and the bundled Warp client applies an - anyone-with-link ACL to the shared session once it has bootstrapped. The same - ACL is mirrored onto the backing conversation so link viewers can read the - conversation without being on the run's team. Subject to the workspace-level - anyone-with-link sharing setting. - """ - skill_spec: Optional[str] = None """ Skill specification identifying which agent skill to use. Format: diff --git a/src/oz_agent_sdk/types/ambient_agent_config_param.py b/src/oz_agent_sdk/types/ambient_agent_config_param.py index fd61d3d..8ea7901 100644 --- a/src/oz_agent_sdk/types/ambient_agent_config_param.py +++ b/src/oz_agent_sdk/types/ambient_agent_config_param.py @@ -7,7 +7,7 @@ from .mcp_server_config_param import McpServerConfigParam -__all__ = ["AmbientAgentConfigParam", "Harness", "HarnessAuthSecrets", "SessionSharing"] +__all__ = ["AmbientAgentConfigParam", "Harness", "HarnessAuthSecrets"] class Harness(TypedDict, total=False): @@ -38,28 +38,6 @@ class HarnessAuthSecrets(TypedDict, total=False): """ -class SessionSharing(TypedDict, total=False): - """ - Configures sharing behavior for the run's shared session. - When set, the worker emits `--share public:` and the bundled Warp - client applies an anyone-with-link ACL to the shared session once it has - bootstrapped. The same ACL is mirrored onto the backing conversation so - link viewers can read the conversation without being on the run's team. - Subject to the workspace-level anyone-with-link sharing setting. - """ - - public_access: Literal["VIEWER", "EDITOR"] - """ - Grants anyone-with-link access at the specified level to the run's shared - session and backing conversation. - - - VIEWER: link viewers can read the session and conversation. - - EDITOR: link viewers can also interact with the session. Anonymous - (unauthenticated) reads are not supported in this release; link viewers must - still be authenticated Warp users. - """ - - class AmbientAgentConfigParam(TypedDict, total=False): """Configuration for a cloud agent run""" @@ -108,16 +86,6 @@ class AmbientAgentConfigParam(TypedDict, total=False): and track them via the name query parameter on GET /agent/runs. """ - session_sharing: SessionSharing - """ - Configures sharing behavior for the run's shared session. When set, the worker - emits `--share public:` and the bundled Warp client applies an - anyone-with-link ACL to the shared session once it has bootstrapped. The same - ACL is mirrored onto the backing conversation so link viewers can read the - conversation without being on the run's team. Subject to the workspace-level - anyone-with-link sharing setting. - """ - skill_spec: str """ Skill specification identifying which agent skill to use. Format: diff --git a/tests/api_resources/agent/test_schedules.py b/tests/api_resources/agent/test_schedules.py index a4818ee..51fbae1 100644 --- a/tests/api_resources/agent/test_schedules.py +++ b/tests/api_resources/agent/test_schedules.py @@ -55,7 +55,6 @@ def test_method_create_with_all_params(self, client: OzAPI) -> None: }, "model_id": "model_id", "name": "name", - "session_sharing": {"public_access": "VIEWER"}, "skill_spec": "skill_spec", "worker_host": "worker_host", }, @@ -173,7 +172,6 @@ def test_method_update_with_all_params(self, client: OzAPI) -> None: }, "model_id": "model_id", "name": "name", - "session_sharing": {"public_access": "VIEWER"}, "skill_spec": "skill_spec", "worker_host": "worker_host", }, @@ -418,7 +416,6 @@ async def test_method_create_with_all_params(self, async_client: AsyncOzAPI) -> }, "model_id": "model_id", "name": "name", - "session_sharing": {"public_access": "VIEWER"}, "skill_spec": "skill_spec", "worker_host": "worker_host", }, @@ -536,7 +533,6 @@ async def test_method_update_with_all_params(self, async_client: AsyncOzAPI) -> }, "model_id": "model_id", "name": "name", - "session_sharing": {"public_access": "VIEWER"}, "skill_spec": "skill_spec", "worker_host": "worker_host", }, diff --git a/tests/api_resources/test_agent.py b/tests/api_resources/test_agent.py index 78b54a4..7f628ef 100644 --- a/tests/api_resources/test_agent.py +++ b/tests/api_resources/test_agent.py @@ -176,7 +176,6 @@ def test_method_run_with_all_params(self, client: OzAPI) -> None: }, "model_id": "model_id", "name": "name", - "session_sharing": {"public_access": "VIEWER"}, "skill_spec": "skill_spec", "worker_host": "worker_host", }, @@ -372,7 +371,6 @@ async def test_method_run_with_all_params(self, async_client: AsyncOzAPI) -> Non }, "model_id": "model_id", "name": "name", - "session_sharing": {"public_access": "VIEWER"}, "skill_spec": "skill_spec", "worker_host": "worker_host", }, From e24ba644c9d3624019f240fd43f51079adf7d8d4 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 21 Apr 2026 21:33:43 +0000 Subject: [PATCH 25/56] feat(api): api update --- .stats.yml | 4 +-- .../types/ambient_agent_config.py | 34 ++++++++++++++++++- .../types/ambient_agent_config_param.py | 34 ++++++++++++++++++- tests/api_resources/agent/test_schedules.py | 4 +++ tests/api_resources/test_agent.py | 2 ++ 5 files changed, 74 insertions(+), 4 deletions(-) diff --git a/.stats.yml b/.stats.yml index fd4484e..54a3931 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 19 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta%2Fwarp-api-caba3084bc4ae52a6847df96dd0f8fe0a3b2bc9801ff4d2935092ae7e2c794f7.yml -openapi_spec_hash: d3dd12a5a9bffb132239a2a206890602 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta%2Fwarp-api-256ff5878e3bbb3164f39342087829f5114c1918d51212668fe8a1f9c8151e4a.yml +openapi_spec_hash: 900f64d8c755ef60e047b63fe23ace66 config_hash: c5fc921cc04f541a85f92299f365eba6 diff --git a/src/oz_agent_sdk/types/ambient_agent_config.py b/src/oz_agent_sdk/types/ambient_agent_config.py index 69eaf3a..4ef39e6 100644 --- a/src/oz_agent_sdk/types/ambient_agent_config.py +++ b/src/oz_agent_sdk/types/ambient_agent_config.py @@ -8,7 +8,7 @@ from .._models import BaseModel from .mcp_server_config import McpServerConfig -__all__ = ["AmbientAgentConfig", "Harness", "HarnessAuthSecrets"] +__all__ = ["AmbientAgentConfig", "Harness", "HarnessAuthSecrets", "SessionSharing"] class Harness(BaseModel): @@ -39,6 +39,28 @@ class HarnessAuthSecrets(BaseModel): """ +class SessionSharing(BaseModel): + """ + Configures sharing behavior for the run's shared session. + When set, the worker emits `--share public:` and the bundled Warp + client applies an anyone-with-link ACL to the shared session once it has + bootstrapped. The same ACL is mirrored onto the backing conversation so + link viewers can read the conversation without being on the run's team. + Subject to the workspace-level anyone-with-link sharing setting. + """ + + public_access: Optional[Literal["VIEWER", "EDITOR"]] = None + """ + Grants anyone-with-link access at the specified level to the run's shared + session and backing conversation. + + - VIEWER: link viewers can read the session and conversation. + - EDITOR: link viewers can also interact with the session. Anonymous + (unauthenticated) reads are not supported in this release; link viewers must + still be authenticated Warp users. + """ + + class AmbientAgentConfig(BaseModel): """Configuration for a cloud agent run""" @@ -87,6 +109,16 @@ class AmbientAgentConfig(BaseModel): and track them via the name query parameter on GET /agent/runs. """ + session_sharing: Optional[SessionSharing] = None + """ + Configures sharing behavior for the run's shared session. When set, the worker + emits `--share public:` and the bundled Warp client applies an + anyone-with-link ACL to the shared session once it has bootstrapped. The same + ACL is mirrored onto the backing conversation so link viewers can read the + conversation without being on the run's team. Subject to the workspace-level + anyone-with-link sharing setting. + """ + skill_spec: Optional[str] = None """ Skill specification identifying which agent skill to use. Format: diff --git a/src/oz_agent_sdk/types/ambient_agent_config_param.py b/src/oz_agent_sdk/types/ambient_agent_config_param.py index 8ea7901..fd61d3d 100644 --- a/src/oz_agent_sdk/types/ambient_agent_config_param.py +++ b/src/oz_agent_sdk/types/ambient_agent_config_param.py @@ -7,7 +7,7 @@ from .mcp_server_config_param import McpServerConfigParam -__all__ = ["AmbientAgentConfigParam", "Harness", "HarnessAuthSecrets"] +__all__ = ["AmbientAgentConfigParam", "Harness", "HarnessAuthSecrets", "SessionSharing"] class Harness(TypedDict, total=False): @@ -38,6 +38,28 @@ class HarnessAuthSecrets(TypedDict, total=False): """ +class SessionSharing(TypedDict, total=False): + """ + Configures sharing behavior for the run's shared session. + When set, the worker emits `--share public:` and the bundled Warp + client applies an anyone-with-link ACL to the shared session once it has + bootstrapped. The same ACL is mirrored onto the backing conversation so + link viewers can read the conversation without being on the run's team. + Subject to the workspace-level anyone-with-link sharing setting. + """ + + public_access: Literal["VIEWER", "EDITOR"] + """ + Grants anyone-with-link access at the specified level to the run's shared + session and backing conversation. + + - VIEWER: link viewers can read the session and conversation. + - EDITOR: link viewers can also interact with the session. Anonymous + (unauthenticated) reads are not supported in this release; link viewers must + still be authenticated Warp users. + """ + + class AmbientAgentConfigParam(TypedDict, total=False): """Configuration for a cloud agent run""" @@ -86,6 +108,16 @@ class AmbientAgentConfigParam(TypedDict, total=False): and track them via the name query parameter on GET /agent/runs. """ + session_sharing: SessionSharing + """ + Configures sharing behavior for the run's shared session. When set, the worker + emits `--share public:` and the bundled Warp client applies an + anyone-with-link ACL to the shared session once it has bootstrapped. The same + ACL is mirrored onto the backing conversation so link viewers can read the + conversation without being on the run's team. Subject to the workspace-level + anyone-with-link sharing setting. + """ + skill_spec: str """ Skill specification identifying which agent skill to use. Format: diff --git a/tests/api_resources/agent/test_schedules.py b/tests/api_resources/agent/test_schedules.py index 51fbae1..a4818ee 100644 --- a/tests/api_resources/agent/test_schedules.py +++ b/tests/api_resources/agent/test_schedules.py @@ -55,6 +55,7 @@ def test_method_create_with_all_params(self, client: OzAPI) -> None: }, "model_id": "model_id", "name": "name", + "session_sharing": {"public_access": "VIEWER"}, "skill_spec": "skill_spec", "worker_host": "worker_host", }, @@ -172,6 +173,7 @@ def test_method_update_with_all_params(self, client: OzAPI) -> None: }, "model_id": "model_id", "name": "name", + "session_sharing": {"public_access": "VIEWER"}, "skill_spec": "skill_spec", "worker_host": "worker_host", }, @@ -416,6 +418,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncOzAPI) -> }, "model_id": "model_id", "name": "name", + "session_sharing": {"public_access": "VIEWER"}, "skill_spec": "skill_spec", "worker_host": "worker_host", }, @@ -533,6 +536,7 @@ async def test_method_update_with_all_params(self, async_client: AsyncOzAPI) -> }, "model_id": "model_id", "name": "name", + "session_sharing": {"public_access": "VIEWER"}, "skill_spec": "skill_spec", "worker_host": "worker_host", }, diff --git a/tests/api_resources/test_agent.py b/tests/api_resources/test_agent.py index 7f628ef..78b54a4 100644 --- a/tests/api_resources/test_agent.py +++ b/tests/api_resources/test_agent.py @@ -176,6 +176,7 @@ def test_method_run_with_all_params(self, client: OzAPI) -> None: }, "model_id": "model_id", "name": "name", + "session_sharing": {"public_access": "VIEWER"}, "skill_spec": "skill_spec", "worker_host": "worker_host", }, @@ -371,6 +372,7 @@ async def test_method_run_with_all_params(self, async_client: AsyncOzAPI) -> Non }, "model_id": "model_id", "name": "name", + "session_sharing": {"public_access": "VIEWER"}, "skill_spec": "skill_spec", "worker_host": "worker_host", }, From 27c80e953bc19de56ea730b0c2170aa8ffbc495a Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 22 Apr 2026 14:03:01 +0000 Subject: [PATCH 26/56] chore(internal): more robust bootstrap script --- scripts/bootstrap | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/bootstrap b/scripts/bootstrap index 4638ec6..5a23841 100755 --- a/scripts/bootstrap +++ b/scripts/bootstrap @@ -4,7 +4,7 @@ set -e cd "$(dirname "$0")/.." -if [ -f "Brewfile" ] && [ "$(uname -s)" = "Darwin" ] && [ "$SKIP_BREW" != "1" ] && [ -t 0 ]; then +if [ -f "Brewfile" ] && [ "$(uname -s)" = "Darwin" ] && [ "${SKIP_BREW:-}" != "1" ] && [ -t 0 ]; then brew bundle check >/dev/null 2>&1 || { echo -n "==> Install Homebrew dependencies? (y/N): " read -r response From 0128722383f87f6d5a73fd0ecafc4206a3013342 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 22 Apr 2026 23:35:32 +0000 Subject: [PATCH 27/56] feat: Add Gemini as a third-party Oz harness. --- .stats.yml | 4 ++-- src/oz_agent_sdk/types/ambient_agent_config.py | 3 ++- src/oz_agent_sdk/types/ambient_agent_config_param.py | 3 ++- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/.stats.yml b/.stats.yml index 54a3931..caf5a6c 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 19 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta%2Fwarp-api-256ff5878e3bbb3164f39342087829f5114c1918d51212668fe8a1f9c8151e4a.yml -openapi_spec_hash: 900f64d8c755ef60e047b63fe23ace66 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta%2Fwarp-api-45c55f7358f117c3291cb54717a97ccb1e7a55691a9cb7541d13064b630030ee.yml +openapi_spec_hash: b50f477080595c2f0b9b4378b2ac774a config_hash: c5fc921cc04f541a85f92299f365eba6 diff --git a/src/oz_agent_sdk/types/ambient_agent_config.py b/src/oz_agent_sdk/types/ambient_agent_config.py index 4ef39e6..b90112c 100644 --- a/src/oz_agent_sdk/types/ambient_agent_config.py +++ b/src/oz_agent_sdk/types/ambient_agent_config.py @@ -17,11 +17,12 @@ class Harness(BaseModel): Default (nil/empty) uses Warp's built-in harness. """ - type: Optional[Literal["oz", "claude"]] = None + type: Optional[Literal["oz", "claude", "gemini"]] = None """The harness type identifier. - oz: Warp's built-in harness (default) - claude: Claude Code harness + - gemini: Gemini CLI harness """ diff --git a/src/oz_agent_sdk/types/ambient_agent_config_param.py b/src/oz_agent_sdk/types/ambient_agent_config_param.py index fd61d3d..9031e46 100644 --- a/src/oz_agent_sdk/types/ambient_agent_config_param.py +++ b/src/oz_agent_sdk/types/ambient_agent_config_param.py @@ -16,11 +16,12 @@ class Harness(TypedDict, total=False): Default (nil/empty) uses Warp's built-in harness. """ - type: Literal["oz", "claude"] + type: Literal["oz", "claude", "gemini"] """The harness type identifier. - oz: Warp's built-in harness (default) - claude: Claude Code harness + - gemini: Gemini CLI harness """ From e045b1accd3bbb22578b9838e23f53fd89094f4b Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 23 Apr 2026 17:25:45 +0000 Subject: [PATCH 28/56] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index caf5a6c..c09cf00 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 19 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta%2Fwarp-api-45c55f7358f117c3291cb54717a97ccb1e7a55691a9cb7541d13064b630030ee.yml -openapi_spec_hash: b50f477080595c2f0b9b4378b2ac774a +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta%2Fwarp-api-348bf98eecccd80255fdcee166b5eb385d8d9743811d080f94a1ec33337abc48.yml +openapi_spec_hash: e192bff5e5b54b3a763136e6cbd70e76 config_hash: c5fc921cc04f541a85f92299f365eba6 From eb873a6092aa1792ca6c23f5d27a7ee66c225ea0 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 23 Apr 2026 17:31:55 +0000 Subject: [PATCH 29/56] feat: implement server-side cloud-to-cloud handoff for agent follow-ups (REMOTE-1290) --- .stats.yml | 8 +- api.md | 3 + src/oz_agent_sdk/resources/agent/runs.py | 189 +++++++++++++++++- src/oz_agent_sdk/types/agent/__init__.py | 4 + .../run_list_handoff_attachments_response.py | 33 +++ .../types/agent/run_submit_followup_params.py | 12 ++ tests/api_resources/agent/test_runs.py | 181 ++++++++++++++++- 7 files changed, 423 insertions(+), 7 deletions(-) create mode 100644 src/oz_agent_sdk/types/agent/run_list_handoff_attachments_response.py create mode 100644 src/oz_agent_sdk/types/agent/run_submit_followup_params.py diff --git a/.stats.yml b/.stats.yml index c09cf00..c37cbba 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 19 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta%2Fwarp-api-348bf98eecccd80255fdcee166b5eb385d8d9743811d080f94a1ec33337abc48.yml -openapi_spec_hash: e192bff5e5b54b3a763136e6cbd70e76 -config_hash: c5fc921cc04f541a85f92299f365eba6 +configured_endpoints: 21 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta%2Fwarp-api-ba0eb0c9006df2bc1ad77d365586cdcc4ae62565aff5a7b746ba613fb3fe0889.yml +openapi_spec_hash: 3ed3c07bf50eba4f02cbbbed358f5761 +config_hash: b893614299dd99b07446072ade3737d1 diff --git a/api.md b/api.md index 918ca45..e2fa926 100644 --- a/api.md +++ b/api.md @@ -40,6 +40,7 @@ from oz_agent_sdk.types.agent import ( RunSourceType, RunState, RunCancelResponse, + RunListHandoffAttachmentsResponse, ) ``` @@ -48,6 +49,8 @@ Methods: - client.agent.runs.retrieve(run_id) -> RunItem - client.agent.runs.list(\*\*params) -> SyncRunsCursorPage[RunItem] - client.agent.runs.cancel(run_id) -> str +- client.agent.runs.list_handoff_attachments(run_id) -> RunListHandoffAttachmentsResponse +- client.agent.runs.submit_followup(run_id, \*\*params) -> object ## Schedules diff --git a/src/oz_agent_sdk/resources/agent/runs.py b/src/oz_agent_sdk/resources/agent/runs.py index 00c3f49..95893df 100644 --- a/src/oz_agent_sdk/resources/agent/runs.py +++ b/src/oz_agent_sdk/resources/agent/runs.py @@ -9,7 +9,7 @@ import httpx from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given -from ..._utils import path_template, maybe_transform +from ..._utils import path_template, maybe_transform, async_maybe_transform from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource from ..._response import ( @@ -19,11 +19,12 @@ async_to_streamed_response_wrapper, ) from ...pagination import SyncRunsCursorPage, AsyncRunsCursorPage -from ...types.agent import RunSourceType, run_list_params +from ...types.agent import RunSourceType, run_list_params, run_submit_followup_params from ..._base_client import AsyncPaginator, make_request_options from ...types.agent.run_item import RunItem from ...types.agent.run_state import RunState from ...types.agent.run_source_type import RunSourceType +from ...types.agent.run_list_handoff_attachments_response import RunListHandoffAttachmentsResponse __all__ = ["RunsResource", "AsyncRunsResource"] @@ -252,6 +253,86 @@ def cancel( cast_to=str, ) + def list_handoff_attachments( + self, + run_id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> RunListHandoffAttachmentsResponse: + """ + Return fresh presigned download URLs for handoff snapshot files uploaded by the + latest ended execution of this run. An empty list is returned when no ended + execution exists or no snapshot files were uploaded. + + This endpoint is useful for third-party harnesses that want to download the + snapshot files produced by a previous execution before starting a handoff + execution themselves. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not run_id: + raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}") + return self._get( + path_template("/agent/runs/{run_id}/handoff/attachments", run_id=run_id), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=RunListHandoffAttachmentsResponse, + ) + + def submit_followup( + self, + run_id: str, + *, + message: str, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> object: + """Send a follow-up message to an existing run. + + The server transparently routes the + message based on the current state of the run (still queued, actively running, + or ended). A 200 response means the follow-up was accepted; updated run state + can be observed via `GET /agent/runs/{runId}`. + + Args: + message: The follow-up message to send to the run. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not run_id: + raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}") + return self._post( + path_template("/agent/runs/{run_id}/followups", run_id=run_id), + body=maybe_transform({"message": message}, run_submit_followup_params.RunSubmitFollowupParams), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=object, + ) + class AsyncRunsResource(AsyncAPIResource): """Operations for running and managing cloud agents""" @@ -477,6 +558,86 @@ async def cancel( cast_to=str, ) + async def list_handoff_attachments( + self, + run_id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> RunListHandoffAttachmentsResponse: + """ + Return fresh presigned download URLs for handoff snapshot files uploaded by the + latest ended execution of this run. An empty list is returned when no ended + execution exists or no snapshot files were uploaded. + + This endpoint is useful for third-party harnesses that want to download the + snapshot files produced by a previous execution before starting a handoff + execution themselves. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not run_id: + raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}") + return await self._get( + path_template("/agent/runs/{run_id}/handoff/attachments", run_id=run_id), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=RunListHandoffAttachmentsResponse, + ) + + async def submit_followup( + self, + run_id: str, + *, + message: str, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> object: + """Send a follow-up message to an existing run. + + The server transparently routes the + message based on the current state of the run (still queued, actively running, + or ended). A 200 response means the follow-up was accepted; updated run state + can be observed via `GET /agent/runs/{runId}`. + + Args: + message: The follow-up message to send to the run. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not run_id: + raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}") + return await self._post( + path_template("/agent/runs/{run_id}/followups", run_id=run_id), + body=await async_maybe_transform({"message": message}, run_submit_followup_params.RunSubmitFollowupParams), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=object, + ) + class RunsResourceWithRawResponse: def __init__(self, runs: RunsResource) -> None: @@ -491,6 +652,12 @@ def __init__(self, runs: RunsResource) -> None: self.cancel = to_raw_response_wrapper( runs.cancel, ) + self.list_handoff_attachments = to_raw_response_wrapper( + runs.list_handoff_attachments, + ) + self.submit_followup = to_raw_response_wrapper( + runs.submit_followup, + ) class AsyncRunsResourceWithRawResponse: @@ -506,6 +673,12 @@ def __init__(self, runs: AsyncRunsResource) -> None: self.cancel = async_to_raw_response_wrapper( runs.cancel, ) + self.list_handoff_attachments = async_to_raw_response_wrapper( + runs.list_handoff_attachments, + ) + self.submit_followup = async_to_raw_response_wrapper( + runs.submit_followup, + ) class RunsResourceWithStreamingResponse: @@ -521,6 +694,12 @@ def __init__(self, runs: RunsResource) -> None: self.cancel = to_streamed_response_wrapper( runs.cancel, ) + self.list_handoff_attachments = to_streamed_response_wrapper( + runs.list_handoff_attachments, + ) + self.submit_followup = to_streamed_response_wrapper( + runs.submit_followup, + ) class AsyncRunsResourceWithStreamingResponse: @@ -536,3 +715,9 @@ def __init__(self, runs: AsyncRunsResource) -> None: self.cancel = async_to_streamed_response_wrapper( runs.cancel, ) + self.list_handoff_attachments = async_to_streamed_response_wrapper( + runs.list_handoff_attachments, + ) + self.submit_followup = async_to_streamed_response_wrapper( + runs.submit_followup, + ) diff --git a/src/oz_agent_sdk/types/agent/__init__.py b/src/oz_agent_sdk/types/agent/__init__.py index ca0f9d8..899793d 100644 --- a/src/oz_agent_sdk/types/agent/__init__.py +++ b/src/oz_agent_sdk/types/agent/__init__.py @@ -16,6 +16,10 @@ from .schedule_list_response import ScheduleListResponse as ScheduleListResponse from .schedule_update_params import ScheduleUpdateParams as ScheduleUpdateParams from .schedule_delete_response import ScheduleDeleteResponse as ScheduleDeleteResponse +from .run_submit_followup_params import RunSubmitFollowupParams as RunSubmitFollowupParams from .scheduled_agent_history_item import ScheduledAgentHistoryItem as ScheduledAgentHistoryItem from .list_agent_identities_response import ListAgentIdentitiesResponse as ListAgentIdentitiesResponse from .session_check_redirect_response import SessionCheckRedirectResponse as SessionCheckRedirectResponse +from .run_list_handoff_attachments_response import ( + RunListHandoffAttachmentsResponse as RunListHandoffAttachmentsResponse, +) diff --git a/src/oz_agent_sdk/types/agent/run_list_handoff_attachments_response.py b/src/oz_agent_sdk/types/agent/run_list_handoff_attachments_response.py new file mode 100644 index 0000000..b3ac5b8 --- /dev/null +++ b/src/oz_agent_sdk/types/agent/run_list_handoff_attachments_response.py @@ -0,0 +1,33 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional + +from ..._models import BaseModel + +__all__ = ["RunListHandoffAttachmentsResponse", "Attachment"] + + +class Attachment(BaseModel): + """A handoff snapshot attachment exposed for download.""" + + attachment_id: str + """Identifier for the snapshot attachment within the run.""" + + download_url: str + """Time-limited signed URL to download the snapshot attachment.""" + + filename: str + """Original filename of the snapshot attachment.""" + + mime_type: Optional[str] = None + """MIME type of the snapshot attachment, if known.""" + + +class RunListHandoffAttachmentsResponse(BaseModel): + """Response body for listing handoff snapshot attachments.""" + + attachments: List[Attachment] + """ + Handoff snapshot attachments exposed by the latest ended execution. Empty when + no ended execution exists or no files were uploaded. + """ diff --git a/src/oz_agent_sdk/types/agent/run_submit_followup_params.py b/src/oz_agent_sdk/types/agent/run_submit_followup_params.py new file mode 100644 index 0000000..4912cd1 --- /dev/null +++ b/src/oz_agent_sdk/types/agent/run_submit_followup_params.py @@ -0,0 +1,12 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Required, TypedDict + +__all__ = ["RunSubmitFollowupParams"] + + +class RunSubmitFollowupParams(TypedDict, total=False): + message: Required[str] + """The follow-up message to send to the run.""" diff --git a/tests/api_resources/agent/test_runs.py b/tests/api_resources/agent/test_runs.py index cf95a65..55b95bb 100644 --- a/tests/api_resources/agent/test_runs.py +++ b/tests/api_resources/agent/test_runs.py @@ -11,7 +11,10 @@ from oz_agent_sdk import OzAPI, AsyncOzAPI from oz_agent_sdk._utils import parse_datetime from oz_agent_sdk.pagination import SyncRunsCursorPage, AsyncRunsCursorPage -from oz_agent_sdk.types.agent import RunItem +from oz_agent_sdk.types.agent import ( + RunItem, + RunListHandoffAttachmentsResponse, +) base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") @@ -158,6 +161,94 @@ def test_path_params_cancel(self, client: OzAPI) -> None: "", ) + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_list_handoff_attachments(self, client: OzAPI) -> None: + run = client.agent.runs.list_handoff_attachments( + "runId", + ) + assert_matches_type(RunListHandoffAttachmentsResponse, run, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_list_handoff_attachments(self, client: OzAPI) -> None: + response = client.agent.runs.with_raw_response.list_handoff_attachments( + "runId", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + run = response.parse() + assert_matches_type(RunListHandoffAttachmentsResponse, run, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_list_handoff_attachments(self, client: OzAPI) -> None: + with client.agent.runs.with_streaming_response.list_handoff_attachments( + "runId", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + run = response.parse() + assert_matches_type(RunListHandoffAttachmentsResponse, run, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_path_params_list_handoff_attachments(self, client: OzAPI) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `run_id` but received ''"): + client.agent.runs.with_raw_response.list_handoff_attachments( + "", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_submit_followup(self, client: OzAPI) -> None: + run = client.agent.runs.submit_followup( + run_id="runId", + message="message", + ) + assert_matches_type(object, run, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_submit_followup(self, client: OzAPI) -> None: + response = client.agent.runs.with_raw_response.submit_followup( + run_id="runId", + message="message", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + run = response.parse() + assert_matches_type(object, run, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_submit_followup(self, client: OzAPI) -> None: + with client.agent.runs.with_streaming_response.submit_followup( + run_id="runId", + message="message", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + run = response.parse() + assert_matches_type(object, run, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_path_params_submit_followup(self, client: OzAPI) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `run_id` but received ''"): + client.agent.runs.with_raw_response.submit_followup( + run_id="", + message="message", + ) + class TestAsyncRuns: parametrize = pytest.mark.parametrize( @@ -302,3 +393,91 @@ async def test_path_params_cancel(self, async_client: AsyncOzAPI) -> None: await async_client.agent.runs.with_raw_response.cancel( "", ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_list_handoff_attachments(self, async_client: AsyncOzAPI) -> None: + run = await async_client.agent.runs.list_handoff_attachments( + "runId", + ) + assert_matches_type(RunListHandoffAttachmentsResponse, run, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_list_handoff_attachments(self, async_client: AsyncOzAPI) -> None: + response = await async_client.agent.runs.with_raw_response.list_handoff_attachments( + "runId", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + run = await response.parse() + assert_matches_type(RunListHandoffAttachmentsResponse, run, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_list_handoff_attachments(self, async_client: AsyncOzAPI) -> None: + async with async_client.agent.runs.with_streaming_response.list_handoff_attachments( + "runId", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + run = await response.parse() + assert_matches_type(RunListHandoffAttachmentsResponse, run, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_path_params_list_handoff_attachments(self, async_client: AsyncOzAPI) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `run_id` but received ''"): + await async_client.agent.runs.with_raw_response.list_handoff_attachments( + "", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_submit_followup(self, async_client: AsyncOzAPI) -> None: + run = await async_client.agent.runs.submit_followup( + run_id="runId", + message="message", + ) + assert_matches_type(object, run, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_submit_followup(self, async_client: AsyncOzAPI) -> None: + response = await async_client.agent.runs.with_raw_response.submit_followup( + run_id="runId", + message="message", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + run = await response.parse() + assert_matches_type(object, run, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_submit_followup(self, async_client: AsyncOzAPI) -> None: + async with async_client.agent.runs.with_streaming_response.submit_followup( + run_id="runId", + message="message", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + run = await response.parse() + assert_matches_type(object, run, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_path_params_submit_followup(self, async_client: AsyncOzAPI) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `run_id` but received ''"): + await async_client.agent.runs.with_raw_response.submit_followup( + run_id="", + message="message", + ) From a8500aa0b3e74221cd931b01d7e7569ad191d1f3 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 23 Apr 2026 18:21:58 +0000 Subject: [PATCH 30/56] feat: Accept and persist executor on schedule and integration create/update APIs --- .stats.yml | 4 ++-- src/oz_agent_sdk/resources/agent/schedules.py | 20 +++++++++++++++++++ .../types/agent/schedule_create_params.py | 6 ++++++ .../types/agent/schedule_update_params.py | 6 ++++++ tests/api_resources/agent/test_schedules.py | 4 ++++ 5 files changed, 38 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index c37cbba..ebdcb69 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 21 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta%2Fwarp-api-ba0eb0c9006df2bc1ad77d365586cdcc4ae62565aff5a7b746ba613fb3fe0889.yml -openapi_spec_hash: 3ed3c07bf50eba4f02cbbbed358f5761 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta%2Fwarp-api-0610670bab7ee6c6c6630c94cf22162d57784544b4ff3acd7f1b9a9b405f71b4.yml +openapi_spec_hash: 53fed4f8bfe081ebe46f892dd6f1f501 config_hash: b893614299dd99b07446072ade3737d1 diff --git a/src/oz_agent_sdk/resources/agent/schedules.py b/src/oz_agent_sdk/resources/agent/schedules.py index f9fbac0..b29a979 100644 --- a/src/oz_agent_sdk/resources/agent/schedules.py +++ b/src/oz_agent_sdk/resources/agent/schedules.py @@ -52,6 +52,7 @@ def create( cron_schedule: str, name: str, agent_config: AmbientAgentConfigParam | Omit = omit, + agent_uid: str | Omit = omit, enabled: bool | Omit = omit, prompt: str | Omit = omit, team: bool | Omit = omit, @@ -75,6 +76,9 @@ def create( agent_config: Configuration for a cloud agent run + agent_uid: Agent UID to use as the execution principal for this schedule. Only valid for + team-owned schedules. + enabled: Whether the schedule should be active immediately prompt: The prompt/instruction for the agent to execute. Required unless @@ -98,6 +102,7 @@ def create( "cron_schedule": cron_schedule, "name": name, "agent_config": agent_config, + "agent_uid": agent_uid, "enabled": enabled, "prompt": prompt, "team": team, @@ -152,6 +157,7 @@ def update( enabled: bool, name: str, agent_config: AmbientAgentConfigParam | Omit = omit, + agent_uid: str | Omit = omit, prompt: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. @@ -174,6 +180,9 @@ def update( agent_config: Configuration for a cloud agent run + agent_uid: Agent UID to use as the execution principal for this schedule. Only valid for + team-owned schedules. + prompt: The prompt/instruction for the agent to execute. Required unless agent_config.skill_spec is provided. @@ -195,6 +204,7 @@ def update( "enabled": enabled, "name": name, "agent_config": agent_config, + "agent_uid": agent_uid, "prompt": prompt, }, schedule_update_params.ScheduleUpdateParams, @@ -360,6 +370,7 @@ async def create( cron_schedule: str, name: str, agent_config: AmbientAgentConfigParam | Omit = omit, + agent_uid: str | Omit = omit, enabled: bool | Omit = omit, prompt: str | Omit = omit, team: bool | Omit = omit, @@ -383,6 +394,9 @@ async def create( agent_config: Configuration for a cloud agent run + agent_uid: Agent UID to use as the execution principal for this schedule. Only valid for + team-owned schedules. + enabled: Whether the schedule should be active immediately prompt: The prompt/instruction for the agent to execute. Required unless @@ -406,6 +420,7 @@ async def create( "cron_schedule": cron_schedule, "name": name, "agent_config": agent_config, + "agent_uid": agent_uid, "enabled": enabled, "prompt": prompt, "team": team, @@ -460,6 +475,7 @@ async def update( enabled: bool, name: str, agent_config: AmbientAgentConfigParam | Omit = omit, + agent_uid: str | Omit = omit, prompt: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. @@ -482,6 +498,9 @@ async def update( agent_config: Configuration for a cloud agent run + agent_uid: Agent UID to use as the execution principal for this schedule. Only valid for + team-owned schedules. + prompt: The prompt/instruction for the agent to execute. Required unless agent_config.skill_spec is provided. @@ -503,6 +522,7 @@ async def update( "enabled": enabled, "name": name, "agent_config": agent_config, + "agent_uid": agent_uid, "prompt": prompt, }, schedule_update_params.ScheduleUpdateParams, diff --git a/src/oz_agent_sdk/types/agent/schedule_create_params.py b/src/oz_agent_sdk/types/agent/schedule_create_params.py index e94a3b3..8958fd0 100644 --- a/src/oz_agent_sdk/types/agent/schedule_create_params.py +++ b/src/oz_agent_sdk/types/agent/schedule_create_params.py @@ -22,6 +22,12 @@ class ScheduleCreateParams(TypedDict, total=False): agent_config: AmbientAgentConfigParam """Configuration for a cloud agent run""" + agent_uid: str + """ + Agent UID to use as the execution principal for this schedule. Only valid for + team-owned schedules. + """ + enabled: bool """Whether the schedule should be active immediately""" diff --git a/src/oz_agent_sdk/types/agent/schedule_update_params.py b/src/oz_agent_sdk/types/agent/schedule_update_params.py index 2c82454..de71dc9 100644 --- a/src/oz_agent_sdk/types/agent/schedule_update_params.py +++ b/src/oz_agent_sdk/types/agent/schedule_update_params.py @@ -22,6 +22,12 @@ class ScheduleUpdateParams(TypedDict, total=False): agent_config: AmbientAgentConfigParam """Configuration for a cloud agent run""" + agent_uid: str + """ + Agent UID to use as the execution principal for this schedule. Only valid for + team-owned schedules. + """ + prompt: str """ The prompt/instruction for the agent to execute. Required unless diff --git a/tests/api_resources/agent/test_schedules.py b/tests/api_resources/agent/test_schedules.py index a4818ee..b37e9bc 100644 --- a/tests/api_resources/agent/test_schedules.py +++ b/tests/api_resources/agent/test_schedules.py @@ -59,6 +59,7 @@ def test_method_create_with_all_params(self, client: OzAPI) -> None: "skill_spec": "skill_spec", "worker_host": "worker_host", }, + agent_uid="agent_uid", enabled=True, prompt="Review open pull requests and provide feedback", team=True, @@ -177,6 +178,7 @@ def test_method_update_with_all_params(self, client: OzAPI) -> None: "skill_spec": "skill_spec", "worker_host": "worker_host", }, + agent_uid="agent_uid", prompt="prompt", ) assert_matches_type(ScheduledAgentItem, schedule, path=["response"]) @@ -422,6 +424,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncOzAPI) -> "skill_spec": "skill_spec", "worker_host": "worker_host", }, + agent_uid="agent_uid", enabled=True, prompt="Review open pull requests and provide feedback", team=True, @@ -540,6 +543,7 @@ async def test_method_update_with_all_params(self, async_client: AsyncOzAPI) -> "skill_spec": "skill_spec", "worker_host": "worker_host", }, + agent_uid="agent_uid", prompt="prompt", ) assert_matches_type(ScheduledAgentItem, schedule, path=["response"]) From a44c455cb949e69b05f33f38571b40d9c0caed36 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 23 Apr 2026 22:00:40 +0000 Subject: [PATCH 31/56] feat(api): api update --- .stats.yml | 8 +- api.md | 3 - src/oz_agent_sdk/resources/agent/runs.py | 189 +----------------- src/oz_agent_sdk/resources/agent/schedules.py | 20 -- src/oz_agent_sdk/types/agent/__init__.py | 4 - .../run_list_handoff_attachments_response.py | 33 --- .../types/agent/run_submit_followup_params.py | 12 -- .../types/agent/schedule_create_params.py | 6 - .../types/agent/schedule_update_params.py | 6 - tests/api_resources/agent/test_runs.py | 181 +---------------- tests/api_resources/agent/test_schedules.py | 4 - 11 files changed, 7 insertions(+), 459 deletions(-) delete mode 100644 src/oz_agent_sdk/types/agent/run_list_handoff_attachments_response.py delete mode 100644 src/oz_agent_sdk/types/agent/run_submit_followup_params.py diff --git a/.stats.yml b/.stats.yml index ebdcb69..c09cf00 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 21 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta%2Fwarp-api-0610670bab7ee6c6c6630c94cf22162d57784544b4ff3acd7f1b9a9b405f71b4.yml -openapi_spec_hash: 53fed4f8bfe081ebe46f892dd6f1f501 -config_hash: b893614299dd99b07446072ade3737d1 +configured_endpoints: 19 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta%2Fwarp-api-348bf98eecccd80255fdcee166b5eb385d8d9743811d080f94a1ec33337abc48.yml +openapi_spec_hash: e192bff5e5b54b3a763136e6cbd70e76 +config_hash: c5fc921cc04f541a85f92299f365eba6 diff --git a/api.md b/api.md index e2fa926..918ca45 100644 --- a/api.md +++ b/api.md @@ -40,7 +40,6 @@ from oz_agent_sdk.types.agent import ( RunSourceType, RunState, RunCancelResponse, - RunListHandoffAttachmentsResponse, ) ``` @@ -49,8 +48,6 @@ Methods: - client.agent.runs.retrieve(run_id) -> RunItem - client.agent.runs.list(\*\*params) -> SyncRunsCursorPage[RunItem] - client.agent.runs.cancel(run_id) -> str -- client.agent.runs.list_handoff_attachments(run_id) -> RunListHandoffAttachmentsResponse -- client.agent.runs.submit_followup(run_id, \*\*params) -> object ## Schedules diff --git a/src/oz_agent_sdk/resources/agent/runs.py b/src/oz_agent_sdk/resources/agent/runs.py index 95893df..00c3f49 100644 --- a/src/oz_agent_sdk/resources/agent/runs.py +++ b/src/oz_agent_sdk/resources/agent/runs.py @@ -9,7 +9,7 @@ import httpx from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given -from ..._utils import path_template, maybe_transform, async_maybe_transform +from ..._utils import path_template, maybe_transform from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource from ..._response import ( @@ -19,12 +19,11 @@ async_to_streamed_response_wrapper, ) from ...pagination import SyncRunsCursorPage, AsyncRunsCursorPage -from ...types.agent import RunSourceType, run_list_params, run_submit_followup_params +from ...types.agent import RunSourceType, run_list_params from ..._base_client import AsyncPaginator, make_request_options from ...types.agent.run_item import RunItem from ...types.agent.run_state import RunState from ...types.agent.run_source_type import RunSourceType -from ...types.agent.run_list_handoff_attachments_response import RunListHandoffAttachmentsResponse __all__ = ["RunsResource", "AsyncRunsResource"] @@ -253,86 +252,6 @@ def cancel( cast_to=str, ) - def list_handoff_attachments( - self, - run_id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> RunListHandoffAttachmentsResponse: - """ - Return fresh presigned download URLs for handoff snapshot files uploaded by the - latest ended execution of this run. An empty list is returned when no ended - execution exists or no snapshot files were uploaded. - - This endpoint is useful for third-party harnesses that want to download the - snapshot files produced by a previous execution before starting a handoff - execution themselves. - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not run_id: - raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}") - return self._get( - path_template("/agent/runs/{run_id}/handoff/attachments", run_id=run_id), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=RunListHandoffAttachmentsResponse, - ) - - def submit_followup( - self, - run_id: str, - *, - message: str, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> object: - """Send a follow-up message to an existing run. - - The server transparently routes the - message based on the current state of the run (still queued, actively running, - or ended). A 200 response means the follow-up was accepted; updated run state - can be observed via `GET /agent/runs/{runId}`. - - Args: - message: The follow-up message to send to the run. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not run_id: - raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}") - return self._post( - path_template("/agent/runs/{run_id}/followups", run_id=run_id), - body=maybe_transform({"message": message}, run_submit_followup_params.RunSubmitFollowupParams), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=object, - ) - class AsyncRunsResource(AsyncAPIResource): """Operations for running and managing cloud agents""" @@ -558,86 +477,6 @@ async def cancel( cast_to=str, ) - async def list_handoff_attachments( - self, - run_id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> RunListHandoffAttachmentsResponse: - """ - Return fresh presigned download URLs for handoff snapshot files uploaded by the - latest ended execution of this run. An empty list is returned when no ended - execution exists or no snapshot files were uploaded. - - This endpoint is useful for third-party harnesses that want to download the - snapshot files produced by a previous execution before starting a handoff - execution themselves. - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not run_id: - raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}") - return await self._get( - path_template("/agent/runs/{run_id}/handoff/attachments", run_id=run_id), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=RunListHandoffAttachmentsResponse, - ) - - async def submit_followup( - self, - run_id: str, - *, - message: str, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> object: - """Send a follow-up message to an existing run. - - The server transparently routes the - message based on the current state of the run (still queued, actively running, - or ended). A 200 response means the follow-up was accepted; updated run state - can be observed via `GET /agent/runs/{runId}`. - - Args: - message: The follow-up message to send to the run. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not run_id: - raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}") - return await self._post( - path_template("/agent/runs/{run_id}/followups", run_id=run_id), - body=await async_maybe_transform({"message": message}, run_submit_followup_params.RunSubmitFollowupParams), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=object, - ) - class RunsResourceWithRawResponse: def __init__(self, runs: RunsResource) -> None: @@ -652,12 +491,6 @@ def __init__(self, runs: RunsResource) -> None: self.cancel = to_raw_response_wrapper( runs.cancel, ) - self.list_handoff_attachments = to_raw_response_wrapper( - runs.list_handoff_attachments, - ) - self.submit_followup = to_raw_response_wrapper( - runs.submit_followup, - ) class AsyncRunsResourceWithRawResponse: @@ -673,12 +506,6 @@ def __init__(self, runs: AsyncRunsResource) -> None: self.cancel = async_to_raw_response_wrapper( runs.cancel, ) - self.list_handoff_attachments = async_to_raw_response_wrapper( - runs.list_handoff_attachments, - ) - self.submit_followup = async_to_raw_response_wrapper( - runs.submit_followup, - ) class RunsResourceWithStreamingResponse: @@ -694,12 +521,6 @@ def __init__(self, runs: RunsResource) -> None: self.cancel = to_streamed_response_wrapper( runs.cancel, ) - self.list_handoff_attachments = to_streamed_response_wrapper( - runs.list_handoff_attachments, - ) - self.submit_followup = to_streamed_response_wrapper( - runs.submit_followup, - ) class AsyncRunsResourceWithStreamingResponse: @@ -715,9 +536,3 @@ def __init__(self, runs: AsyncRunsResource) -> None: self.cancel = async_to_streamed_response_wrapper( runs.cancel, ) - self.list_handoff_attachments = async_to_streamed_response_wrapper( - runs.list_handoff_attachments, - ) - self.submit_followup = async_to_streamed_response_wrapper( - runs.submit_followup, - ) diff --git a/src/oz_agent_sdk/resources/agent/schedules.py b/src/oz_agent_sdk/resources/agent/schedules.py index b29a979..f9fbac0 100644 --- a/src/oz_agent_sdk/resources/agent/schedules.py +++ b/src/oz_agent_sdk/resources/agent/schedules.py @@ -52,7 +52,6 @@ def create( cron_schedule: str, name: str, agent_config: AmbientAgentConfigParam | Omit = omit, - agent_uid: str | Omit = omit, enabled: bool | Omit = omit, prompt: str | Omit = omit, team: bool | Omit = omit, @@ -76,9 +75,6 @@ def create( agent_config: Configuration for a cloud agent run - agent_uid: Agent UID to use as the execution principal for this schedule. Only valid for - team-owned schedules. - enabled: Whether the schedule should be active immediately prompt: The prompt/instruction for the agent to execute. Required unless @@ -102,7 +98,6 @@ def create( "cron_schedule": cron_schedule, "name": name, "agent_config": agent_config, - "agent_uid": agent_uid, "enabled": enabled, "prompt": prompt, "team": team, @@ -157,7 +152,6 @@ def update( enabled: bool, name: str, agent_config: AmbientAgentConfigParam | Omit = omit, - agent_uid: str | Omit = omit, prompt: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. @@ -180,9 +174,6 @@ def update( agent_config: Configuration for a cloud agent run - agent_uid: Agent UID to use as the execution principal for this schedule. Only valid for - team-owned schedules. - prompt: The prompt/instruction for the agent to execute. Required unless agent_config.skill_spec is provided. @@ -204,7 +195,6 @@ def update( "enabled": enabled, "name": name, "agent_config": agent_config, - "agent_uid": agent_uid, "prompt": prompt, }, schedule_update_params.ScheduleUpdateParams, @@ -370,7 +360,6 @@ async def create( cron_schedule: str, name: str, agent_config: AmbientAgentConfigParam | Omit = omit, - agent_uid: str | Omit = omit, enabled: bool | Omit = omit, prompt: str | Omit = omit, team: bool | Omit = omit, @@ -394,9 +383,6 @@ async def create( agent_config: Configuration for a cloud agent run - agent_uid: Agent UID to use as the execution principal for this schedule. Only valid for - team-owned schedules. - enabled: Whether the schedule should be active immediately prompt: The prompt/instruction for the agent to execute. Required unless @@ -420,7 +406,6 @@ async def create( "cron_schedule": cron_schedule, "name": name, "agent_config": agent_config, - "agent_uid": agent_uid, "enabled": enabled, "prompt": prompt, "team": team, @@ -475,7 +460,6 @@ async def update( enabled: bool, name: str, agent_config: AmbientAgentConfigParam | Omit = omit, - agent_uid: str | Omit = omit, prompt: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. @@ -498,9 +482,6 @@ async def update( agent_config: Configuration for a cloud agent run - agent_uid: Agent UID to use as the execution principal for this schedule. Only valid for - team-owned schedules. - prompt: The prompt/instruction for the agent to execute. Required unless agent_config.skill_spec is provided. @@ -522,7 +503,6 @@ async def update( "enabled": enabled, "name": name, "agent_config": agent_config, - "agent_uid": agent_uid, "prompt": prompt, }, schedule_update_params.ScheduleUpdateParams, diff --git a/src/oz_agent_sdk/types/agent/__init__.py b/src/oz_agent_sdk/types/agent/__init__.py index 899793d..ca0f9d8 100644 --- a/src/oz_agent_sdk/types/agent/__init__.py +++ b/src/oz_agent_sdk/types/agent/__init__.py @@ -16,10 +16,6 @@ from .schedule_list_response import ScheduleListResponse as ScheduleListResponse from .schedule_update_params import ScheduleUpdateParams as ScheduleUpdateParams from .schedule_delete_response import ScheduleDeleteResponse as ScheduleDeleteResponse -from .run_submit_followup_params import RunSubmitFollowupParams as RunSubmitFollowupParams from .scheduled_agent_history_item import ScheduledAgentHistoryItem as ScheduledAgentHistoryItem from .list_agent_identities_response import ListAgentIdentitiesResponse as ListAgentIdentitiesResponse from .session_check_redirect_response import SessionCheckRedirectResponse as SessionCheckRedirectResponse -from .run_list_handoff_attachments_response import ( - RunListHandoffAttachmentsResponse as RunListHandoffAttachmentsResponse, -) diff --git a/src/oz_agent_sdk/types/agent/run_list_handoff_attachments_response.py b/src/oz_agent_sdk/types/agent/run_list_handoff_attachments_response.py deleted file mode 100644 index b3ac5b8..0000000 --- a/src/oz_agent_sdk/types/agent/run_list_handoff_attachments_response.py +++ /dev/null @@ -1,33 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import List, Optional - -from ..._models import BaseModel - -__all__ = ["RunListHandoffAttachmentsResponse", "Attachment"] - - -class Attachment(BaseModel): - """A handoff snapshot attachment exposed for download.""" - - attachment_id: str - """Identifier for the snapshot attachment within the run.""" - - download_url: str - """Time-limited signed URL to download the snapshot attachment.""" - - filename: str - """Original filename of the snapshot attachment.""" - - mime_type: Optional[str] = None - """MIME type of the snapshot attachment, if known.""" - - -class RunListHandoffAttachmentsResponse(BaseModel): - """Response body for listing handoff snapshot attachments.""" - - attachments: List[Attachment] - """ - Handoff snapshot attachments exposed by the latest ended execution. Empty when - no ended execution exists or no files were uploaded. - """ diff --git a/src/oz_agent_sdk/types/agent/run_submit_followup_params.py b/src/oz_agent_sdk/types/agent/run_submit_followup_params.py deleted file mode 100644 index 4912cd1..0000000 --- a/src/oz_agent_sdk/types/agent/run_submit_followup_params.py +++ /dev/null @@ -1,12 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing_extensions import Required, TypedDict - -__all__ = ["RunSubmitFollowupParams"] - - -class RunSubmitFollowupParams(TypedDict, total=False): - message: Required[str] - """The follow-up message to send to the run.""" diff --git a/src/oz_agent_sdk/types/agent/schedule_create_params.py b/src/oz_agent_sdk/types/agent/schedule_create_params.py index 8958fd0..e94a3b3 100644 --- a/src/oz_agent_sdk/types/agent/schedule_create_params.py +++ b/src/oz_agent_sdk/types/agent/schedule_create_params.py @@ -22,12 +22,6 @@ class ScheduleCreateParams(TypedDict, total=False): agent_config: AmbientAgentConfigParam """Configuration for a cloud agent run""" - agent_uid: str - """ - Agent UID to use as the execution principal for this schedule. Only valid for - team-owned schedules. - """ - enabled: bool """Whether the schedule should be active immediately""" diff --git a/src/oz_agent_sdk/types/agent/schedule_update_params.py b/src/oz_agent_sdk/types/agent/schedule_update_params.py index de71dc9..2c82454 100644 --- a/src/oz_agent_sdk/types/agent/schedule_update_params.py +++ b/src/oz_agent_sdk/types/agent/schedule_update_params.py @@ -22,12 +22,6 @@ class ScheduleUpdateParams(TypedDict, total=False): agent_config: AmbientAgentConfigParam """Configuration for a cloud agent run""" - agent_uid: str - """ - Agent UID to use as the execution principal for this schedule. Only valid for - team-owned schedules. - """ - prompt: str """ The prompt/instruction for the agent to execute. Required unless diff --git a/tests/api_resources/agent/test_runs.py b/tests/api_resources/agent/test_runs.py index 55b95bb..cf95a65 100644 --- a/tests/api_resources/agent/test_runs.py +++ b/tests/api_resources/agent/test_runs.py @@ -11,10 +11,7 @@ from oz_agent_sdk import OzAPI, AsyncOzAPI from oz_agent_sdk._utils import parse_datetime from oz_agent_sdk.pagination import SyncRunsCursorPage, AsyncRunsCursorPage -from oz_agent_sdk.types.agent import ( - RunItem, - RunListHandoffAttachmentsResponse, -) +from oz_agent_sdk.types.agent import RunItem base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") @@ -161,94 +158,6 @@ def test_path_params_cancel(self, client: OzAPI) -> None: "", ) - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_method_list_handoff_attachments(self, client: OzAPI) -> None: - run = client.agent.runs.list_handoff_attachments( - "runId", - ) - assert_matches_type(RunListHandoffAttachmentsResponse, run, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_raw_response_list_handoff_attachments(self, client: OzAPI) -> None: - response = client.agent.runs.with_raw_response.list_handoff_attachments( - "runId", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - run = response.parse() - assert_matches_type(RunListHandoffAttachmentsResponse, run, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_streaming_response_list_handoff_attachments(self, client: OzAPI) -> None: - with client.agent.runs.with_streaming_response.list_handoff_attachments( - "runId", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - run = response.parse() - assert_matches_type(RunListHandoffAttachmentsResponse, run, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_path_params_list_handoff_attachments(self, client: OzAPI) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `run_id` but received ''"): - client.agent.runs.with_raw_response.list_handoff_attachments( - "", - ) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_method_submit_followup(self, client: OzAPI) -> None: - run = client.agent.runs.submit_followup( - run_id="runId", - message="message", - ) - assert_matches_type(object, run, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_raw_response_submit_followup(self, client: OzAPI) -> None: - response = client.agent.runs.with_raw_response.submit_followup( - run_id="runId", - message="message", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - run = response.parse() - assert_matches_type(object, run, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_streaming_response_submit_followup(self, client: OzAPI) -> None: - with client.agent.runs.with_streaming_response.submit_followup( - run_id="runId", - message="message", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - run = response.parse() - assert_matches_type(object, run, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_path_params_submit_followup(self, client: OzAPI) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `run_id` but received ''"): - client.agent.runs.with_raw_response.submit_followup( - run_id="", - message="message", - ) - class TestAsyncRuns: parametrize = pytest.mark.parametrize( @@ -393,91 +302,3 @@ async def test_path_params_cancel(self, async_client: AsyncOzAPI) -> None: await async_client.agent.runs.with_raw_response.cancel( "", ) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_method_list_handoff_attachments(self, async_client: AsyncOzAPI) -> None: - run = await async_client.agent.runs.list_handoff_attachments( - "runId", - ) - assert_matches_type(RunListHandoffAttachmentsResponse, run, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_raw_response_list_handoff_attachments(self, async_client: AsyncOzAPI) -> None: - response = await async_client.agent.runs.with_raw_response.list_handoff_attachments( - "runId", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - run = await response.parse() - assert_matches_type(RunListHandoffAttachmentsResponse, run, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_streaming_response_list_handoff_attachments(self, async_client: AsyncOzAPI) -> None: - async with async_client.agent.runs.with_streaming_response.list_handoff_attachments( - "runId", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - run = await response.parse() - assert_matches_type(RunListHandoffAttachmentsResponse, run, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_path_params_list_handoff_attachments(self, async_client: AsyncOzAPI) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `run_id` but received ''"): - await async_client.agent.runs.with_raw_response.list_handoff_attachments( - "", - ) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_method_submit_followup(self, async_client: AsyncOzAPI) -> None: - run = await async_client.agent.runs.submit_followup( - run_id="runId", - message="message", - ) - assert_matches_type(object, run, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_raw_response_submit_followup(self, async_client: AsyncOzAPI) -> None: - response = await async_client.agent.runs.with_raw_response.submit_followup( - run_id="runId", - message="message", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - run = await response.parse() - assert_matches_type(object, run, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_streaming_response_submit_followup(self, async_client: AsyncOzAPI) -> None: - async with async_client.agent.runs.with_streaming_response.submit_followup( - run_id="runId", - message="message", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - run = await response.parse() - assert_matches_type(object, run, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_path_params_submit_followup(self, async_client: AsyncOzAPI) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `run_id` but received ''"): - await async_client.agent.runs.with_raw_response.submit_followup( - run_id="", - message="message", - ) diff --git a/tests/api_resources/agent/test_schedules.py b/tests/api_resources/agent/test_schedules.py index b37e9bc..a4818ee 100644 --- a/tests/api_resources/agent/test_schedules.py +++ b/tests/api_resources/agent/test_schedules.py @@ -59,7 +59,6 @@ def test_method_create_with_all_params(self, client: OzAPI) -> None: "skill_spec": "skill_spec", "worker_host": "worker_host", }, - agent_uid="agent_uid", enabled=True, prompt="Review open pull requests and provide feedback", team=True, @@ -178,7 +177,6 @@ def test_method_update_with_all_params(self, client: OzAPI) -> None: "skill_spec": "skill_spec", "worker_host": "worker_host", }, - agent_uid="agent_uid", prompt="prompt", ) assert_matches_type(ScheduledAgentItem, schedule, path=["response"]) @@ -424,7 +422,6 @@ async def test_method_create_with_all_params(self, async_client: AsyncOzAPI) -> "skill_spec": "skill_spec", "worker_host": "worker_host", }, - agent_uid="agent_uid", enabled=True, prompt="Review open pull requests and provide feedback", team=True, @@ -543,7 +540,6 @@ async def test_method_update_with_all_params(self, async_client: AsyncOzAPI) -> "skill_spec": "skill_spec", "worker_host": "worker_host", }, - agent_uid="agent_uid", prompt="prompt", ) assert_matches_type(ScheduledAgentItem, schedule, path=["response"]) From f785ff2bafbd319574974549a73c21643cdb5cc5 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 27 Apr 2026 14:58:39 +0000 Subject: [PATCH 32/56] fix: use correct field name format for multipart file arrays --- src/oz_agent_sdk/_qs.py | 8 ++---- src/oz_agent_sdk/_types.py | 3 +++ src/oz_agent_sdk/_utils/_utils.py | 42 +++++++++++++++++++++++++------ tests/test_extract_files.py | 28 +++++++++++++++++---- tests/test_files.py | 2 +- 5 files changed, 63 insertions(+), 20 deletions(-) diff --git a/src/oz_agent_sdk/_qs.py b/src/oz_agent_sdk/_qs.py index de8c99b..4127c19 100644 --- a/src/oz_agent_sdk/_qs.py +++ b/src/oz_agent_sdk/_qs.py @@ -2,17 +2,13 @@ from typing import Any, List, Tuple, Union, Mapping, TypeVar from urllib.parse import parse_qs, urlencode -from typing_extensions import Literal, get_args +from typing_extensions import get_args -from ._types import NotGiven, not_given +from ._types import NotGiven, ArrayFormat, NestedFormat, not_given from ._utils import flatten _T = TypeVar("_T") - -ArrayFormat = Literal["comma", "repeat", "indices", "brackets"] -NestedFormat = Literal["dots", "brackets"] - PrimitiveData = Union[str, int, float, bool, None] # this should be Data = Union[PrimitiveData, "List[Data]", "Tuple[Data]", "Mapping[str, Data]"] # https://github.com/microsoft/pyright/issues/3555 diff --git a/src/oz_agent_sdk/_types.py b/src/oz_agent_sdk/_types.py index cbb7d7e..09db394 100644 --- a/src/oz_agent_sdk/_types.py +++ b/src/oz_agent_sdk/_types.py @@ -47,6 +47,9 @@ ModelT = TypeVar("ModelT", bound=pydantic.BaseModel) _T = TypeVar("_T") +ArrayFormat = Literal["comma", "repeat", "indices", "brackets"] +NestedFormat = Literal["dots", "brackets"] + # Approximates httpx internal ProxiesTypes and RequestFiles types # while adding support for `PathLike` instances diff --git a/src/oz_agent_sdk/_utils/_utils.py b/src/oz_agent_sdk/_utils/_utils.py index 771859f..199cd23 100644 --- a/src/oz_agent_sdk/_utils/_utils.py +++ b/src/oz_agent_sdk/_utils/_utils.py @@ -17,11 +17,11 @@ ) from pathlib import Path from datetime import date, datetime -from typing_extensions import TypeGuard +from typing_extensions import TypeGuard, get_args import sniffio -from .._types import Omit, NotGiven, FileTypes, HeadersLike +from .._types import Omit, NotGiven, FileTypes, ArrayFormat, HeadersLike _T = TypeVar("_T") _TupleT = TypeVar("_TupleT", bound=Tuple[object, ...]) @@ -40,25 +40,45 @@ def extract_files( query: Mapping[str, object], *, paths: Sequence[Sequence[str]], + array_format: ArrayFormat = "brackets", ) -> list[tuple[str, FileTypes]]: """Recursively extract files from the given dictionary based on specified paths. A path may look like this ['foo', 'files', '', 'data']. + ``array_format`` controls how ```` segments contribute to the emitted + field name. Supported values: ``"brackets"`` (``foo[]``), ``"repeat"`` and + ``"comma"`` (``foo``), ``"indices"`` (``foo[0]``, ``foo[1]``). + Note: this mutates the given dictionary. """ files: list[tuple[str, FileTypes]] = [] for path in paths: - files.extend(_extract_items(query, path, index=0, flattened_key=None)) + files.extend(_extract_items(query, path, index=0, flattened_key=None, array_format=array_format)) return files +def _array_suffix(array_format: ArrayFormat, array_index: int) -> str: + if array_format == "brackets": + return "[]" + if array_format == "indices": + return f"[{array_index}]" + if array_format == "repeat" or array_format == "comma": + # Both repeat the bare field name for each file part; there is no + # meaningful way to comma-join binary parts. + return "" + raise NotImplementedError( + f"Unknown array_format value: {array_format}, choose from {', '.join(get_args(ArrayFormat))}" + ) + + def _extract_items( obj: object, path: Sequence[str], *, index: int, flattened_key: str | None, + array_format: ArrayFormat, ) -> list[tuple[str, FileTypes]]: try: key = path[index] @@ -75,9 +95,11 @@ def _extract_items( if is_list(obj): files: list[tuple[str, FileTypes]] = [] - for entry in obj: - assert_is_file_content(entry, key=flattened_key + "[]" if flattened_key else "") - files.append((flattened_key + "[]", cast(FileTypes, entry))) + for array_index, entry in enumerate(obj): + suffix = _array_suffix(array_format, array_index) + emitted_key = (flattened_key + suffix) if flattened_key else suffix + assert_is_file_content(entry, key=emitted_key) + files.append((emitted_key, cast(FileTypes, entry))) return files assert_is_file_content(obj, key=flattened_key) @@ -106,6 +128,7 @@ def _extract_items( path, index=index, flattened_key=flattened_key, + array_format=array_format, ) elif is_list(obj): if key != "": @@ -117,9 +140,12 @@ def _extract_items( item, path, index=index, - flattened_key=flattened_key + "[]" if flattened_key is not None else "[]", + flattened_key=( + (flattened_key if flattened_key is not None else "") + _array_suffix(array_format, array_index) + ), + array_format=array_format, ) - for item in obj + for array_index, item in enumerate(obj) ] ) diff --git a/tests/test_extract_files.py b/tests/test_extract_files.py index f014004..c7d7add 100644 --- a/tests/test_extract_files.py +++ b/tests/test_extract_files.py @@ -4,7 +4,7 @@ import pytest -from oz_agent_sdk._types import FileTypes +from oz_agent_sdk._types import FileTypes, ArrayFormat from oz_agent_sdk._utils import extract_files @@ -37,10 +37,7 @@ def test_multiple_files() -> None: def test_top_level_file_array() -> None: query = {"files": [b"file one", b"file two"], "title": "hello"} - assert extract_files(query, paths=[["files", ""]]) == [ - ("files[]", b"file one"), - ("files[]", b"file two"), - ] + assert extract_files(query, paths=[["files", ""]]) == [("files[]", b"file one"), ("files[]", b"file two")] assert query == {"title": "hello"} @@ -71,3 +68,24 @@ def test_ignores_incorrect_paths( expected: list[tuple[str, FileTypes]], ) -> None: assert extract_files(query, paths=paths) == expected + + +@pytest.mark.parametrize( + "array_format,expected_top_level,expected_nested", + [ + ("brackets", [("files[]", b"a"), ("files[]", b"b")], [("items[][file]", b"a"), ("items[][file]", b"b")]), + ("repeat", [("files", b"a"), ("files", b"b")], [("items[file]", b"a"), ("items[file]", b"b")]), + ("comma", [("files", b"a"), ("files", b"b")], [("items[file]", b"a"), ("items[file]", b"b")]), + ("indices", [("files[0]", b"a"), ("files[1]", b"b")], [("items[0][file]", b"a"), ("items[1][file]", b"b")]), + ], +) +def test_array_format_controls_file_field_names( + array_format: ArrayFormat, + expected_top_level: list[tuple[str, FileTypes]], + expected_nested: list[tuple[str, FileTypes]], +) -> None: + top_level = {"files": [b"a", b"b"]} + assert extract_files(top_level, paths=[["files", ""]], array_format=array_format) == expected_top_level + + nested = {"items": [{"file": b"a"}, {"file": b"b"}]} + assert extract_files(nested, paths=[["items", "", "file"]], array_format=array_format) == expected_nested diff --git a/tests/test_files.py b/tests/test_files.py index 26486e1..393aa1a 100644 --- a/tests/test_files.py +++ b/tests/test_files.py @@ -131,7 +131,7 @@ def test_extract_files_does_not_mutate_original_nested_array_path(self) -> None: copied = deepcopy_with_paths(original, [["items", "", "file"]]) extracted = extract_files(copied, paths=[["items", "", "file"]]) - assert extracted == [("items[][file]", file1), ("items[][file]", file2)] + assert [entry for _, entry in extracted] == [file1, file2] assert original == { "items": [ {"file": file1, "extra": 1}, From ed871aac657265138112d98be757a0de48796e02 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 27 Apr 2026 21:53:21 +0000 Subject: [PATCH 33/56] feat(api): api update --- .stats.yml | 6 +- api.md | 3 + src/oz_agent_sdk/resources/agent/runs.py | 189 +++++++++++++++++- src/oz_agent_sdk/resources/agent/schedules.py | 20 ++ src/oz_agent_sdk/types/agent/__init__.py | 4 + .../run_list_handoff_attachments_response.py | 33 +++ .../types/agent/run_submit_followup_params.py | 12 ++ .../types/agent/schedule_create_params.py | 6 + .../types/agent/schedule_update_params.py | 6 + tests/api_resources/agent/test_runs.py | 181 ++++++++++++++++- tests/api_resources/agent/test_schedules.py | 4 + 11 files changed, 458 insertions(+), 6 deletions(-) create mode 100644 src/oz_agent_sdk/types/agent/run_list_handoff_attachments_response.py create mode 100644 src/oz_agent_sdk/types/agent/run_submit_followup_params.py diff --git a/.stats.yml b/.stats.yml index c09cf00..637bc77 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 19 +configured_endpoints: 21 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta%2Fwarp-api-348bf98eecccd80255fdcee166b5eb385d8d9743811d080f94a1ec33337abc48.yml -openapi_spec_hash: e192bff5e5b54b3a763136e6cbd70e76 -config_hash: c5fc921cc04f541a85f92299f365eba6 +openapi_spec_hash: 5da1dccadb70219c6dfdda1a440b9ad2 +config_hash: b893614299dd99b07446072ade3737d1 diff --git a/api.md b/api.md index 918ca45..e2fa926 100644 --- a/api.md +++ b/api.md @@ -40,6 +40,7 @@ from oz_agent_sdk.types.agent import ( RunSourceType, RunState, RunCancelResponse, + RunListHandoffAttachmentsResponse, ) ``` @@ -48,6 +49,8 @@ Methods: - client.agent.runs.retrieve(run_id) -> RunItem - client.agent.runs.list(\*\*params) -> SyncRunsCursorPage[RunItem] - client.agent.runs.cancel(run_id) -> str +- client.agent.runs.list_handoff_attachments(run_id) -> RunListHandoffAttachmentsResponse +- client.agent.runs.submit_followup(run_id, \*\*params) -> object ## Schedules diff --git a/src/oz_agent_sdk/resources/agent/runs.py b/src/oz_agent_sdk/resources/agent/runs.py index 00c3f49..95893df 100644 --- a/src/oz_agent_sdk/resources/agent/runs.py +++ b/src/oz_agent_sdk/resources/agent/runs.py @@ -9,7 +9,7 @@ import httpx from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given -from ..._utils import path_template, maybe_transform +from ..._utils import path_template, maybe_transform, async_maybe_transform from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource from ..._response import ( @@ -19,11 +19,12 @@ async_to_streamed_response_wrapper, ) from ...pagination import SyncRunsCursorPage, AsyncRunsCursorPage -from ...types.agent import RunSourceType, run_list_params +from ...types.agent import RunSourceType, run_list_params, run_submit_followup_params from ..._base_client import AsyncPaginator, make_request_options from ...types.agent.run_item import RunItem from ...types.agent.run_state import RunState from ...types.agent.run_source_type import RunSourceType +from ...types.agent.run_list_handoff_attachments_response import RunListHandoffAttachmentsResponse __all__ = ["RunsResource", "AsyncRunsResource"] @@ -252,6 +253,86 @@ def cancel( cast_to=str, ) + def list_handoff_attachments( + self, + run_id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> RunListHandoffAttachmentsResponse: + """ + Return fresh presigned download URLs for handoff snapshot files uploaded by the + latest ended execution of this run. An empty list is returned when no ended + execution exists or no snapshot files were uploaded. + + This endpoint is useful for third-party harnesses that want to download the + snapshot files produced by a previous execution before starting a handoff + execution themselves. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not run_id: + raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}") + return self._get( + path_template("/agent/runs/{run_id}/handoff/attachments", run_id=run_id), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=RunListHandoffAttachmentsResponse, + ) + + def submit_followup( + self, + run_id: str, + *, + message: str, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> object: + """Send a follow-up message to an existing run. + + The server transparently routes the + message based on the current state of the run (still queued, actively running, + or ended). A 200 response means the follow-up was accepted; updated run state + can be observed via `GET /agent/runs/{runId}`. + + Args: + message: The follow-up message to send to the run. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not run_id: + raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}") + return self._post( + path_template("/agent/runs/{run_id}/followups", run_id=run_id), + body=maybe_transform({"message": message}, run_submit_followup_params.RunSubmitFollowupParams), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=object, + ) + class AsyncRunsResource(AsyncAPIResource): """Operations for running and managing cloud agents""" @@ -477,6 +558,86 @@ async def cancel( cast_to=str, ) + async def list_handoff_attachments( + self, + run_id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> RunListHandoffAttachmentsResponse: + """ + Return fresh presigned download URLs for handoff snapshot files uploaded by the + latest ended execution of this run. An empty list is returned when no ended + execution exists or no snapshot files were uploaded. + + This endpoint is useful for third-party harnesses that want to download the + snapshot files produced by a previous execution before starting a handoff + execution themselves. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not run_id: + raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}") + return await self._get( + path_template("/agent/runs/{run_id}/handoff/attachments", run_id=run_id), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=RunListHandoffAttachmentsResponse, + ) + + async def submit_followup( + self, + run_id: str, + *, + message: str, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> object: + """Send a follow-up message to an existing run. + + The server transparently routes the + message based on the current state of the run (still queued, actively running, + or ended). A 200 response means the follow-up was accepted; updated run state + can be observed via `GET /agent/runs/{runId}`. + + Args: + message: The follow-up message to send to the run. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not run_id: + raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}") + return await self._post( + path_template("/agent/runs/{run_id}/followups", run_id=run_id), + body=await async_maybe_transform({"message": message}, run_submit_followup_params.RunSubmitFollowupParams), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=object, + ) + class RunsResourceWithRawResponse: def __init__(self, runs: RunsResource) -> None: @@ -491,6 +652,12 @@ def __init__(self, runs: RunsResource) -> None: self.cancel = to_raw_response_wrapper( runs.cancel, ) + self.list_handoff_attachments = to_raw_response_wrapper( + runs.list_handoff_attachments, + ) + self.submit_followup = to_raw_response_wrapper( + runs.submit_followup, + ) class AsyncRunsResourceWithRawResponse: @@ -506,6 +673,12 @@ def __init__(self, runs: AsyncRunsResource) -> None: self.cancel = async_to_raw_response_wrapper( runs.cancel, ) + self.list_handoff_attachments = async_to_raw_response_wrapper( + runs.list_handoff_attachments, + ) + self.submit_followup = async_to_raw_response_wrapper( + runs.submit_followup, + ) class RunsResourceWithStreamingResponse: @@ -521,6 +694,12 @@ def __init__(self, runs: RunsResource) -> None: self.cancel = to_streamed_response_wrapper( runs.cancel, ) + self.list_handoff_attachments = to_streamed_response_wrapper( + runs.list_handoff_attachments, + ) + self.submit_followup = to_streamed_response_wrapper( + runs.submit_followup, + ) class AsyncRunsResourceWithStreamingResponse: @@ -536,3 +715,9 @@ def __init__(self, runs: AsyncRunsResource) -> None: self.cancel = async_to_streamed_response_wrapper( runs.cancel, ) + self.list_handoff_attachments = async_to_streamed_response_wrapper( + runs.list_handoff_attachments, + ) + self.submit_followup = async_to_streamed_response_wrapper( + runs.submit_followup, + ) diff --git a/src/oz_agent_sdk/resources/agent/schedules.py b/src/oz_agent_sdk/resources/agent/schedules.py index f9fbac0..b29a979 100644 --- a/src/oz_agent_sdk/resources/agent/schedules.py +++ b/src/oz_agent_sdk/resources/agent/schedules.py @@ -52,6 +52,7 @@ def create( cron_schedule: str, name: str, agent_config: AmbientAgentConfigParam | Omit = omit, + agent_uid: str | Omit = omit, enabled: bool | Omit = omit, prompt: str | Omit = omit, team: bool | Omit = omit, @@ -75,6 +76,9 @@ def create( agent_config: Configuration for a cloud agent run + agent_uid: Agent UID to use as the execution principal for this schedule. Only valid for + team-owned schedules. + enabled: Whether the schedule should be active immediately prompt: The prompt/instruction for the agent to execute. Required unless @@ -98,6 +102,7 @@ def create( "cron_schedule": cron_schedule, "name": name, "agent_config": agent_config, + "agent_uid": agent_uid, "enabled": enabled, "prompt": prompt, "team": team, @@ -152,6 +157,7 @@ def update( enabled: bool, name: str, agent_config: AmbientAgentConfigParam | Omit = omit, + agent_uid: str | Omit = omit, prompt: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. @@ -174,6 +180,9 @@ def update( agent_config: Configuration for a cloud agent run + agent_uid: Agent UID to use as the execution principal for this schedule. Only valid for + team-owned schedules. + prompt: The prompt/instruction for the agent to execute. Required unless agent_config.skill_spec is provided. @@ -195,6 +204,7 @@ def update( "enabled": enabled, "name": name, "agent_config": agent_config, + "agent_uid": agent_uid, "prompt": prompt, }, schedule_update_params.ScheduleUpdateParams, @@ -360,6 +370,7 @@ async def create( cron_schedule: str, name: str, agent_config: AmbientAgentConfigParam | Omit = omit, + agent_uid: str | Omit = omit, enabled: bool | Omit = omit, prompt: str | Omit = omit, team: bool | Omit = omit, @@ -383,6 +394,9 @@ async def create( agent_config: Configuration for a cloud agent run + agent_uid: Agent UID to use as the execution principal for this schedule. Only valid for + team-owned schedules. + enabled: Whether the schedule should be active immediately prompt: The prompt/instruction for the agent to execute. Required unless @@ -406,6 +420,7 @@ async def create( "cron_schedule": cron_schedule, "name": name, "agent_config": agent_config, + "agent_uid": agent_uid, "enabled": enabled, "prompt": prompt, "team": team, @@ -460,6 +475,7 @@ async def update( enabled: bool, name: str, agent_config: AmbientAgentConfigParam | Omit = omit, + agent_uid: str | Omit = omit, prompt: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. @@ -482,6 +498,9 @@ async def update( agent_config: Configuration for a cloud agent run + agent_uid: Agent UID to use as the execution principal for this schedule. Only valid for + team-owned schedules. + prompt: The prompt/instruction for the agent to execute. Required unless agent_config.skill_spec is provided. @@ -503,6 +522,7 @@ async def update( "enabled": enabled, "name": name, "agent_config": agent_config, + "agent_uid": agent_uid, "prompt": prompt, }, schedule_update_params.ScheduleUpdateParams, diff --git a/src/oz_agent_sdk/types/agent/__init__.py b/src/oz_agent_sdk/types/agent/__init__.py index ca0f9d8..899793d 100644 --- a/src/oz_agent_sdk/types/agent/__init__.py +++ b/src/oz_agent_sdk/types/agent/__init__.py @@ -16,6 +16,10 @@ from .schedule_list_response import ScheduleListResponse as ScheduleListResponse from .schedule_update_params import ScheduleUpdateParams as ScheduleUpdateParams from .schedule_delete_response import ScheduleDeleteResponse as ScheduleDeleteResponse +from .run_submit_followup_params import RunSubmitFollowupParams as RunSubmitFollowupParams from .scheduled_agent_history_item import ScheduledAgentHistoryItem as ScheduledAgentHistoryItem from .list_agent_identities_response import ListAgentIdentitiesResponse as ListAgentIdentitiesResponse from .session_check_redirect_response import SessionCheckRedirectResponse as SessionCheckRedirectResponse +from .run_list_handoff_attachments_response import ( + RunListHandoffAttachmentsResponse as RunListHandoffAttachmentsResponse, +) diff --git a/src/oz_agent_sdk/types/agent/run_list_handoff_attachments_response.py b/src/oz_agent_sdk/types/agent/run_list_handoff_attachments_response.py new file mode 100644 index 0000000..b3ac5b8 --- /dev/null +++ b/src/oz_agent_sdk/types/agent/run_list_handoff_attachments_response.py @@ -0,0 +1,33 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional + +from ..._models import BaseModel + +__all__ = ["RunListHandoffAttachmentsResponse", "Attachment"] + + +class Attachment(BaseModel): + """A handoff snapshot attachment exposed for download.""" + + attachment_id: str + """Identifier for the snapshot attachment within the run.""" + + download_url: str + """Time-limited signed URL to download the snapshot attachment.""" + + filename: str + """Original filename of the snapshot attachment.""" + + mime_type: Optional[str] = None + """MIME type of the snapshot attachment, if known.""" + + +class RunListHandoffAttachmentsResponse(BaseModel): + """Response body for listing handoff snapshot attachments.""" + + attachments: List[Attachment] + """ + Handoff snapshot attachments exposed by the latest ended execution. Empty when + no ended execution exists or no files were uploaded. + """ diff --git a/src/oz_agent_sdk/types/agent/run_submit_followup_params.py b/src/oz_agent_sdk/types/agent/run_submit_followup_params.py new file mode 100644 index 0000000..4912cd1 --- /dev/null +++ b/src/oz_agent_sdk/types/agent/run_submit_followup_params.py @@ -0,0 +1,12 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Required, TypedDict + +__all__ = ["RunSubmitFollowupParams"] + + +class RunSubmitFollowupParams(TypedDict, total=False): + message: Required[str] + """The follow-up message to send to the run.""" diff --git a/src/oz_agent_sdk/types/agent/schedule_create_params.py b/src/oz_agent_sdk/types/agent/schedule_create_params.py index e94a3b3..8958fd0 100644 --- a/src/oz_agent_sdk/types/agent/schedule_create_params.py +++ b/src/oz_agent_sdk/types/agent/schedule_create_params.py @@ -22,6 +22,12 @@ class ScheduleCreateParams(TypedDict, total=False): agent_config: AmbientAgentConfigParam """Configuration for a cloud agent run""" + agent_uid: str + """ + Agent UID to use as the execution principal for this schedule. Only valid for + team-owned schedules. + """ + enabled: bool """Whether the schedule should be active immediately""" diff --git a/src/oz_agent_sdk/types/agent/schedule_update_params.py b/src/oz_agent_sdk/types/agent/schedule_update_params.py index 2c82454..de71dc9 100644 --- a/src/oz_agent_sdk/types/agent/schedule_update_params.py +++ b/src/oz_agent_sdk/types/agent/schedule_update_params.py @@ -22,6 +22,12 @@ class ScheduleUpdateParams(TypedDict, total=False): agent_config: AmbientAgentConfigParam """Configuration for a cloud agent run""" + agent_uid: str + """ + Agent UID to use as the execution principal for this schedule. Only valid for + team-owned schedules. + """ + prompt: str """ The prompt/instruction for the agent to execute. Required unless diff --git a/tests/api_resources/agent/test_runs.py b/tests/api_resources/agent/test_runs.py index cf95a65..55b95bb 100644 --- a/tests/api_resources/agent/test_runs.py +++ b/tests/api_resources/agent/test_runs.py @@ -11,7 +11,10 @@ from oz_agent_sdk import OzAPI, AsyncOzAPI from oz_agent_sdk._utils import parse_datetime from oz_agent_sdk.pagination import SyncRunsCursorPage, AsyncRunsCursorPage -from oz_agent_sdk.types.agent import RunItem +from oz_agent_sdk.types.agent import ( + RunItem, + RunListHandoffAttachmentsResponse, +) base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") @@ -158,6 +161,94 @@ def test_path_params_cancel(self, client: OzAPI) -> None: "", ) + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_list_handoff_attachments(self, client: OzAPI) -> None: + run = client.agent.runs.list_handoff_attachments( + "runId", + ) + assert_matches_type(RunListHandoffAttachmentsResponse, run, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_list_handoff_attachments(self, client: OzAPI) -> None: + response = client.agent.runs.with_raw_response.list_handoff_attachments( + "runId", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + run = response.parse() + assert_matches_type(RunListHandoffAttachmentsResponse, run, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_list_handoff_attachments(self, client: OzAPI) -> None: + with client.agent.runs.with_streaming_response.list_handoff_attachments( + "runId", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + run = response.parse() + assert_matches_type(RunListHandoffAttachmentsResponse, run, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_path_params_list_handoff_attachments(self, client: OzAPI) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `run_id` but received ''"): + client.agent.runs.with_raw_response.list_handoff_attachments( + "", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_submit_followup(self, client: OzAPI) -> None: + run = client.agent.runs.submit_followup( + run_id="runId", + message="message", + ) + assert_matches_type(object, run, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_submit_followup(self, client: OzAPI) -> None: + response = client.agent.runs.with_raw_response.submit_followup( + run_id="runId", + message="message", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + run = response.parse() + assert_matches_type(object, run, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_submit_followup(self, client: OzAPI) -> None: + with client.agent.runs.with_streaming_response.submit_followup( + run_id="runId", + message="message", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + run = response.parse() + assert_matches_type(object, run, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_path_params_submit_followup(self, client: OzAPI) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `run_id` but received ''"): + client.agent.runs.with_raw_response.submit_followup( + run_id="", + message="message", + ) + class TestAsyncRuns: parametrize = pytest.mark.parametrize( @@ -302,3 +393,91 @@ async def test_path_params_cancel(self, async_client: AsyncOzAPI) -> None: await async_client.agent.runs.with_raw_response.cancel( "", ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_list_handoff_attachments(self, async_client: AsyncOzAPI) -> None: + run = await async_client.agent.runs.list_handoff_attachments( + "runId", + ) + assert_matches_type(RunListHandoffAttachmentsResponse, run, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_list_handoff_attachments(self, async_client: AsyncOzAPI) -> None: + response = await async_client.agent.runs.with_raw_response.list_handoff_attachments( + "runId", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + run = await response.parse() + assert_matches_type(RunListHandoffAttachmentsResponse, run, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_list_handoff_attachments(self, async_client: AsyncOzAPI) -> None: + async with async_client.agent.runs.with_streaming_response.list_handoff_attachments( + "runId", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + run = await response.parse() + assert_matches_type(RunListHandoffAttachmentsResponse, run, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_path_params_list_handoff_attachments(self, async_client: AsyncOzAPI) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `run_id` but received ''"): + await async_client.agent.runs.with_raw_response.list_handoff_attachments( + "", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_submit_followup(self, async_client: AsyncOzAPI) -> None: + run = await async_client.agent.runs.submit_followup( + run_id="runId", + message="message", + ) + assert_matches_type(object, run, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_submit_followup(self, async_client: AsyncOzAPI) -> None: + response = await async_client.agent.runs.with_raw_response.submit_followup( + run_id="runId", + message="message", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + run = await response.parse() + assert_matches_type(object, run, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_submit_followup(self, async_client: AsyncOzAPI) -> None: + async with async_client.agent.runs.with_streaming_response.submit_followup( + run_id="runId", + message="message", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + run = await response.parse() + assert_matches_type(object, run, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_path_params_submit_followup(self, async_client: AsyncOzAPI) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `run_id` but received ''"): + await async_client.agent.runs.with_raw_response.submit_followup( + run_id="", + message="message", + ) diff --git a/tests/api_resources/agent/test_schedules.py b/tests/api_resources/agent/test_schedules.py index a4818ee..b37e9bc 100644 --- a/tests/api_resources/agent/test_schedules.py +++ b/tests/api_resources/agent/test_schedules.py @@ -59,6 +59,7 @@ def test_method_create_with_all_params(self, client: OzAPI) -> None: "skill_spec": "skill_spec", "worker_host": "worker_host", }, + agent_uid="agent_uid", enabled=True, prompt="Review open pull requests and provide feedback", team=True, @@ -177,6 +178,7 @@ def test_method_update_with_all_params(self, client: OzAPI) -> None: "skill_spec": "skill_spec", "worker_host": "worker_host", }, + agent_uid="agent_uid", prompt="prompt", ) assert_matches_type(ScheduledAgentItem, schedule, path=["response"]) @@ -422,6 +424,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncOzAPI) -> "skill_spec": "skill_spec", "worker_host": "worker_host", }, + agent_uid="agent_uid", enabled=True, prompt="Review open pull requests and provide feedback", team=True, @@ -540,6 +543,7 @@ async def test_method_update_with_all_params(self, async_client: AsyncOzAPI) -> "skill_spec": "skill_spec", "worker_host": "worker_host", }, + agent_uid="agent_uid", prompt="prompt", ) assert_matches_type(ScheduledAgentItem, schedule, path=["response"]) From d3b4755c7447d915a4e11be043b21b859f6c028d Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 27 Apr 2026 22:25:36 +0000 Subject: [PATCH 34/56] feat: support setting headers via env --- src/oz_agent_sdk/_client.py | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/oz_agent_sdk/_client.py b/src/oz_agent_sdk/_client.py index 81603d2..949709b 100644 --- a/src/oz_agent_sdk/_client.py +++ b/src/oz_agent_sdk/_client.py @@ -19,7 +19,11 @@ RequestOptions, not_given, ) -from ._utils import is_given, get_async_library +from ._utils import ( + is_given, + is_mapping_t, + get_async_library, +) from ._compat import cached_property from ._models import SecurityOptions from ._version import __version__ @@ -82,6 +86,15 @@ def __init__( if base_url is None: base_url = f"https://app.warp.dev/api/v1" + custom_headers_env = os.environ.get("OZ_API_CUSTOM_HEADERS") + if custom_headers_env is not None: + parsed: dict[str, str] = {} + for line in custom_headers_env.split("\n"): + colon = line.find(":") + if colon >= 0: + parsed[line[:colon].strip()] = line[colon + 1 :].strip() + default_headers = {**parsed, **(default_headers if is_mapping_t(default_headers) else {})} + super().__init__( version=__version__, base_url=base_url, @@ -262,6 +275,15 @@ def __init__( if base_url is None: base_url = f"https://app.warp.dev/api/v1" + custom_headers_env = os.environ.get("OZ_API_CUSTOM_HEADERS") + if custom_headers_env is not None: + parsed: dict[str, str] = {} + for line in custom_headers_env.split("\n"): + colon = line.find(":") + if colon >= 0: + parsed[line[:colon].strip()] = line[colon + 1 :].strip() + default_headers = {**parsed, **(default_headers if is_mapping_t(default_headers) else {})} + super().__init__( version=__version__, base_url=base_url, From 4c23bb6ebec32b5022a1731284d3e07b81a9f5ae Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 28 Apr 2026 03:17:16 +0000 Subject: [PATCH 35/56] feat: Make conversation/session redirects public --- .stats.yml | 6 +- api.md | 12 ++ src/oz_agent_sdk/resources/agent/__init__.py | 14 ++ src/oz_agent_sdk/resources/agent/agent.py | 38 ++++ .../resources/agent/conversations.py | 190 ++++++++++++++++++ src/oz_agent_sdk/resources/agent/sessions.py | 20 +- src/oz_agent_sdk/types/agent/__init__.py | 1 + .../conversation_check_redirect_response.py | 12 ++ .../api_resources/agent/test_conversations.py | 108 ++++++++++ 9 files changed, 396 insertions(+), 5 deletions(-) create mode 100644 src/oz_agent_sdk/resources/agent/conversations.py create mode 100644 src/oz_agent_sdk/types/agent/conversation_check_redirect_response.py create mode 100644 tests/api_resources/agent/test_conversations.py diff --git a/.stats.yml b/.stats.yml index 637bc77..e583fdb 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 21 +configured_endpoints: 22 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta%2Fwarp-api-348bf98eecccd80255fdcee166b5eb385d8d9743811d080f94a1ec33337abc48.yml -openapi_spec_hash: 5da1dccadb70219c6dfdda1a440b9ad2 -config_hash: b893614299dd99b07446072ade3737d1 +openapi_spec_hash: 1952fae99172f1adaf35d800b0d63936 +config_hash: 44a1e8f98607a5cf03815a63bae63453 diff --git a/api.md b/api.md index e2fa926..bd33474 100644 --- a/api.md +++ b/api.md @@ -106,3 +106,15 @@ from oz_agent_sdk.types.agent import SessionCheckRedirectResponse Methods: - client.agent.sessions.check_redirect(session_uuid) -> SessionCheckRedirectResponse + +## Conversations + +Types: + +```python +from oz_agent_sdk.types.agent import ConversationCheckRedirectResponse +``` + +Methods: + +- client.agent.conversations.check_redirect(conversation_id) -> ConversationCheckRedirectResponse diff --git a/src/oz_agent_sdk/resources/agent/__init__.py b/src/oz_agent_sdk/resources/agent/__init__.py index 4336e34..69e9075 100644 --- a/src/oz_agent_sdk/resources/agent/__init__.py +++ b/src/oz_agent_sdk/resources/agent/__init__.py @@ -32,6 +32,14 @@ SchedulesResourceWithStreamingResponse, AsyncSchedulesResourceWithStreamingResponse, ) +from .conversations import ( + ConversationsResource, + AsyncConversationsResource, + ConversationsResourceWithRawResponse, + AsyncConversationsResourceWithRawResponse, + ConversationsResourceWithStreamingResponse, + AsyncConversationsResourceWithStreamingResponse, +) __all__ = [ "RunsResource", @@ -52,6 +60,12 @@ "AsyncSessionsResourceWithRawResponse", "SessionsResourceWithStreamingResponse", "AsyncSessionsResourceWithStreamingResponse", + "ConversationsResource", + "AsyncConversationsResource", + "ConversationsResourceWithRawResponse", + "AsyncConversationsResourceWithRawResponse", + "ConversationsResourceWithStreamingResponse", + "AsyncConversationsResourceWithStreamingResponse", "AgentResource", "AsyncAgentResource", "AgentResourceWithRawResponse", diff --git a/src/oz_agent_sdk/resources/agent/agent.py b/src/oz_agent_sdk/resources/agent/agent.py index 0b12e59..ff5f385 100644 --- a/src/oz_agent_sdk/resources/agent/agent.py +++ b/src/oz_agent_sdk/resources/agent/agent.py @@ -43,6 +43,14 @@ async_to_raw_response_wrapper, async_to_streamed_response_wrapper, ) +from .conversations import ( + ConversationsResource, + AsyncConversationsResource, + ConversationsResourceWithRawResponse, + AsyncConversationsResourceWithRawResponse, + ConversationsResourceWithStreamingResponse, + AsyncConversationsResourceWithStreamingResponse, +) from ..._base_client import make_request_options from ...types.agent_run_response import AgentRunResponse from ...types.agent_list_response import AgentListResponse @@ -76,6 +84,11 @@ def sessions(self) -> SessionsResource: """Operations for running and managing cloud agents""" return SessionsResource(self._client) + @cached_property + def conversations(self) -> ConversationsResource: + """Operations for running and managing cloud agents""" + return ConversationsResource(self._client) + @cached_property def with_raw_response(self) -> AgentResourceWithRawResponse: """ @@ -354,6 +367,11 @@ def sessions(self) -> AsyncSessionsResource: """Operations for running and managing cloud agents""" return AsyncSessionsResource(self._client) + @cached_property + def conversations(self) -> AsyncConversationsResource: + """Operations for running and managing cloud agents""" + return AsyncConversationsResource(self._client) + @cached_property def with_raw_response(self) -> AsyncAgentResourceWithRawResponse: """ @@ -648,6 +666,11 @@ def sessions(self) -> SessionsResourceWithRawResponse: """Operations for running and managing cloud agents""" return SessionsResourceWithRawResponse(self._agent.sessions) + @cached_property + def conversations(self) -> ConversationsResourceWithRawResponse: + """Operations for running and managing cloud agents""" + return ConversationsResourceWithRawResponse(self._agent.conversations) + class AsyncAgentResourceWithRawResponse: def __init__(self, agent: AsyncAgentResource) -> None: @@ -686,6 +709,11 @@ def sessions(self) -> AsyncSessionsResourceWithRawResponse: """Operations for running and managing cloud agents""" return AsyncSessionsResourceWithRawResponse(self._agent.sessions) + @cached_property + def conversations(self) -> AsyncConversationsResourceWithRawResponse: + """Operations for running and managing cloud agents""" + return AsyncConversationsResourceWithRawResponse(self._agent.conversations) + class AgentResourceWithStreamingResponse: def __init__(self, agent: AgentResource) -> None: @@ -724,6 +752,11 @@ def sessions(self) -> SessionsResourceWithStreamingResponse: """Operations for running and managing cloud agents""" return SessionsResourceWithStreamingResponse(self._agent.sessions) + @cached_property + def conversations(self) -> ConversationsResourceWithStreamingResponse: + """Operations for running and managing cloud agents""" + return ConversationsResourceWithStreamingResponse(self._agent.conversations) + class AsyncAgentResourceWithStreamingResponse: def __init__(self, agent: AsyncAgentResource) -> None: @@ -761,3 +794,8 @@ def agent(self) -> agent.AsyncAgentResourceWithStreamingResponse: def sessions(self) -> AsyncSessionsResourceWithStreamingResponse: """Operations for running and managing cloud agents""" return AsyncSessionsResourceWithStreamingResponse(self._agent.sessions) + + @cached_property + def conversations(self) -> AsyncConversationsResourceWithStreamingResponse: + """Operations for running and managing cloud agents""" + return AsyncConversationsResourceWithStreamingResponse(self._agent.conversations) diff --git a/src/oz_agent_sdk/resources/agent/conversations.py b/src/oz_agent_sdk/resources/agent/conversations.py new file mode 100644 index 0000000..2525916 --- /dev/null +++ b/src/oz_agent_sdk/resources/agent/conversations.py @@ -0,0 +1,190 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import httpx + +from ..._types import Body, Query, Headers, NotGiven, not_given +from ..._utils import path_template +from ..._compat import cached_property +from ..._resource import SyncAPIResource, AsyncAPIResource +from ..._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from ..._base_client import make_request_options +from ...types.agent.conversation_check_redirect_response import ConversationCheckRedirectResponse + +__all__ = ["ConversationsResource", "AsyncConversationsResource"] + + +class ConversationsResource(SyncAPIResource): + """Operations for running and managing cloud agents""" + + @cached_property + def with_raw_response(self) -> ConversationsResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/warpdotdev/oz-sdk-python#accessing-raw-response-data-eg-headers + """ + return ConversationsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> ConversationsResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/warpdotdev/oz-sdk-python#with_streaming_response + """ + return ConversationsResourceWithStreamingResponse(self) + + def check_redirect( + self, + conversation_id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> ConversationCheckRedirectResponse: + """Check whether a conversation should redirect to a live shared session. + + Returns a + session_id if the underlying ambient agent task still has a live shared session, + or an empty object if no redirect is needed. + + This endpoint is public (no authentication required) so that anonymous viewers + can resolve a publicly-shared conversation link before signing in. Access to the + underlying live session is still gated by the session-sharing service ACLs. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not conversation_id: + raise ValueError(f"Expected a non-empty value for `conversation_id` but received {conversation_id!r}") + return self._get( + path_template("/agent/conversations/{conversation_id}/redirect", conversation_id=conversation_id), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + security={}, + ), + cast_to=ConversationCheckRedirectResponse, + ) + + +class AsyncConversationsResource(AsyncAPIResource): + """Operations for running and managing cloud agents""" + + @cached_property + def with_raw_response(self) -> AsyncConversationsResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/warpdotdev/oz-sdk-python#accessing-raw-response-data-eg-headers + """ + return AsyncConversationsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncConversationsResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/warpdotdev/oz-sdk-python#with_streaming_response + """ + return AsyncConversationsResourceWithStreamingResponse(self) + + async def check_redirect( + self, + conversation_id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> ConversationCheckRedirectResponse: + """Check whether a conversation should redirect to a live shared session. + + Returns a + session_id if the underlying ambient agent task still has a live shared session, + or an empty object if no redirect is needed. + + This endpoint is public (no authentication required) so that anonymous viewers + can resolve a publicly-shared conversation link before signing in. Access to the + underlying live session is still gated by the session-sharing service ACLs. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not conversation_id: + raise ValueError(f"Expected a non-empty value for `conversation_id` but received {conversation_id!r}") + return await self._get( + path_template("/agent/conversations/{conversation_id}/redirect", conversation_id=conversation_id), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + security={}, + ), + cast_to=ConversationCheckRedirectResponse, + ) + + +class ConversationsResourceWithRawResponse: + def __init__(self, conversations: ConversationsResource) -> None: + self._conversations = conversations + + self.check_redirect = to_raw_response_wrapper( + conversations.check_redirect, + ) + + +class AsyncConversationsResourceWithRawResponse: + def __init__(self, conversations: AsyncConversationsResource) -> None: + self._conversations = conversations + + self.check_redirect = async_to_raw_response_wrapper( + conversations.check_redirect, + ) + + +class ConversationsResourceWithStreamingResponse: + def __init__(self, conversations: ConversationsResource) -> None: + self._conversations = conversations + + self.check_redirect = to_streamed_response_wrapper( + conversations.check_redirect, + ) + + +class AsyncConversationsResourceWithStreamingResponse: + def __init__(self, conversations: AsyncConversationsResource) -> None: + self._conversations = conversations + + self.check_redirect = async_to_streamed_response_wrapper( + conversations.check_redirect, + ) diff --git a/src/oz_agent_sdk/resources/agent/sessions.py b/src/oz_agent_sdk/resources/agent/sessions.py index 0beb811..d704bd6 100644 --- a/src/oz_agent_sdk/resources/agent/sessions.py +++ b/src/oz_agent_sdk/resources/agent/sessions.py @@ -58,6 +58,10 @@ def check_redirect( Returns a conversation_id if the agent sandbox has finished and conversation data is available, or an empty object if no redirect is needed. + This endpoint is public (no authentication required) so that anonymous viewers + can resolve a publicly-shared session link before signing in. Access to the + underlying conversation transcript is still gated by conversation link-sharing. + Args: extra_headers: Send extra headers @@ -72,7 +76,11 @@ def check_redirect( return self._get( path_template("/agent/sessions/{session_uuid}/redirect", session_uuid=session_uuid), options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + security={}, ), cast_to=SessionCheckRedirectResponse, ) @@ -116,6 +124,10 @@ async def check_redirect( Returns a conversation_id if the agent sandbox has finished and conversation data is available, or an empty object if no redirect is needed. + This endpoint is public (no authentication required) so that anonymous viewers + can resolve a publicly-shared session link before signing in. Access to the + underlying conversation transcript is still gated by conversation link-sharing. + Args: extra_headers: Send extra headers @@ -130,7 +142,11 @@ async def check_redirect( return await self._get( path_template("/agent/sessions/{session_uuid}/redirect", session_uuid=session_uuid), options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + security={}, ), cast_to=SessionCheckRedirectResponse, ) diff --git a/src/oz_agent_sdk/types/agent/__init__.py b/src/oz_agent_sdk/types/agent/__init__.py index 899793d..07bab46 100644 --- a/src/oz_agent_sdk/types/agent/__init__.py +++ b/src/oz_agent_sdk/types/agent/__init__.py @@ -20,6 +20,7 @@ from .scheduled_agent_history_item import ScheduledAgentHistoryItem as ScheduledAgentHistoryItem from .list_agent_identities_response import ListAgentIdentitiesResponse as ListAgentIdentitiesResponse from .session_check_redirect_response import SessionCheckRedirectResponse as SessionCheckRedirectResponse +from .conversation_check_redirect_response import ConversationCheckRedirectResponse as ConversationCheckRedirectResponse from .run_list_handoff_attachments_response import ( RunListHandoffAttachmentsResponse as RunListHandoffAttachmentsResponse, ) diff --git a/src/oz_agent_sdk/types/agent/conversation_check_redirect_response.py b/src/oz_agent_sdk/types/agent/conversation_check_redirect_response.py new file mode 100644 index 0000000..d18fa13 --- /dev/null +++ b/src/oz_agent_sdk/types/agent/conversation_check_redirect_response.py @@ -0,0 +1,12 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional + +from ..._models import BaseModel + +__all__ = ["ConversationCheckRedirectResponse"] + + +class ConversationCheckRedirectResponse(BaseModel): + session_id: Optional[str] = None + """The shared session UUID to redirect to (only present when redirect is needed)""" diff --git a/tests/api_resources/agent/test_conversations.py b/tests/api_resources/agent/test_conversations.py new file mode 100644 index 0000000..e1a21d4 --- /dev/null +++ b/tests/api_resources/agent/test_conversations.py @@ -0,0 +1,108 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +from typing import Any, cast + +import pytest + +from tests.utils import assert_matches_type +from oz_agent_sdk import OzAPI, AsyncOzAPI +from oz_agent_sdk.types.agent import ConversationCheckRedirectResponse + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestConversations: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_check_redirect(self, client: OzAPI) -> None: + conversation = client.agent.conversations.check_redirect( + "conversationId", + ) + assert_matches_type(ConversationCheckRedirectResponse, conversation, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_check_redirect(self, client: OzAPI) -> None: + response = client.agent.conversations.with_raw_response.check_redirect( + "conversationId", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + conversation = response.parse() + assert_matches_type(ConversationCheckRedirectResponse, conversation, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_check_redirect(self, client: OzAPI) -> None: + with client.agent.conversations.with_streaming_response.check_redirect( + "conversationId", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + conversation = response.parse() + assert_matches_type(ConversationCheckRedirectResponse, conversation, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_path_params_check_redirect(self, client: OzAPI) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `conversation_id` but received ''"): + client.agent.conversations.with_raw_response.check_redirect( + "", + ) + + +class TestAsyncConversations: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_check_redirect(self, async_client: AsyncOzAPI) -> None: + conversation = await async_client.agent.conversations.check_redirect( + "conversationId", + ) + assert_matches_type(ConversationCheckRedirectResponse, conversation, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_check_redirect(self, async_client: AsyncOzAPI) -> None: + response = await async_client.agent.conversations.with_raw_response.check_redirect( + "conversationId", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + conversation = await response.parse() + assert_matches_type(ConversationCheckRedirectResponse, conversation, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_check_redirect(self, async_client: AsyncOzAPI) -> None: + async with async_client.agent.conversations.with_streaming_response.check_redirect( + "conversationId", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + conversation = await response.parse() + assert_matches_type(ConversationCheckRedirectResponse, conversation, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_path_params_check_redirect(self, async_client: AsyncOzAPI) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `conversation_id` but received ''"): + await async_client.agent.conversations.with_raw_response.check_redirect( + "", + ) From caf9c4539ad1718ed194619ebf26425217265706 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 28 Apr 2026 11:18:08 +0000 Subject: [PATCH 36/56] feat: Extend service account API to support skills + secrets --- .stats.yml | 2 +- src/oz_agent_sdk/resources/agent/agent_.py | 108 ++++++++++++++++-- .../types/agent/agent_create_params.py | 30 ++++- .../types/agent/agent_response.py | 22 +++- .../types/agent/agent_update_params.py | 34 +++++- tests/api_resources/agent/test_agent_.py | 28 +++++ 6 files changed, 210 insertions(+), 14 deletions(-) diff --git a/.stats.yml b/.stats.yml index e583fdb..7cdb09e 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 22 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta%2Fwarp-api-348bf98eecccd80255fdcee166b5eb385d8d9743811d080f94a1ec33337abc48.yml -openapi_spec_hash: 1952fae99172f1adaf35d800b0d63936 +openapi_spec_hash: 276da0f1c45cb44f9c882a505cb2f8b6 config_hash: 44a1e8f98607a5cf03815a63bae63453 diff --git a/src/oz_agent_sdk/resources/agent/agent_.py b/src/oz_agent_sdk/resources/agent/agent_.py index 2c82516..b3e7a57 100644 --- a/src/oz_agent_sdk/resources/agent/agent_.py +++ b/src/oz_agent_sdk/resources/agent/agent_.py @@ -2,9 +2,11 @@ from __future__ import annotations +from typing import Iterable, Optional + import httpx -from ..._types import Body, Omit, Query, Headers, NoneType, NotGiven, omit, not_given +from ..._types import Body, Omit, Query, Headers, NoneType, NotGiven, SequenceNotStr, omit, not_given from ..._utils import path_template, maybe_transform, async_maybe_transform from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource @@ -48,6 +50,9 @@ def create( self, *, name: str, + description: Optional[str] | Omit = omit, + secrets: Iterable[agent_create_params.Secret] | Omit = omit, + skills: SequenceNotStr[str] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -63,6 +68,18 @@ def create( Args: name: A name for the agent + description: Optional description of the agent + + secrets: Optional list of secrets associated with the agent. Duplicate names within a + single request are rejected. + + skills: + Optional list of skill specs to associate with the agent. Format: + "{owner}/{repo}:{skill_path}" (e.g., + "warpdotdev/warp-server:.claude/skills/deploy/SKILL.md"). Each spec is validated + and normalized at attach time using the team's GitHub credentials; inaccessible + or malformed specs are rejected. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -73,7 +90,15 @@ def create( """ return self._post( "/agent/identities", - body=maybe_transform({"name": name}, agent_create_params.AgentCreateParams), + body=maybe_transform( + { + "name": name, + "description": description, + "secrets": secrets, + "skills": skills, + }, + agent_create_params.AgentCreateParams, + ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -84,7 +109,10 @@ def update( self, uid: str, *, + description: Optional[str] | Omit = omit, name: str | Omit = omit, + secrets: Optional[Iterable[agent_update_params.Secret]] | Omit = omit, + skills: Optional[SequenceNotStr[str]] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -92,12 +120,22 @@ def update( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AgentResponse: - """ - Update an existing agent. + """Update an existing agent. Args: + description: Replacement description. + + Omit or pass `null` to leave unchanged, or use an empty + value to clear. + name: The new name for the agent + secrets: Replacement list of secrets. Omit to leave unchanged, pass an empty array to + clear, or pass a non-empty array to replace. Duplicate names are rejected. + + skills: Replacement list of skill specs. Omit to leave unchanged, pass an empty array to + clear, or pass a non-empty array to replace. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -110,7 +148,15 @@ def update( raise ValueError(f"Expected a non-empty value for `uid` but received {uid!r}") return self._put( path_template("/agent/identities/{uid}", uid=uid), - body=maybe_transform({"name": name}, agent_update_params.AgentUpdateParams), + body=maybe_transform( + { + "description": description, + "name": name, + "secrets": secrets, + "skills": skills, + }, + agent_update_params.AgentUpdateParams, + ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -202,6 +248,9 @@ async def create( self, *, name: str, + description: Optional[str] | Omit = omit, + secrets: Iterable[agent_create_params.Secret] | Omit = omit, + skills: SequenceNotStr[str] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -217,6 +266,18 @@ async def create( Args: name: A name for the agent + description: Optional description of the agent + + secrets: Optional list of secrets associated with the agent. Duplicate names within a + single request are rejected. + + skills: + Optional list of skill specs to associate with the agent. Format: + "{owner}/{repo}:{skill_path}" (e.g., + "warpdotdev/warp-server:.claude/skills/deploy/SKILL.md"). Each spec is validated + and normalized at attach time using the team's GitHub credentials; inaccessible + or malformed specs are rejected. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -227,7 +288,15 @@ async def create( """ return await self._post( "/agent/identities", - body=await async_maybe_transform({"name": name}, agent_create_params.AgentCreateParams), + body=await async_maybe_transform( + { + "name": name, + "description": description, + "secrets": secrets, + "skills": skills, + }, + agent_create_params.AgentCreateParams, + ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -238,7 +307,10 @@ async def update( self, uid: str, *, + description: Optional[str] | Omit = omit, name: str | Omit = omit, + secrets: Optional[Iterable[agent_update_params.Secret]] | Omit = omit, + skills: Optional[SequenceNotStr[str]] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -246,12 +318,22 @@ async def update( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AgentResponse: - """ - Update an existing agent. + """Update an existing agent. Args: + description: Replacement description. + + Omit or pass `null` to leave unchanged, or use an empty + value to clear. + name: The new name for the agent + secrets: Replacement list of secrets. Omit to leave unchanged, pass an empty array to + clear, or pass a non-empty array to replace. Duplicate names are rejected. + + skills: Replacement list of skill specs. Omit to leave unchanged, pass an empty array to + clear, or pass a non-empty array to replace. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -264,7 +346,15 @@ async def update( raise ValueError(f"Expected a non-empty value for `uid` but received {uid!r}") return await self._put( path_template("/agent/identities/{uid}", uid=uid), - body=await async_maybe_transform({"name": name}, agent_update_params.AgentUpdateParams), + body=await async_maybe_transform( + { + "description": description, + "name": name, + "secrets": secrets, + "skills": skills, + }, + agent_update_params.AgentUpdateParams, + ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/oz_agent_sdk/types/agent/agent_create_params.py b/src/oz_agent_sdk/types/agent/agent_create_params.py index 5f0a737..59fc08d 100644 --- a/src/oz_agent_sdk/types/agent/agent_create_params.py +++ b/src/oz_agent_sdk/types/agent/agent_create_params.py @@ -2,11 +2,39 @@ from __future__ import annotations +from typing import Iterable, Optional from typing_extensions import Required, TypedDict -__all__ = ["AgentCreateParams"] +from ..._types import SequenceNotStr + +__all__ = ["AgentCreateParams", "Secret"] class AgentCreateParams(TypedDict, total=False): name: Required[str] """A name for the agent""" + + description: Optional[str] + """Optional description of the agent""" + + secrets: Iterable[Secret] + """ + Optional list of secrets associated with the agent. Duplicate names within a + single request are rejected. + """ + + skills: SequenceNotStr[str] + """ + Optional list of skill specs to associate with the agent. Format: + "{owner}/{repo}:{skill_path}" (e.g., + "warpdotdev/warp-server:.claude/skills/deploy/SKILL.md"). Each spec is validated + and normalized at attach time using the team's GitHub credentials; inaccessible + or malformed specs are rejected. + """ + + +class Secret(TypedDict, total=False): + """Reference to a managed secret by name.""" + + name: Required[str] + """Name of the managed secret.""" diff --git a/src/oz_agent_sdk/types/agent/agent_response.py b/src/oz_agent_sdk/types/agent/agent_response.py index d748157..8b46c85 100644 --- a/src/oz_agent_sdk/types/agent/agent_response.py +++ b/src/oz_agent_sdk/types/agent/agent_response.py @@ -1,10 +1,18 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +from typing import List, Optional from datetime import datetime from ..._models import BaseModel -__all__ = ["AgentResponse"] +__all__ = ["AgentResponse", "Secret"] + + +class Secret(BaseModel): + """Reference to a managed secret by name.""" + + name: str + """Name of the managed secret.""" class AgentResponse(BaseModel): @@ -17,5 +25,17 @@ class AgentResponse(BaseModel): name: str """Name of the agent""" + secrets: List[Secret] + """Secrets that this agent may access by default.""" + + skills: List[str] + """ + Ordered list of normalized skill specs associated with this agent. Always + present; empty when no skills are attached. + """ + uid: str """Unique identifier for the agent""" + + description: Optional[str] = None + """Optional description of the agent""" diff --git a/src/oz_agent_sdk/types/agent/agent_update_params.py b/src/oz_agent_sdk/types/agent/agent_update_params.py index e5aecdd..d3cc68a 100644 --- a/src/oz_agent_sdk/types/agent/agent_update_params.py +++ b/src/oz_agent_sdk/types/agent/agent_update_params.py @@ -2,11 +2,41 @@ from __future__ import annotations -from typing_extensions import TypedDict +from typing import Iterable, Optional +from typing_extensions import Required, TypedDict -__all__ = ["AgentUpdateParams"] +from ..._types import SequenceNotStr + +__all__ = ["AgentUpdateParams", "Secret"] class AgentUpdateParams(TypedDict, total=False): + description: Optional[str] + """Replacement description. + + Omit or pass `null` to leave unchanged, or use an empty value to clear. + """ + name: str """The new name for the agent""" + + secrets: Optional[Iterable[Secret]] + """Replacement list of secrets. + + Omit to leave unchanged, pass an empty array to clear, or pass a non-empty array + to replace. Duplicate names are rejected. + """ + + skills: Optional[SequenceNotStr[str]] + """Replacement list of skill specs. + + Omit to leave unchanged, pass an empty array to clear, or pass a non-empty array + to replace. + """ + + +class Secret(TypedDict, total=False): + """Reference to a managed secret by name.""" + + name: Required[str] + """Name of the managed secret.""" diff --git a/tests/api_resources/agent/test_agent_.py b/tests/api_resources/agent/test_agent_.py index 9bbc914..a23b05e 100644 --- a/tests/api_resources/agent/test_agent_.py +++ b/tests/api_resources/agent/test_agent_.py @@ -28,6 +28,17 @@ def test_method_create(self, client: OzAPI) -> None: ) assert_matches_type(AgentResponse, agent, path=["response"]) + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_create_with_all_params(self, client: OzAPI) -> None: + agent = client.agent.agent.create( + name="name", + description="description", + secrets=[{"name": "name"}], + skills=["string"], + ) + assert_matches_type(AgentResponse, agent, path=["response"]) + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_raw_response_create(self, client: OzAPI) -> None: @@ -67,7 +78,10 @@ def test_method_update(self, client: OzAPI) -> None: def test_method_update_with_all_params(self, client: OzAPI) -> None: agent = client.agent.agent.update( uid="uid", + description="description", name="name", + secrets=[{"name": "name"}], + skills=["string"], ) assert_matches_type(AgentResponse, agent, path=["response"]) @@ -189,6 +203,17 @@ async def test_method_create(self, async_client: AsyncOzAPI) -> None: ) assert_matches_type(AgentResponse, agent, path=["response"]) + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_create_with_all_params(self, async_client: AsyncOzAPI) -> None: + agent = await async_client.agent.agent.create( + name="name", + description="description", + secrets=[{"name": "name"}], + skills=["string"], + ) + assert_matches_type(AgentResponse, agent, path=["response"]) + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_raw_response_create(self, async_client: AsyncOzAPI) -> None: @@ -228,7 +253,10 @@ async def test_method_update(self, async_client: AsyncOzAPI) -> None: async def test_method_update_with_all_params(self, async_client: AsyncOzAPI) -> None: agent = await async_client.agent.agent.update( uid="uid", + description="description", name="name", + secrets=[{"name": "name"}], + skills=["string"], ) assert_matches_type(AgentResponse, agent, path=["response"]) From 9cf2d0352242be5c7075fe971561cc36aaaf6e77 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 28 Apr 2026 12:42:58 +0000 Subject: [PATCH 37/56] feat(api): api update --- .stats.yml | 2 +- src/oz_agent_sdk/resources/agent/agent_.py | 108 ++---------------- .../types/agent/agent_create_params.py | 30 +---- .../types/agent/agent_response.py | 22 +--- .../types/agent/agent_update_params.py | 34 +----- tests/api_resources/agent/test_agent_.py | 28 ----- 6 files changed, 14 insertions(+), 210 deletions(-) diff --git a/.stats.yml b/.stats.yml index 7cdb09e..e583fdb 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 22 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta%2Fwarp-api-348bf98eecccd80255fdcee166b5eb385d8d9743811d080f94a1ec33337abc48.yml -openapi_spec_hash: 276da0f1c45cb44f9c882a505cb2f8b6 +openapi_spec_hash: 1952fae99172f1adaf35d800b0d63936 config_hash: 44a1e8f98607a5cf03815a63bae63453 diff --git a/src/oz_agent_sdk/resources/agent/agent_.py b/src/oz_agent_sdk/resources/agent/agent_.py index b3e7a57..2c82516 100644 --- a/src/oz_agent_sdk/resources/agent/agent_.py +++ b/src/oz_agent_sdk/resources/agent/agent_.py @@ -2,11 +2,9 @@ from __future__ import annotations -from typing import Iterable, Optional - import httpx -from ..._types import Body, Omit, Query, Headers, NoneType, NotGiven, SequenceNotStr, omit, not_given +from ..._types import Body, Omit, Query, Headers, NoneType, NotGiven, omit, not_given from ..._utils import path_template, maybe_transform, async_maybe_transform from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource @@ -50,9 +48,6 @@ def create( self, *, name: str, - description: Optional[str] | Omit = omit, - secrets: Iterable[agent_create_params.Secret] | Omit = omit, - skills: SequenceNotStr[str] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -68,18 +63,6 @@ def create( Args: name: A name for the agent - description: Optional description of the agent - - secrets: Optional list of secrets associated with the agent. Duplicate names within a - single request are rejected. - - skills: - Optional list of skill specs to associate with the agent. Format: - "{owner}/{repo}:{skill_path}" (e.g., - "warpdotdev/warp-server:.claude/skills/deploy/SKILL.md"). Each spec is validated - and normalized at attach time using the team's GitHub credentials; inaccessible - or malformed specs are rejected. - extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -90,15 +73,7 @@ def create( """ return self._post( "/agent/identities", - body=maybe_transform( - { - "name": name, - "description": description, - "secrets": secrets, - "skills": skills, - }, - agent_create_params.AgentCreateParams, - ), + body=maybe_transform({"name": name}, agent_create_params.AgentCreateParams), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -109,10 +84,7 @@ def update( self, uid: str, *, - description: Optional[str] | Omit = omit, name: str | Omit = omit, - secrets: Optional[Iterable[agent_update_params.Secret]] | Omit = omit, - skills: Optional[SequenceNotStr[str]] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -120,22 +92,12 @@ def update( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AgentResponse: - """Update an existing agent. + """ + Update an existing agent. Args: - description: Replacement description. - - Omit or pass `null` to leave unchanged, or use an empty - value to clear. - name: The new name for the agent - secrets: Replacement list of secrets. Omit to leave unchanged, pass an empty array to - clear, or pass a non-empty array to replace. Duplicate names are rejected. - - skills: Replacement list of skill specs. Omit to leave unchanged, pass an empty array to - clear, or pass a non-empty array to replace. - extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -148,15 +110,7 @@ def update( raise ValueError(f"Expected a non-empty value for `uid` but received {uid!r}") return self._put( path_template("/agent/identities/{uid}", uid=uid), - body=maybe_transform( - { - "description": description, - "name": name, - "secrets": secrets, - "skills": skills, - }, - agent_update_params.AgentUpdateParams, - ), + body=maybe_transform({"name": name}, agent_update_params.AgentUpdateParams), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -248,9 +202,6 @@ async def create( self, *, name: str, - description: Optional[str] | Omit = omit, - secrets: Iterable[agent_create_params.Secret] | Omit = omit, - skills: SequenceNotStr[str] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -266,18 +217,6 @@ async def create( Args: name: A name for the agent - description: Optional description of the agent - - secrets: Optional list of secrets associated with the agent. Duplicate names within a - single request are rejected. - - skills: - Optional list of skill specs to associate with the agent. Format: - "{owner}/{repo}:{skill_path}" (e.g., - "warpdotdev/warp-server:.claude/skills/deploy/SKILL.md"). Each spec is validated - and normalized at attach time using the team's GitHub credentials; inaccessible - or malformed specs are rejected. - extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -288,15 +227,7 @@ async def create( """ return await self._post( "/agent/identities", - body=await async_maybe_transform( - { - "name": name, - "description": description, - "secrets": secrets, - "skills": skills, - }, - agent_create_params.AgentCreateParams, - ), + body=await async_maybe_transform({"name": name}, agent_create_params.AgentCreateParams), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -307,10 +238,7 @@ async def update( self, uid: str, *, - description: Optional[str] | Omit = omit, name: str | Omit = omit, - secrets: Optional[Iterable[agent_update_params.Secret]] | Omit = omit, - skills: Optional[SequenceNotStr[str]] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -318,22 +246,12 @@ async def update( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AgentResponse: - """Update an existing agent. + """ + Update an existing agent. Args: - description: Replacement description. - - Omit or pass `null` to leave unchanged, or use an empty - value to clear. - name: The new name for the agent - secrets: Replacement list of secrets. Omit to leave unchanged, pass an empty array to - clear, or pass a non-empty array to replace. Duplicate names are rejected. - - skills: Replacement list of skill specs. Omit to leave unchanged, pass an empty array to - clear, or pass a non-empty array to replace. - extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -346,15 +264,7 @@ async def update( raise ValueError(f"Expected a non-empty value for `uid` but received {uid!r}") return await self._put( path_template("/agent/identities/{uid}", uid=uid), - body=await async_maybe_transform( - { - "description": description, - "name": name, - "secrets": secrets, - "skills": skills, - }, - agent_update_params.AgentUpdateParams, - ), + body=await async_maybe_transform({"name": name}, agent_update_params.AgentUpdateParams), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/oz_agent_sdk/types/agent/agent_create_params.py b/src/oz_agent_sdk/types/agent/agent_create_params.py index 59fc08d..5f0a737 100644 --- a/src/oz_agent_sdk/types/agent/agent_create_params.py +++ b/src/oz_agent_sdk/types/agent/agent_create_params.py @@ -2,39 +2,11 @@ from __future__ import annotations -from typing import Iterable, Optional from typing_extensions import Required, TypedDict -from ..._types import SequenceNotStr - -__all__ = ["AgentCreateParams", "Secret"] +__all__ = ["AgentCreateParams"] class AgentCreateParams(TypedDict, total=False): name: Required[str] """A name for the agent""" - - description: Optional[str] - """Optional description of the agent""" - - secrets: Iterable[Secret] - """ - Optional list of secrets associated with the agent. Duplicate names within a - single request are rejected. - """ - - skills: SequenceNotStr[str] - """ - Optional list of skill specs to associate with the agent. Format: - "{owner}/{repo}:{skill_path}" (e.g., - "warpdotdev/warp-server:.claude/skills/deploy/SKILL.md"). Each spec is validated - and normalized at attach time using the team's GitHub credentials; inaccessible - or malformed specs are rejected. - """ - - -class Secret(TypedDict, total=False): - """Reference to a managed secret by name.""" - - name: Required[str] - """Name of the managed secret.""" diff --git a/src/oz_agent_sdk/types/agent/agent_response.py b/src/oz_agent_sdk/types/agent/agent_response.py index 8b46c85..d748157 100644 --- a/src/oz_agent_sdk/types/agent/agent_response.py +++ b/src/oz_agent_sdk/types/agent/agent_response.py @@ -1,18 +1,10 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import List, Optional from datetime import datetime from ..._models import BaseModel -__all__ = ["AgentResponse", "Secret"] - - -class Secret(BaseModel): - """Reference to a managed secret by name.""" - - name: str - """Name of the managed secret.""" +__all__ = ["AgentResponse"] class AgentResponse(BaseModel): @@ -25,17 +17,5 @@ class AgentResponse(BaseModel): name: str """Name of the agent""" - secrets: List[Secret] - """Secrets that this agent may access by default.""" - - skills: List[str] - """ - Ordered list of normalized skill specs associated with this agent. Always - present; empty when no skills are attached. - """ - uid: str """Unique identifier for the agent""" - - description: Optional[str] = None - """Optional description of the agent""" diff --git a/src/oz_agent_sdk/types/agent/agent_update_params.py b/src/oz_agent_sdk/types/agent/agent_update_params.py index d3cc68a..e5aecdd 100644 --- a/src/oz_agent_sdk/types/agent/agent_update_params.py +++ b/src/oz_agent_sdk/types/agent/agent_update_params.py @@ -2,41 +2,11 @@ from __future__ import annotations -from typing import Iterable, Optional -from typing_extensions import Required, TypedDict +from typing_extensions import TypedDict -from ..._types import SequenceNotStr - -__all__ = ["AgentUpdateParams", "Secret"] +__all__ = ["AgentUpdateParams"] class AgentUpdateParams(TypedDict, total=False): - description: Optional[str] - """Replacement description. - - Omit or pass `null` to leave unchanged, or use an empty value to clear. - """ - name: str """The new name for the agent""" - - secrets: Optional[Iterable[Secret]] - """Replacement list of secrets. - - Omit to leave unchanged, pass an empty array to clear, or pass a non-empty array - to replace. Duplicate names are rejected. - """ - - skills: Optional[SequenceNotStr[str]] - """Replacement list of skill specs. - - Omit to leave unchanged, pass an empty array to clear, or pass a non-empty array - to replace. - """ - - -class Secret(TypedDict, total=False): - """Reference to a managed secret by name.""" - - name: Required[str] - """Name of the managed secret.""" diff --git a/tests/api_resources/agent/test_agent_.py b/tests/api_resources/agent/test_agent_.py index a23b05e..9bbc914 100644 --- a/tests/api_resources/agent/test_agent_.py +++ b/tests/api_resources/agent/test_agent_.py @@ -28,17 +28,6 @@ def test_method_create(self, client: OzAPI) -> None: ) assert_matches_type(AgentResponse, agent, path=["response"]) - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_method_create_with_all_params(self, client: OzAPI) -> None: - agent = client.agent.agent.create( - name="name", - description="description", - secrets=[{"name": "name"}], - skills=["string"], - ) - assert_matches_type(AgentResponse, agent, path=["response"]) - @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_raw_response_create(self, client: OzAPI) -> None: @@ -78,10 +67,7 @@ def test_method_update(self, client: OzAPI) -> None: def test_method_update_with_all_params(self, client: OzAPI) -> None: agent = client.agent.agent.update( uid="uid", - description="description", name="name", - secrets=[{"name": "name"}], - skills=["string"], ) assert_matches_type(AgentResponse, agent, path=["response"]) @@ -203,17 +189,6 @@ async def test_method_create(self, async_client: AsyncOzAPI) -> None: ) assert_matches_type(AgentResponse, agent, path=["response"]) - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_method_create_with_all_params(self, async_client: AsyncOzAPI) -> None: - agent = await async_client.agent.agent.create( - name="name", - description="description", - secrets=[{"name": "name"}], - skills=["string"], - ) - assert_matches_type(AgentResponse, agent, path=["response"]) - @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_raw_response_create(self, async_client: AsyncOzAPI) -> None: @@ -253,10 +228,7 @@ async def test_method_update(self, async_client: AsyncOzAPI) -> None: async def test_method_update_with_all_params(self, async_client: AsyncOzAPI) -> None: agent = await async_client.agent.agent.update( uid="uid", - description="description", name="name", - secrets=[{"name": "name"}], - skills=["string"], ) assert_matches_type(AgentResponse, agent, path=["response"]) From d388cce4cc3e80c87a45dce6a0194c6dc3047d77 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 28 Apr 2026 18:56:42 +0000 Subject: [PATCH 38/56] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index e583fdb..e7c6b7e 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 22 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta%2Fwarp-api-348bf98eecccd80255fdcee166b5eb385d8d9743811d080f94a1ec33337abc48.yml +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta%2Fwarp-api-f5a88aa4f1991447272228b7024ebfbec99d31706b8806058917a3f90dd39d00.yml openapi_spec_hash: 1952fae99172f1adaf35d800b0d63936 config_hash: 44a1e8f98607a5cf03815a63bae63453 From 2dbc22949c6c9475a31e74cba5eadecb018277f3 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 28 Apr 2026 20:07:54 +0000 Subject: [PATCH 39/56] feat: [REMOTE-1481] [3/N] Add executor filter to run list API --- .stats.yml | 4 ++-- src/oz_agent_sdk/resources/agent/runs.py | 10 ++++++++++ src/oz_agent_sdk/types/agent/run_item.py | 2 ++ src/oz_agent_sdk/types/agent/run_list_params.py | 7 +++++++ tests/api_resources/agent/test_runs.py | 2 ++ 5 files changed, 23 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index e7c6b7e..7960a5e 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 22 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta%2Fwarp-api-f5a88aa4f1991447272228b7024ebfbec99d31706b8806058917a3f90dd39d00.yml -openapi_spec_hash: 1952fae99172f1adaf35d800b0d63936 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta%2Fwarp-api-c115a70d043bb17e7591b51464aa8666f7124fb137334d422a4281b1d9ee373f.yml +openapi_spec_hash: 66546de6547990d8367b531ab9e0302a config_hash: 44a1e8f98607a5cf03815a63bae63453 diff --git a/src/oz_agent_sdk/resources/agent/runs.py b/src/oz_agent_sdk/resources/agent/runs.py index 95893df..6b1ab06 100644 --- a/src/oz_agent_sdk/resources/agent/runs.py +++ b/src/oz_agent_sdk/resources/agent/runs.py @@ -96,6 +96,7 @@ def list( cursor: str | Omit = omit, environment_id: str | Omit = omit, execution_location: Literal["LOCAL", "REMOTE"] | Omit = omit, + executor: str | Omit = omit, limit: int | Omit = omit, model_id: str | Omit = omit, name: str | Omit = omit, @@ -138,6 +139,9 @@ def list( execution_location: Filter by where the run executed + executor: Filter by the user or agent that executed the run. This will often be the same + as the creator, but not always: users may delegate tasks to agents. + limit: Maximum number of runs to return model_id: Filter by model ID @@ -195,6 +199,7 @@ def list( "cursor": cursor, "environment_id": environment_id, "execution_location": execution_location, + "executor": executor, "limit": limit, "model_id": model_id, "name": name, @@ -401,6 +406,7 @@ def list( cursor: str | Omit = omit, environment_id: str | Omit = omit, execution_location: Literal["LOCAL", "REMOTE"] | Omit = omit, + executor: str | Omit = omit, limit: int | Omit = omit, model_id: str | Omit = omit, name: str | Omit = omit, @@ -443,6 +449,9 @@ def list( execution_location: Filter by where the run executed + executor: Filter by the user or agent that executed the run. This will often be the same + as the creator, but not always: users may delegate tasks to agents. + limit: Maximum number of runs to return model_id: Filter by model ID @@ -500,6 +509,7 @@ def list( "cursor": cursor, "environment_id": environment_id, "execution_location": execution_location, + "executor": executor, "limit": limit, "model_id": model_id, "name": name, diff --git a/src/oz_agent_sdk/types/agent/run_item.py b/src/oz_agent_sdk/types/agent/run_item.py index 61dd012..5b802d8 100644 --- a/src/oz_agent_sdk/types/agent/run_item.py +++ b/src/oz_agent_sdk/types/agent/run_item.py @@ -168,6 +168,8 @@ class RunItem(BaseModel): - REMOTE: Executed by a remote/cloud worker """ + executor: Optional[UserProfile] = None + is_sandbox_running: Optional[bool] = None """Whether the sandbox environment is currently running""" diff --git a/src/oz_agent_sdk/types/agent/run_list_params.py b/src/oz_agent_sdk/types/agent/run_list_params.py index b53a299..2e2d36f 100644 --- a/src/oz_agent_sdk/types/agent/run_list_params.py +++ b/src/oz_agent_sdk/types/agent/run_list_params.py @@ -41,6 +41,13 @@ class RunListParams(TypedDict, total=False): execution_location: Literal["LOCAL", "REMOTE"] """Filter by where the run executed""" + executor: str + """Filter by the user or agent that executed the run. + + This will often be the same as the creator, but not always: users may delegate + tasks to agents. + """ + limit: int """Maximum number of runs to return""" diff --git a/tests/api_resources/agent/test_runs.py b/tests/api_resources/agent/test_runs.py index 55b95bb..cb77f95 100644 --- a/tests/api_resources/agent/test_runs.py +++ b/tests/api_resources/agent/test_runs.py @@ -82,6 +82,7 @@ def test_method_list_with_all_params(self, client: OzAPI) -> None: cursor="cursor", environment_id="environment_id", execution_location="LOCAL", + executor="executor", limit=1, model_id="model_id", name="name", @@ -315,6 +316,7 @@ async def test_method_list_with_all_params(self, async_client: AsyncOzAPI) -> No cursor="cursor", environment_id="environment_id", execution_location="LOCAL", + executor="executor", limit=1, model_id="model_id", name="name", From 35565ada13a8a16f9117b3ca0c12279d1708d184 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 28 Apr 2026 21:04:11 +0000 Subject: [PATCH 40/56] feat(api): api update --- .stats.yml | 4 ++-- src/oz_agent_sdk/resources/agent/runs.py | 10 ---------- src/oz_agent_sdk/types/agent/run_item.py | 2 -- src/oz_agent_sdk/types/agent/run_list_params.py | 7 ------- tests/api_resources/agent/test_runs.py | 2 -- 5 files changed, 2 insertions(+), 23 deletions(-) diff --git a/.stats.yml b/.stats.yml index 7960a5e..e7c6b7e 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 22 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta%2Fwarp-api-c115a70d043bb17e7591b51464aa8666f7124fb137334d422a4281b1d9ee373f.yml -openapi_spec_hash: 66546de6547990d8367b531ab9e0302a +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta%2Fwarp-api-f5a88aa4f1991447272228b7024ebfbec99d31706b8806058917a3f90dd39d00.yml +openapi_spec_hash: 1952fae99172f1adaf35d800b0d63936 config_hash: 44a1e8f98607a5cf03815a63bae63453 diff --git a/src/oz_agent_sdk/resources/agent/runs.py b/src/oz_agent_sdk/resources/agent/runs.py index 6b1ab06..95893df 100644 --- a/src/oz_agent_sdk/resources/agent/runs.py +++ b/src/oz_agent_sdk/resources/agent/runs.py @@ -96,7 +96,6 @@ def list( cursor: str | Omit = omit, environment_id: str | Omit = omit, execution_location: Literal["LOCAL", "REMOTE"] | Omit = omit, - executor: str | Omit = omit, limit: int | Omit = omit, model_id: str | Omit = omit, name: str | Omit = omit, @@ -139,9 +138,6 @@ def list( execution_location: Filter by where the run executed - executor: Filter by the user or agent that executed the run. This will often be the same - as the creator, but not always: users may delegate tasks to agents. - limit: Maximum number of runs to return model_id: Filter by model ID @@ -199,7 +195,6 @@ def list( "cursor": cursor, "environment_id": environment_id, "execution_location": execution_location, - "executor": executor, "limit": limit, "model_id": model_id, "name": name, @@ -406,7 +401,6 @@ def list( cursor: str | Omit = omit, environment_id: str | Omit = omit, execution_location: Literal["LOCAL", "REMOTE"] | Omit = omit, - executor: str | Omit = omit, limit: int | Omit = omit, model_id: str | Omit = omit, name: str | Omit = omit, @@ -449,9 +443,6 @@ def list( execution_location: Filter by where the run executed - executor: Filter by the user or agent that executed the run. This will often be the same - as the creator, but not always: users may delegate tasks to agents. - limit: Maximum number of runs to return model_id: Filter by model ID @@ -509,7 +500,6 @@ def list( "cursor": cursor, "environment_id": environment_id, "execution_location": execution_location, - "executor": executor, "limit": limit, "model_id": model_id, "name": name, diff --git a/src/oz_agent_sdk/types/agent/run_item.py b/src/oz_agent_sdk/types/agent/run_item.py index 5b802d8..61dd012 100644 --- a/src/oz_agent_sdk/types/agent/run_item.py +++ b/src/oz_agent_sdk/types/agent/run_item.py @@ -168,8 +168,6 @@ class RunItem(BaseModel): - REMOTE: Executed by a remote/cloud worker """ - executor: Optional[UserProfile] = None - is_sandbox_running: Optional[bool] = None """Whether the sandbox environment is currently running""" diff --git a/src/oz_agent_sdk/types/agent/run_list_params.py b/src/oz_agent_sdk/types/agent/run_list_params.py index 2e2d36f..b53a299 100644 --- a/src/oz_agent_sdk/types/agent/run_list_params.py +++ b/src/oz_agent_sdk/types/agent/run_list_params.py @@ -41,13 +41,6 @@ class RunListParams(TypedDict, total=False): execution_location: Literal["LOCAL", "REMOTE"] """Filter by where the run executed""" - executor: str - """Filter by the user or agent that executed the run. - - This will often be the same as the creator, but not always: users may delegate - tasks to agents. - """ - limit: int """Maximum number of runs to return""" diff --git a/tests/api_resources/agent/test_runs.py b/tests/api_resources/agent/test_runs.py index cb77f95..55b95bb 100644 --- a/tests/api_resources/agent/test_runs.py +++ b/tests/api_resources/agent/test_runs.py @@ -82,7 +82,6 @@ def test_method_list_with_all_params(self, client: OzAPI) -> None: cursor="cursor", environment_id="environment_id", execution_location="LOCAL", - executor="executor", limit=1, model_id="model_id", name="name", @@ -316,7 +315,6 @@ async def test_method_list_with_all_params(self, async_client: AsyncOzAPI) -> No cursor="cursor", environment_id="environment_id", execution_location="LOCAL", - executor="executor", limit=1, model_id="model_id", name="name", From 898e18f8e26a2064d3bb3bdda83c08adeb91088d Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 28 Apr 2026 22:10:43 +0000 Subject: [PATCH 41/56] feat: Add Codex as a third-party Oz harness. --- .stats.yml | 4 ++-- src/oz_agent_sdk/types/ambient_agent_config.py | 3 ++- src/oz_agent_sdk/types/ambient_agent_config_param.py | 3 ++- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/.stats.yml b/.stats.yml index e7c6b7e..4f216c4 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 22 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta%2Fwarp-api-f5a88aa4f1991447272228b7024ebfbec99d31706b8806058917a3f90dd39d00.yml -openapi_spec_hash: 1952fae99172f1adaf35d800b0d63936 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta%2Fwarp-api-c3f87d920653b2a483226549626a30481124471e57ff0a4d869597d79a0a172f.yml +openapi_spec_hash: 9633e85587b7b96b381c4c29319cc1f2 config_hash: 44a1e8f98607a5cf03815a63bae63453 diff --git a/src/oz_agent_sdk/types/ambient_agent_config.py b/src/oz_agent_sdk/types/ambient_agent_config.py index b90112c..148931d 100644 --- a/src/oz_agent_sdk/types/ambient_agent_config.py +++ b/src/oz_agent_sdk/types/ambient_agent_config.py @@ -17,12 +17,13 @@ class Harness(BaseModel): Default (nil/empty) uses Warp's built-in harness. """ - type: Optional[Literal["oz", "claude", "gemini"]] = None + type: Optional[Literal["oz", "claude", "gemini", "codex"]] = None """The harness type identifier. - oz: Warp's built-in harness (default) - claude: Claude Code harness - gemini: Gemini CLI harness + - codex: Codex CLI harness """ diff --git a/src/oz_agent_sdk/types/ambient_agent_config_param.py b/src/oz_agent_sdk/types/ambient_agent_config_param.py index 9031e46..f4c6ee4 100644 --- a/src/oz_agent_sdk/types/ambient_agent_config_param.py +++ b/src/oz_agent_sdk/types/ambient_agent_config_param.py @@ -16,12 +16,13 @@ class Harness(TypedDict, total=False): Default (nil/empty) uses Warp's built-in harness. """ - type: Literal["oz", "claude", "gemini"] + type: Literal["oz", "claude", "gemini", "codex"] """The harness type identifier. - oz: Warp's built-in harness (default) - claude: Claude Code harness - gemini: Gemini CLI harness + - codex: Codex CLI harness """ From e290d3b8cd2e8bd10a713e41992e282b704c624e Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 28 Apr 2026 23:02:15 +0000 Subject: [PATCH 42/56] feat(api): api update --- .stats.yml | 4 ++-- src/oz_agent_sdk/types/ambient_agent_config.py | 3 +-- src/oz_agent_sdk/types/ambient_agent_config_param.py | 3 +-- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/.stats.yml b/.stats.yml index 4f216c4..e7c6b7e 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 22 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta%2Fwarp-api-c3f87d920653b2a483226549626a30481124471e57ff0a4d869597d79a0a172f.yml -openapi_spec_hash: 9633e85587b7b96b381c4c29319cc1f2 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta%2Fwarp-api-f5a88aa4f1991447272228b7024ebfbec99d31706b8806058917a3f90dd39d00.yml +openapi_spec_hash: 1952fae99172f1adaf35d800b0d63936 config_hash: 44a1e8f98607a5cf03815a63bae63453 diff --git a/src/oz_agent_sdk/types/ambient_agent_config.py b/src/oz_agent_sdk/types/ambient_agent_config.py index 148931d..b90112c 100644 --- a/src/oz_agent_sdk/types/ambient_agent_config.py +++ b/src/oz_agent_sdk/types/ambient_agent_config.py @@ -17,13 +17,12 @@ class Harness(BaseModel): Default (nil/empty) uses Warp's built-in harness. """ - type: Optional[Literal["oz", "claude", "gemini", "codex"]] = None + type: Optional[Literal["oz", "claude", "gemini"]] = None """The harness type identifier. - oz: Warp's built-in harness (default) - claude: Claude Code harness - gemini: Gemini CLI harness - - codex: Codex CLI harness """ diff --git a/src/oz_agent_sdk/types/ambient_agent_config_param.py b/src/oz_agent_sdk/types/ambient_agent_config_param.py index f4c6ee4..9031e46 100644 --- a/src/oz_agent_sdk/types/ambient_agent_config_param.py +++ b/src/oz_agent_sdk/types/ambient_agent_config_param.py @@ -16,13 +16,12 @@ class Harness(TypedDict, total=False): Default (nil/empty) uses Warp's built-in harness. """ - type: Literal["oz", "claude", "gemini", "codex"] + type: Literal["oz", "claude", "gemini"] """The harness type identifier. - oz: Warp's built-in harness (default) - claude: Claude Code harness - gemini: Gemini CLI harness - - codex: Codex CLI harness """ From 4ccbe0371e7bf02c454a14bc8bc2d412dcebf290 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 29 Apr 2026 05:55:59 +0000 Subject: [PATCH 43/56] feat: Memory data model scaffolding. --- .stats.yml | 6 +- src/oz_agent_sdk/resources/agent/agent_.py | 108 ++++++++++++++++-- src/oz_agent_sdk/resources/agent/runs.py | 10 ++ .../types/agent/agent_create_params.py | 30 ++++- .../types/agent/agent_response.py | 22 +++- .../types/agent/agent_update_params.py | 34 +++++- src/oz_agent_sdk/types/agent/run_item.py | 2 + .../types/agent/run_list_params.py | 7 ++ .../types/ambient_agent_config.py | 3 +- .../types/ambient_agent_config_param.py | 3 +- tests/api_resources/agent/test_agent_.py | 28 +++++ tests/api_resources/agent/test_runs.py | 2 + 12 files changed, 237 insertions(+), 18 deletions(-) diff --git a/.stats.yml b/.stats.yml index e7c6b7e..f4b96e3 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 22 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta%2Fwarp-api-f5a88aa4f1991447272228b7024ebfbec99d31706b8806058917a3f90dd39d00.yml -openapi_spec_hash: 1952fae99172f1adaf35d800b0d63936 -config_hash: 44a1e8f98607a5cf03815a63bae63453 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta%2Fwarp-api-1ef9ad3f2ad814382839a23ea6731e16dda71ce83f460b91489b1464a0e2104a.yml +openapi_spec_hash: a69bd63605861951ed480d5bcbb8fd38 +config_hash: c15534df6c8d861059e44d9dd5483b3f diff --git a/src/oz_agent_sdk/resources/agent/agent_.py b/src/oz_agent_sdk/resources/agent/agent_.py index 2c82516..b3e7a57 100644 --- a/src/oz_agent_sdk/resources/agent/agent_.py +++ b/src/oz_agent_sdk/resources/agent/agent_.py @@ -2,9 +2,11 @@ from __future__ import annotations +from typing import Iterable, Optional + import httpx -from ..._types import Body, Omit, Query, Headers, NoneType, NotGiven, omit, not_given +from ..._types import Body, Omit, Query, Headers, NoneType, NotGiven, SequenceNotStr, omit, not_given from ..._utils import path_template, maybe_transform, async_maybe_transform from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource @@ -48,6 +50,9 @@ def create( self, *, name: str, + description: Optional[str] | Omit = omit, + secrets: Iterable[agent_create_params.Secret] | Omit = omit, + skills: SequenceNotStr[str] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -63,6 +68,18 @@ def create( Args: name: A name for the agent + description: Optional description of the agent + + secrets: Optional list of secrets associated with the agent. Duplicate names within a + single request are rejected. + + skills: + Optional list of skill specs to associate with the agent. Format: + "{owner}/{repo}:{skill_path}" (e.g., + "warpdotdev/warp-server:.claude/skills/deploy/SKILL.md"). Each spec is validated + and normalized at attach time using the team's GitHub credentials; inaccessible + or malformed specs are rejected. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -73,7 +90,15 @@ def create( """ return self._post( "/agent/identities", - body=maybe_transform({"name": name}, agent_create_params.AgentCreateParams), + body=maybe_transform( + { + "name": name, + "description": description, + "secrets": secrets, + "skills": skills, + }, + agent_create_params.AgentCreateParams, + ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -84,7 +109,10 @@ def update( self, uid: str, *, + description: Optional[str] | Omit = omit, name: str | Omit = omit, + secrets: Optional[Iterable[agent_update_params.Secret]] | Omit = omit, + skills: Optional[SequenceNotStr[str]] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -92,12 +120,22 @@ def update( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AgentResponse: - """ - Update an existing agent. + """Update an existing agent. Args: + description: Replacement description. + + Omit or pass `null` to leave unchanged, or use an empty + value to clear. + name: The new name for the agent + secrets: Replacement list of secrets. Omit to leave unchanged, pass an empty array to + clear, or pass a non-empty array to replace. Duplicate names are rejected. + + skills: Replacement list of skill specs. Omit to leave unchanged, pass an empty array to + clear, or pass a non-empty array to replace. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -110,7 +148,15 @@ def update( raise ValueError(f"Expected a non-empty value for `uid` but received {uid!r}") return self._put( path_template("/agent/identities/{uid}", uid=uid), - body=maybe_transform({"name": name}, agent_update_params.AgentUpdateParams), + body=maybe_transform( + { + "description": description, + "name": name, + "secrets": secrets, + "skills": skills, + }, + agent_update_params.AgentUpdateParams, + ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -202,6 +248,9 @@ async def create( self, *, name: str, + description: Optional[str] | Omit = omit, + secrets: Iterable[agent_create_params.Secret] | Omit = omit, + skills: SequenceNotStr[str] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -217,6 +266,18 @@ async def create( Args: name: A name for the agent + description: Optional description of the agent + + secrets: Optional list of secrets associated with the agent. Duplicate names within a + single request are rejected. + + skills: + Optional list of skill specs to associate with the agent. Format: + "{owner}/{repo}:{skill_path}" (e.g., + "warpdotdev/warp-server:.claude/skills/deploy/SKILL.md"). Each spec is validated + and normalized at attach time using the team's GitHub credentials; inaccessible + or malformed specs are rejected. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -227,7 +288,15 @@ async def create( """ return await self._post( "/agent/identities", - body=await async_maybe_transform({"name": name}, agent_create_params.AgentCreateParams), + body=await async_maybe_transform( + { + "name": name, + "description": description, + "secrets": secrets, + "skills": skills, + }, + agent_create_params.AgentCreateParams, + ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -238,7 +307,10 @@ async def update( self, uid: str, *, + description: Optional[str] | Omit = omit, name: str | Omit = omit, + secrets: Optional[Iterable[agent_update_params.Secret]] | Omit = omit, + skills: Optional[SequenceNotStr[str]] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -246,12 +318,22 @@ async def update( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AgentResponse: - """ - Update an existing agent. + """Update an existing agent. Args: + description: Replacement description. + + Omit or pass `null` to leave unchanged, or use an empty + value to clear. + name: The new name for the agent + secrets: Replacement list of secrets. Omit to leave unchanged, pass an empty array to + clear, or pass a non-empty array to replace. Duplicate names are rejected. + + skills: Replacement list of skill specs. Omit to leave unchanged, pass an empty array to + clear, or pass a non-empty array to replace. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -264,7 +346,15 @@ async def update( raise ValueError(f"Expected a non-empty value for `uid` but received {uid!r}") return await self._put( path_template("/agent/identities/{uid}", uid=uid), - body=await async_maybe_transform({"name": name}, agent_update_params.AgentUpdateParams), + body=await async_maybe_transform( + { + "description": description, + "name": name, + "secrets": secrets, + "skills": skills, + }, + agent_update_params.AgentUpdateParams, + ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/oz_agent_sdk/resources/agent/runs.py b/src/oz_agent_sdk/resources/agent/runs.py index 95893df..6b1ab06 100644 --- a/src/oz_agent_sdk/resources/agent/runs.py +++ b/src/oz_agent_sdk/resources/agent/runs.py @@ -96,6 +96,7 @@ def list( cursor: str | Omit = omit, environment_id: str | Omit = omit, execution_location: Literal["LOCAL", "REMOTE"] | Omit = omit, + executor: str | Omit = omit, limit: int | Omit = omit, model_id: str | Omit = omit, name: str | Omit = omit, @@ -138,6 +139,9 @@ def list( execution_location: Filter by where the run executed + executor: Filter by the user or agent that executed the run. This will often be the same + as the creator, but not always: users may delegate tasks to agents. + limit: Maximum number of runs to return model_id: Filter by model ID @@ -195,6 +199,7 @@ def list( "cursor": cursor, "environment_id": environment_id, "execution_location": execution_location, + "executor": executor, "limit": limit, "model_id": model_id, "name": name, @@ -401,6 +406,7 @@ def list( cursor: str | Omit = omit, environment_id: str | Omit = omit, execution_location: Literal["LOCAL", "REMOTE"] | Omit = omit, + executor: str | Omit = omit, limit: int | Omit = omit, model_id: str | Omit = omit, name: str | Omit = omit, @@ -443,6 +449,9 @@ def list( execution_location: Filter by where the run executed + executor: Filter by the user or agent that executed the run. This will often be the same + as the creator, but not always: users may delegate tasks to agents. + limit: Maximum number of runs to return model_id: Filter by model ID @@ -500,6 +509,7 @@ def list( "cursor": cursor, "environment_id": environment_id, "execution_location": execution_location, + "executor": executor, "limit": limit, "model_id": model_id, "name": name, diff --git a/src/oz_agent_sdk/types/agent/agent_create_params.py b/src/oz_agent_sdk/types/agent/agent_create_params.py index 5f0a737..59fc08d 100644 --- a/src/oz_agent_sdk/types/agent/agent_create_params.py +++ b/src/oz_agent_sdk/types/agent/agent_create_params.py @@ -2,11 +2,39 @@ from __future__ import annotations +from typing import Iterable, Optional from typing_extensions import Required, TypedDict -__all__ = ["AgentCreateParams"] +from ..._types import SequenceNotStr + +__all__ = ["AgentCreateParams", "Secret"] class AgentCreateParams(TypedDict, total=False): name: Required[str] """A name for the agent""" + + description: Optional[str] + """Optional description of the agent""" + + secrets: Iterable[Secret] + """ + Optional list of secrets associated with the agent. Duplicate names within a + single request are rejected. + """ + + skills: SequenceNotStr[str] + """ + Optional list of skill specs to associate with the agent. Format: + "{owner}/{repo}:{skill_path}" (e.g., + "warpdotdev/warp-server:.claude/skills/deploy/SKILL.md"). Each spec is validated + and normalized at attach time using the team's GitHub credentials; inaccessible + or malformed specs are rejected. + """ + + +class Secret(TypedDict, total=False): + """Reference to a managed secret by name.""" + + name: Required[str] + """Name of the managed secret.""" diff --git a/src/oz_agent_sdk/types/agent/agent_response.py b/src/oz_agent_sdk/types/agent/agent_response.py index d748157..8b46c85 100644 --- a/src/oz_agent_sdk/types/agent/agent_response.py +++ b/src/oz_agent_sdk/types/agent/agent_response.py @@ -1,10 +1,18 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +from typing import List, Optional from datetime import datetime from ..._models import BaseModel -__all__ = ["AgentResponse"] +__all__ = ["AgentResponse", "Secret"] + + +class Secret(BaseModel): + """Reference to a managed secret by name.""" + + name: str + """Name of the managed secret.""" class AgentResponse(BaseModel): @@ -17,5 +25,17 @@ class AgentResponse(BaseModel): name: str """Name of the agent""" + secrets: List[Secret] + """Secrets that this agent may access by default.""" + + skills: List[str] + """ + Ordered list of normalized skill specs associated with this agent. Always + present; empty when no skills are attached. + """ + uid: str """Unique identifier for the agent""" + + description: Optional[str] = None + """Optional description of the agent""" diff --git a/src/oz_agent_sdk/types/agent/agent_update_params.py b/src/oz_agent_sdk/types/agent/agent_update_params.py index e5aecdd..d3cc68a 100644 --- a/src/oz_agent_sdk/types/agent/agent_update_params.py +++ b/src/oz_agent_sdk/types/agent/agent_update_params.py @@ -2,11 +2,41 @@ from __future__ import annotations -from typing_extensions import TypedDict +from typing import Iterable, Optional +from typing_extensions import Required, TypedDict -__all__ = ["AgentUpdateParams"] +from ..._types import SequenceNotStr + +__all__ = ["AgentUpdateParams", "Secret"] class AgentUpdateParams(TypedDict, total=False): + description: Optional[str] + """Replacement description. + + Omit or pass `null` to leave unchanged, or use an empty value to clear. + """ + name: str """The new name for the agent""" + + secrets: Optional[Iterable[Secret]] + """Replacement list of secrets. + + Omit to leave unchanged, pass an empty array to clear, or pass a non-empty array + to replace. Duplicate names are rejected. + """ + + skills: Optional[SequenceNotStr[str]] + """Replacement list of skill specs. + + Omit to leave unchanged, pass an empty array to clear, or pass a non-empty array + to replace. + """ + + +class Secret(TypedDict, total=False): + """Reference to a managed secret by name.""" + + name: Required[str] + """Name of the managed secret.""" diff --git a/src/oz_agent_sdk/types/agent/run_item.py b/src/oz_agent_sdk/types/agent/run_item.py index 61dd012..5b802d8 100644 --- a/src/oz_agent_sdk/types/agent/run_item.py +++ b/src/oz_agent_sdk/types/agent/run_item.py @@ -168,6 +168,8 @@ class RunItem(BaseModel): - REMOTE: Executed by a remote/cloud worker """ + executor: Optional[UserProfile] = None + is_sandbox_running: Optional[bool] = None """Whether the sandbox environment is currently running""" diff --git a/src/oz_agent_sdk/types/agent/run_list_params.py b/src/oz_agent_sdk/types/agent/run_list_params.py index b53a299..2e2d36f 100644 --- a/src/oz_agent_sdk/types/agent/run_list_params.py +++ b/src/oz_agent_sdk/types/agent/run_list_params.py @@ -41,6 +41,13 @@ class RunListParams(TypedDict, total=False): execution_location: Literal["LOCAL", "REMOTE"] """Filter by where the run executed""" + executor: str + """Filter by the user or agent that executed the run. + + This will often be the same as the creator, but not always: users may delegate + tasks to agents. + """ + limit: int """Maximum number of runs to return""" diff --git a/src/oz_agent_sdk/types/ambient_agent_config.py b/src/oz_agent_sdk/types/ambient_agent_config.py index b90112c..148931d 100644 --- a/src/oz_agent_sdk/types/ambient_agent_config.py +++ b/src/oz_agent_sdk/types/ambient_agent_config.py @@ -17,12 +17,13 @@ class Harness(BaseModel): Default (nil/empty) uses Warp's built-in harness. """ - type: Optional[Literal["oz", "claude", "gemini"]] = None + type: Optional[Literal["oz", "claude", "gemini", "codex"]] = None """The harness type identifier. - oz: Warp's built-in harness (default) - claude: Claude Code harness - gemini: Gemini CLI harness + - codex: Codex CLI harness """ diff --git a/src/oz_agent_sdk/types/ambient_agent_config_param.py b/src/oz_agent_sdk/types/ambient_agent_config_param.py index 9031e46..f4c6ee4 100644 --- a/src/oz_agent_sdk/types/ambient_agent_config_param.py +++ b/src/oz_agent_sdk/types/ambient_agent_config_param.py @@ -16,12 +16,13 @@ class Harness(TypedDict, total=False): Default (nil/empty) uses Warp's built-in harness. """ - type: Literal["oz", "claude", "gemini"] + type: Literal["oz", "claude", "gemini", "codex"] """The harness type identifier. - oz: Warp's built-in harness (default) - claude: Claude Code harness - gemini: Gemini CLI harness + - codex: Codex CLI harness """ diff --git a/tests/api_resources/agent/test_agent_.py b/tests/api_resources/agent/test_agent_.py index 9bbc914..a23b05e 100644 --- a/tests/api_resources/agent/test_agent_.py +++ b/tests/api_resources/agent/test_agent_.py @@ -28,6 +28,17 @@ def test_method_create(self, client: OzAPI) -> None: ) assert_matches_type(AgentResponse, agent, path=["response"]) + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_create_with_all_params(self, client: OzAPI) -> None: + agent = client.agent.agent.create( + name="name", + description="description", + secrets=[{"name": "name"}], + skills=["string"], + ) + assert_matches_type(AgentResponse, agent, path=["response"]) + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_raw_response_create(self, client: OzAPI) -> None: @@ -67,7 +78,10 @@ def test_method_update(self, client: OzAPI) -> None: def test_method_update_with_all_params(self, client: OzAPI) -> None: agent = client.agent.agent.update( uid="uid", + description="description", name="name", + secrets=[{"name": "name"}], + skills=["string"], ) assert_matches_type(AgentResponse, agent, path=["response"]) @@ -189,6 +203,17 @@ async def test_method_create(self, async_client: AsyncOzAPI) -> None: ) assert_matches_type(AgentResponse, agent, path=["response"]) + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_create_with_all_params(self, async_client: AsyncOzAPI) -> None: + agent = await async_client.agent.agent.create( + name="name", + description="description", + secrets=[{"name": "name"}], + skills=["string"], + ) + assert_matches_type(AgentResponse, agent, path=["response"]) + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_raw_response_create(self, async_client: AsyncOzAPI) -> None: @@ -228,7 +253,10 @@ async def test_method_update(self, async_client: AsyncOzAPI) -> None: async def test_method_update_with_all_params(self, async_client: AsyncOzAPI) -> None: agent = await async_client.agent.agent.update( uid="uid", + description="description", name="name", + secrets=[{"name": "name"}], + skills=["string"], ) assert_matches_type(AgentResponse, agent, path=["response"]) diff --git a/tests/api_resources/agent/test_runs.py b/tests/api_resources/agent/test_runs.py index 55b95bb..cb77f95 100644 --- a/tests/api_resources/agent/test_runs.py +++ b/tests/api_resources/agent/test_runs.py @@ -82,6 +82,7 @@ def test_method_list_with_all_params(self, client: OzAPI) -> None: cursor="cursor", environment_id="environment_id", execution_location="LOCAL", + executor="executor", limit=1, model_id="model_id", name="name", @@ -315,6 +316,7 @@ async def test_method_list_with_all_params(self, async_client: AsyncOzAPI) -> No cursor="cursor", environment_id="environment_id", execution_location="LOCAL", + executor="executor", limit=1, model_id="model_id", name="name", From f308faf7ac13b8f02a6246e5147be1c99767592e Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 29 Apr 2026 13:21:59 +0000 Subject: [PATCH 44/56] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index f4b96e3..7a71594 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 22 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta%2Fwarp-api-1ef9ad3f2ad814382839a23ea6731e16dda71ce83f460b91489b1464a0e2104a.yml -openapi_spec_hash: a69bd63605861951ed480d5bcbb8fd38 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta%2Fwarp-api-e7bd2827f37fc42deaad63c2545bf14f838d58f117c887f3db3fdca5acb4c86b.yml +openapi_spec_hash: 6a3e306f812185f0ac1115b090da7fe8 config_hash: c15534df6c8d861059e44d9dd5483b3f From 54f5cdc819015611f7214b8ac6632df1cebf857d Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 29 Apr 2026 17:19:28 +0000 Subject: [PATCH 45/56] feat(api): api update --- .stats.yml | 6 +- src/oz_agent_sdk/resources/agent/agent_.py | 108 ++---------------- src/oz_agent_sdk/resources/agent/runs.py | 10 -- .../types/agent/agent_create_params.py | 30 +---- .../types/agent/agent_response.py | 22 +--- .../types/agent/agent_update_params.py | 34 +----- src/oz_agent_sdk/types/agent/run_item.py | 2 - .../types/agent/run_list_params.py | 7 -- .../types/ambient_agent_config.py | 3 +- .../types/ambient_agent_config_param.py | 3 +- tests/api_resources/agent/test_agent_.py | 28 ----- tests/api_resources/agent/test_runs.py | 2 - 12 files changed, 18 insertions(+), 237 deletions(-) diff --git a/.stats.yml b/.stats.yml index 7a71594..e7c6b7e 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 22 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta%2Fwarp-api-e7bd2827f37fc42deaad63c2545bf14f838d58f117c887f3db3fdca5acb4c86b.yml -openapi_spec_hash: 6a3e306f812185f0ac1115b090da7fe8 -config_hash: c15534df6c8d861059e44d9dd5483b3f +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta%2Fwarp-api-f5a88aa4f1991447272228b7024ebfbec99d31706b8806058917a3f90dd39d00.yml +openapi_spec_hash: 1952fae99172f1adaf35d800b0d63936 +config_hash: 44a1e8f98607a5cf03815a63bae63453 diff --git a/src/oz_agent_sdk/resources/agent/agent_.py b/src/oz_agent_sdk/resources/agent/agent_.py index b3e7a57..2c82516 100644 --- a/src/oz_agent_sdk/resources/agent/agent_.py +++ b/src/oz_agent_sdk/resources/agent/agent_.py @@ -2,11 +2,9 @@ from __future__ import annotations -from typing import Iterable, Optional - import httpx -from ..._types import Body, Omit, Query, Headers, NoneType, NotGiven, SequenceNotStr, omit, not_given +from ..._types import Body, Omit, Query, Headers, NoneType, NotGiven, omit, not_given from ..._utils import path_template, maybe_transform, async_maybe_transform from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource @@ -50,9 +48,6 @@ def create( self, *, name: str, - description: Optional[str] | Omit = omit, - secrets: Iterable[agent_create_params.Secret] | Omit = omit, - skills: SequenceNotStr[str] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -68,18 +63,6 @@ def create( Args: name: A name for the agent - description: Optional description of the agent - - secrets: Optional list of secrets associated with the agent. Duplicate names within a - single request are rejected. - - skills: - Optional list of skill specs to associate with the agent. Format: - "{owner}/{repo}:{skill_path}" (e.g., - "warpdotdev/warp-server:.claude/skills/deploy/SKILL.md"). Each spec is validated - and normalized at attach time using the team's GitHub credentials; inaccessible - or malformed specs are rejected. - extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -90,15 +73,7 @@ def create( """ return self._post( "/agent/identities", - body=maybe_transform( - { - "name": name, - "description": description, - "secrets": secrets, - "skills": skills, - }, - agent_create_params.AgentCreateParams, - ), + body=maybe_transform({"name": name}, agent_create_params.AgentCreateParams), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -109,10 +84,7 @@ def update( self, uid: str, *, - description: Optional[str] | Omit = omit, name: str | Omit = omit, - secrets: Optional[Iterable[agent_update_params.Secret]] | Omit = omit, - skills: Optional[SequenceNotStr[str]] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -120,22 +92,12 @@ def update( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AgentResponse: - """Update an existing agent. + """ + Update an existing agent. Args: - description: Replacement description. - - Omit or pass `null` to leave unchanged, or use an empty - value to clear. - name: The new name for the agent - secrets: Replacement list of secrets. Omit to leave unchanged, pass an empty array to - clear, or pass a non-empty array to replace. Duplicate names are rejected. - - skills: Replacement list of skill specs. Omit to leave unchanged, pass an empty array to - clear, or pass a non-empty array to replace. - extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -148,15 +110,7 @@ def update( raise ValueError(f"Expected a non-empty value for `uid` but received {uid!r}") return self._put( path_template("/agent/identities/{uid}", uid=uid), - body=maybe_transform( - { - "description": description, - "name": name, - "secrets": secrets, - "skills": skills, - }, - agent_update_params.AgentUpdateParams, - ), + body=maybe_transform({"name": name}, agent_update_params.AgentUpdateParams), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -248,9 +202,6 @@ async def create( self, *, name: str, - description: Optional[str] | Omit = omit, - secrets: Iterable[agent_create_params.Secret] | Omit = omit, - skills: SequenceNotStr[str] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -266,18 +217,6 @@ async def create( Args: name: A name for the agent - description: Optional description of the agent - - secrets: Optional list of secrets associated with the agent. Duplicate names within a - single request are rejected. - - skills: - Optional list of skill specs to associate with the agent. Format: - "{owner}/{repo}:{skill_path}" (e.g., - "warpdotdev/warp-server:.claude/skills/deploy/SKILL.md"). Each spec is validated - and normalized at attach time using the team's GitHub credentials; inaccessible - or malformed specs are rejected. - extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -288,15 +227,7 @@ async def create( """ return await self._post( "/agent/identities", - body=await async_maybe_transform( - { - "name": name, - "description": description, - "secrets": secrets, - "skills": skills, - }, - agent_create_params.AgentCreateParams, - ), + body=await async_maybe_transform({"name": name}, agent_create_params.AgentCreateParams), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -307,10 +238,7 @@ async def update( self, uid: str, *, - description: Optional[str] | Omit = omit, name: str | Omit = omit, - secrets: Optional[Iterable[agent_update_params.Secret]] | Omit = omit, - skills: Optional[SequenceNotStr[str]] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -318,22 +246,12 @@ async def update( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AgentResponse: - """Update an existing agent. + """ + Update an existing agent. Args: - description: Replacement description. - - Omit or pass `null` to leave unchanged, or use an empty - value to clear. - name: The new name for the agent - secrets: Replacement list of secrets. Omit to leave unchanged, pass an empty array to - clear, or pass a non-empty array to replace. Duplicate names are rejected. - - skills: Replacement list of skill specs. Omit to leave unchanged, pass an empty array to - clear, or pass a non-empty array to replace. - extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -346,15 +264,7 @@ async def update( raise ValueError(f"Expected a non-empty value for `uid` but received {uid!r}") return await self._put( path_template("/agent/identities/{uid}", uid=uid), - body=await async_maybe_transform( - { - "description": description, - "name": name, - "secrets": secrets, - "skills": skills, - }, - agent_update_params.AgentUpdateParams, - ), + body=await async_maybe_transform({"name": name}, agent_update_params.AgentUpdateParams), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/oz_agent_sdk/resources/agent/runs.py b/src/oz_agent_sdk/resources/agent/runs.py index 6b1ab06..95893df 100644 --- a/src/oz_agent_sdk/resources/agent/runs.py +++ b/src/oz_agent_sdk/resources/agent/runs.py @@ -96,7 +96,6 @@ def list( cursor: str | Omit = omit, environment_id: str | Omit = omit, execution_location: Literal["LOCAL", "REMOTE"] | Omit = omit, - executor: str | Omit = omit, limit: int | Omit = omit, model_id: str | Omit = omit, name: str | Omit = omit, @@ -139,9 +138,6 @@ def list( execution_location: Filter by where the run executed - executor: Filter by the user or agent that executed the run. This will often be the same - as the creator, but not always: users may delegate tasks to agents. - limit: Maximum number of runs to return model_id: Filter by model ID @@ -199,7 +195,6 @@ def list( "cursor": cursor, "environment_id": environment_id, "execution_location": execution_location, - "executor": executor, "limit": limit, "model_id": model_id, "name": name, @@ -406,7 +401,6 @@ def list( cursor: str | Omit = omit, environment_id: str | Omit = omit, execution_location: Literal["LOCAL", "REMOTE"] | Omit = omit, - executor: str | Omit = omit, limit: int | Omit = omit, model_id: str | Omit = omit, name: str | Omit = omit, @@ -449,9 +443,6 @@ def list( execution_location: Filter by where the run executed - executor: Filter by the user or agent that executed the run. This will often be the same - as the creator, but not always: users may delegate tasks to agents. - limit: Maximum number of runs to return model_id: Filter by model ID @@ -509,7 +500,6 @@ def list( "cursor": cursor, "environment_id": environment_id, "execution_location": execution_location, - "executor": executor, "limit": limit, "model_id": model_id, "name": name, diff --git a/src/oz_agent_sdk/types/agent/agent_create_params.py b/src/oz_agent_sdk/types/agent/agent_create_params.py index 59fc08d..5f0a737 100644 --- a/src/oz_agent_sdk/types/agent/agent_create_params.py +++ b/src/oz_agent_sdk/types/agent/agent_create_params.py @@ -2,39 +2,11 @@ from __future__ import annotations -from typing import Iterable, Optional from typing_extensions import Required, TypedDict -from ..._types import SequenceNotStr - -__all__ = ["AgentCreateParams", "Secret"] +__all__ = ["AgentCreateParams"] class AgentCreateParams(TypedDict, total=False): name: Required[str] """A name for the agent""" - - description: Optional[str] - """Optional description of the agent""" - - secrets: Iterable[Secret] - """ - Optional list of secrets associated with the agent. Duplicate names within a - single request are rejected. - """ - - skills: SequenceNotStr[str] - """ - Optional list of skill specs to associate with the agent. Format: - "{owner}/{repo}:{skill_path}" (e.g., - "warpdotdev/warp-server:.claude/skills/deploy/SKILL.md"). Each spec is validated - and normalized at attach time using the team's GitHub credentials; inaccessible - or malformed specs are rejected. - """ - - -class Secret(TypedDict, total=False): - """Reference to a managed secret by name.""" - - name: Required[str] - """Name of the managed secret.""" diff --git a/src/oz_agent_sdk/types/agent/agent_response.py b/src/oz_agent_sdk/types/agent/agent_response.py index 8b46c85..d748157 100644 --- a/src/oz_agent_sdk/types/agent/agent_response.py +++ b/src/oz_agent_sdk/types/agent/agent_response.py @@ -1,18 +1,10 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import List, Optional from datetime import datetime from ..._models import BaseModel -__all__ = ["AgentResponse", "Secret"] - - -class Secret(BaseModel): - """Reference to a managed secret by name.""" - - name: str - """Name of the managed secret.""" +__all__ = ["AgentResponse"] class AgentResponse(BaseModel): @@ -25,17 +17,5 @@ class AgentResponse(BaseModel): name: str """Name of the agent""" - secrets: List[Secret] - """Secrets that this agent may access by default.""" - - skills: List[str] - """ - Ordered list of normalized skill specs associated with this agent. Always - present; empty when no skills are attached. - """ - uid: str """Unique identifier for the agent""" - - description: Optional[str] = None - """Optional description of the agent""" diff --git a/src/oz_agent_sdk/types/agent/agent_update_params.py b/src/oz_agent_sdk/types/agent/agent_update_params.py index d3cc68a..e5aecdd 100644 --- a/src/oz_agent_sdk/types/agent/agent_update_params.py +++ b/src/oz_agent_sdk/types/agent/agent_update_params.py @@ -2,41 +2,11 @@ from __future__ import annotations -from typing import Iterable, Optional -from typing_extensions import Required, TypedDict +from typing_extensions import TypedDict -from ..._types import SequenceNotStr - -__all__ = ["AgentUpdateParams", "Secret"] +__all__ = ["AgentUpdateParams"] class AgentUpdateParams(TypedDict, total=False): - description: Optional[str] - """Replacement description. - - Omit or pass `null` to leave unchanged, or use an empty value to clear. - """ - name: str """The new name for the agent""" - - secrets: Optional[Iterable[Secret]] - """Replacement list of secrets. - - Omit to leave unchanged, pass an empty array to clear, or pass a non-empty array - to replace. Duplicate names are rejected. - """ - - skills: Optional[SequenceNotStr[str]] - """Replacement list of skill specs. - - Omit to leave unchanged, pass an empty array to clear, or pass a non-empty array - to replace. - """ - - -class Secret(TypedDict, total=False): - """Reference to a managed secret by name.""" - - name: Required[str] - """Name of the managed secret.""" diff --git a/src/oz_agent_sdk/types/agent/run_item.py b/src/oz_agent_sdk/types/agent/run_item.py index 5b802d8..61dd012 100644 --- a/src/oz_agent_sdk/types/agent/run_item.py +++ b/src/oz_agent_sdk/types/agent/run_item.py @@ -168,8 +168,6 @@ class RunItem(BaseModel): - REMOTE: Executed by a remote/cloud worker """ - executor: Optional[UserProfile] = None - is_sandbox_running: Optional[bool] = None """Whether the sandbox environment is currently running""" diff --git a/src/oz_agent_sdk/types/agent/run_list_params.py b/src/oz_agent_sdk/types/agent/run_list_params.py index 2e2d36f..b53a299 100644 --- a/src/oz_agent_sdk/types/agent/run_list_params.py +++ b/src/oz_agent_sdk/types/agent/run_list_params.py @@ -41,13 +41,6 @@ class RunListParams(TypedDict, total=False): execution_location: Literal["LOCAL", "REMOTE"] """Filter by where the run executed""" - executor: str - """Filter by the user or agent that executed the run. - - This will often be the same as the creator, but not always: users may delegate - tasks to agents. - """ - limit: int """Maximum number of runs to return""" diff --git a/src/oz_agent_sdk/types/ambient_agent_config.py b/src/oz_agent_sdk/types/ambient_agent_config.py index 148931d..b90112c 100644 --- a/src/oz_agent_sdk/types/ambient_agent_config.py +++ b/src/oz_agent_sdk/types/ambient_agent_config.py @@ -17,13 +17,12 @@ class Harness(BaseModel): Default (nil/empty) uses Warp's built-in harness. """ - type: Optional[Literal["oz", "claude", "gemini", "codex"]] = None + type: Optional[Literal["oz", "claude", "gemini"]] = None """The harness type identifier. - oz: Warp's built-in harness (default) - claude: Claude Code harness - gemini: Gemini CLI harness - - codex: Codex CLI harness """ diff --git a/src/oz_agent_sdk/types/ambient_agent_config_param.py b/src/oz_agent_sdk/types/ambient_agent_config_param.py index f4c6ee4..9031e46 100644 --- a/src/oz_agent_sdk/types/ambient_agent_config_param.py +++ b/src/oz_agent_sdk/types/ambient_agent_config_param.py @@ -16,13 +16,12 @@ class Harness(TypedDict, total=False): Default (nil/empty) uses Warp's built-in harness. """ - type: Literal["oz", "claude", "gemini", "codex"] + type: Literal["oz", "claude", "gemini"] """The harness type identifier. - oz: Warp's built-in harness (default) - claude: Claude Code harness - gemini: Gemini CLI harness - - codex: Codex CLI harness """ diff --git a/tests/api_resources/agent/test_agent_.py b/tests/api_resources/agent/test_agent_.py index a23b05e..9bbc914 100644 --- a/tests/api_resources/agent/test_agent_.py +++ b/tests/api_resources/agent/test_agent_.py @@ -28,17 +28,6 @@ def test_method_create(self, client: OzAPI) -> None: ) assert_matches_type(AgentResponse, agent, path=["response"]) - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_method_create_with_all_params(self, client: OzAPI) -> None: - agent = client.agent.agent.create( - name="name", - description="description", - secrets=[{"name": "name"}], - skills=["string"], - ) - assert_matches_type(AgentResponse, agent, path=["response"]) - @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_raw_response_create(self, client: OzAPI) -> None: @@ -78,10 +67,7 @@ def test_method_update(self, client: OzAPI) -> None: def test_method_update_with_all_params(self, client: OzAPI) -> None: agent = client.agent.agent.update( uid="uid", - description="description", name="name", - secrets=[{"name": "name"}], - skills=["string"], ) assert_matches_type(AgentResponse, agent, path=["response"]) @@ -203,17 +189,6 @@ async def test_method_create(self, async_client: AsyncOzAPI) -> None: ) assert_matches_type(AgentResponse, agent, path=["response"]) - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_method_create_with_all_params(self, async_client: AsyncOzAPI) -> None: - agent = await async_client.agent.agent.create( - name="name", - description="description", - secrets=[{"name": "name"}], - skills=["string"], - ) - assert_matches_type(AgentResponse, agent, path=["response"]) - @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_raw_response_create(self, async_client: AsyncOzAPI) -> None: @@ -253,10 +228,7 @@ async def test_method_update(self, async_client: AsyncOzAPI) -> None: async def test_method_update_with_all_params(self, async_client: AsyncOzAPI) -> None: agent = await async_client.agent.agent.update( uid="uid", - description="description", name="name", - secrets=[{"name": "name"}], - skills=["string"], ) assert_matches_type(AgentResponse, agent, path=["response"]) diff --git a/tests/api_resources/agent/test_runs.py b/tests/api_resources/agent/test_runs.py index cb77f95..55b95bb 100644 --- a/tests/api_resources/agent/test_runs.py +++ b/tests/api_resources/agent/test_runs.py @@ -82,7 +82,6 @@ def test_method_list_with_all_params(self, client: OzAPI) -> None: cursor="cursor", environment_id="environment_id", execution_location="LOCAL", - executor="executor", limit=1, model_id="model_id", name="name", @@ -316,7 +315,6 @@ async def test_method_list_with_all_params(self, async_client: AsyncOzAPI) -> No cursor="cursor", environment_id="environment_id", execution_location="LOCAL", - executor="executor", limit=1, model_id="model_id", name="name", From 263a1205daf91ff3843d4167c4a39f90f617bddc Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 29 Apr 2026 18:30:16 +0000 Subject: [PATCH 46/56] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index e7c6b7e..58291b4 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 22 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta%2Fwarp-api-f5a88aa4f1991447272228b7024ebfbec99d31706b8806058917a3f90dd39d00.yml +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta/warp-api-f5a88aa4f1991447272228b7024ebfbec99d31706b8806058917a3f90dd39d00.yml openapi_spec_hash: 1952fae99172f1adaf35d800b0d63936 config_hash: 44a1e8f98607a5cf03815a63bae63453 From 15d68a1db8178fd9cb5fae456ca6f341b60fd1e7 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 30 Apr 2026 14:13:42 +0000 Subject: [PATCH 47/56] feat(api): api update --- .stats.yml | 6 +- src/oz_agent_sdk/resources/agent/agent_.py | 108 ++++++++++++++++-- src/oz_agent_sdk/resources/agent/runs.py | 10 ++ .../types/agent/agent_create_params.py | 30 ++++- .../types/agent/agent_response.py | 22 +++- .../types/agent/agent_update_params.py | 34 +++++- src/oz_agent_sdk/types/agent/run_item.py | 2 + .../types/agent/run_list_params.py | 7 ++ .../types/ambient_agent_config.py | 3 +- .../types/ambient_agent_config_param.py | 3 +- tests/api_resources/agent/test_agent_.py | 28 +++++ tests/api_resources/agent/test_runs.py | 2 + 12 files changed, 237 insertions(+), 18 deletions(-) diff --git a/.stats.yml b/.stats.yml index 58291b4..29b972a 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 22 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta/warp-api-f5a88aa4f1991447272228b7024ebfbec99d31706b8806058917a3f90dd39d00.yml -openapi_spec_hash: 1952fae99172f1adaf35d800b0d63936 -config_hash: 44a1e8f98607a5cf03815a63bae63453 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta/warp-api-8eb8e46de29b887cbcb25b90fec55d34e11ff82b174b7a5c1d1ce4ba4d7c2fb4.yml +openapi_spec_hash: a071b7c932453dc870e7e6cf39df0535 +config_hash: c15534df6c8d861059e44d9dd5483b3f diff --git a/src/oz_agent_sdk/resources/agent/agent_.py b/src/oz_agent_sdk/resources/agent/agent_.py index 2c82516..b3e7a57 100644 --- a/src/oz_agent_sdk/resources/agent/agent_.py +++ b/src/oz_agent_sdk/resources/agent/agent_.py @@ -2,9 +2,11 @@ from __future__ import annotations +from typing import Iterable, Optional + import httpx -from ..._types import Body, Omit, Query, Headers, NoneType, NotGiven, omit, not_given +from ..._types import Body, Omit, Query, Headers, NoneType, NotGiven, SequenceNotStr, omit, not_given from ..._utils import path_template, maybe_transform, async_maybe_transform from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource @@ -48,6 +50,9 @@ def create( self, *, name: str, + description: Optional[str] | Omit = omit, + secrets: Iterable[agent_create_params.Secret] | Omit = omit, + skills: SequenceNotStr[str] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -63,6 +68,18 @@ def create( Args: name: A name for the agent + description: Optional description of the agent + + secrets: Optional list of secrets associated with the agent. Duplicate names within a + single request are rejected. + + skills: + Optional list of skill specs to associate with the agent. Format: + "{owner}/{repo}:{skill_path}" (e.g., + "warpdotdev/warp-server:.claude/skills/deploy/SKILL.md"). Each spec is validated + and normalized at attach time using the team's GitHub credentials; inaccessible + or malformed specs are rejected. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -73,7 +90,15 @@ def create( """ return self._post( "/agent/identities", - body=maybe_transform({"name": name}, agent_create_params.AgentCreateParams), + body=maybe_transform( + { + "name": name, + "description": description, + "secrets": secrets, + "skills": skills, + }, + agent_create_params.AgentCreateParams, + ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -84,7 +109,10 @@ def update( self, uid: str, *, + description: Optional[str] | Omit = omit, name: str | Omit = omit, + secrets: Optional[Iterable[agent_update_params.Secret]] | Omit = omit, + skills: Optional[SequenceNotStr[str]] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -92,12 +120,22 @@ def update( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AgentResponse: - """ - Update an existing agent. + """Update an existing agent. Args: + description: Replacement description. + + Omit or pass `null` to leave unchanged, or use an empty + value to clear. + name: The new name for the agent + secrets: Replacement list of secrets. Omit to leave unchanged, pass an empty array to + clear, or pass a non-empty array to replace. Duplicate names are rejected. + + skills: Replacement list of skill specs. Omit to leave unchanged, pass an empty array to + clear, or pass a non-empty array to replace. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -110,7 +148,15 @@ def update( raise ValueError(f"Expected a non-empty value for `uid` but received {uid!r}") return self._put( path_template("/agent/identities/{uid}", uid=uid), - body=maybe_transform({"name": name}, agent_update_params.AgentUpdateParams), + body=maybe_transform( + { + "description": description, + "name": name, + "secrets": secrets, + "skills": skills, + }, + agent_update_params.AgentUpdateParams, + ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -202,6 +248,9 @@ async def create( self, *, name: str, + description: Optional[str] | Omit = omit, + secrets: Iterable[agent_create_params.Secret] | Omit = omit, + skills: SequenceNotStr[str] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -217,6 +266,18 @@ async def create( Args: name: A name for the agent + description: Optional description of the agent + + secrets: Optional list of secrets associated with the agent. Duplicate names within a + single request are rejected. + + skills: + Optional list of skill specs to associate with the agent. Format: + "{owner}/{repo}:{skill_path}" (e.g., + "warpdotdev/warp-server:.claude/skills/deploy/SKILL.md"). Each spec is validated + and normalized at attach time using the team's GitHub credentials; inaccessible + or malformed specs are rejected. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -227,7 +288,15 @@ async def create( """ return await self._post( "/agent/identities", - body=await async_maybe_transform({"name": name}, agent_create_params.AgentCreateParams), + body=await async_maybe_transform( + { + "name": name, + "description": description, + "secrets": secrets, + "skills": skills, + }, + agent_create_params.AgentCreateParams, + ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -238,7 +307,10 @@ async def update( self, uid: str, *, + description: Optional[str] | Omit = omit, name: str | Omit = omit, + secrets: Optional[Iterable[agent_update_params.Secret]] | Omit = omit, + skills: Optional[SequenceNotStr[str]] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -246,12 +318,22 @@ async def update( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AgentResponse: - """ - Update an existing agent. + """Update an existing agent. Args: + description: Replacement description. + + Omit or pass `null` to leave unchanged, or use an empty + value to clear. + name: The new name for the agent + secrets: Replacement list of secrets. Omit to leave unchanged, pass an empty array to + clear, or pass a non-empty array to replace. Duplicate names are rejected. + + skills: Replacement list of skill specs. Omit to leave unchanged, pass an empty array to + clear, or pass a non-empty array to replace. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -264,7 +346,15 @@ async def update( raise ValueError(f"Expected a non-empty value for `uid` but received {uid!r}") return await self._put( path_template("/agent/identities/{uid}", uid=uid), - body=await async_maybe_transform({"name": name}, agent_update_params.AgentUpdateParams), + body=await async_maybe_transform( + { + "description": description, + "name": name, + "secrets": secrets, + "skills": skills, + }, + agent_update_params.AgentUpdateParams, + ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/oz_agent_sdk/resources/agent/runs.py b/src/oz_agent_sdk/resources/agent/runs.py index 95893df..6b1ab06 100644 --- a/src/oz_agent_sdk/resources/agent/runs.py +++ b/src/oz_agent_sdk/resources/agent/runs.py @@ -96,6 +96,7 @@ def list( cursor: str | Omit = omit, environment_id: str | Omit = omit, execution_location: Literal["LOCAL", "REMOTE"] | Omit = omit, + executor: str | Omit = omit, limit: int | Omit = omit, model_id: str | Omit = omit, name: str | Omit = omit, @@ -138,6 +139,9 @@ def list( execution_location: Filter by where the run executed + executor: Filter by the user or agent that executed the run. This will often be the same + as the creator, but not always: users may delegate tasks to agents. + limit: Maximum number of runs to return model_id: Filter by model ID @@ -195,6 +199,7 @@ def list( "cursor": cursor, "environment_id": environment_id, "execution_location": execution_location, + "executor": executor, "limit": limit, "model_id": model_id, "name": name, @@ -401,6 +406,7 @@ def list( cursor: str | Omit = omit, environment_id: str | Omit = omit, execution_location: Literal["LOCAL", "REMOTE"] | Omit = omit, + executor: str | Omit = omit, limit: int | Omit = omit, model_id: str | Omit = omit, name: str | Omit = omit, @@ -443,6 +449,9 @@ def list( execution_location: Filter by where the run executed + executor: Filter by the user or agent that executed the run. This will often be the same + as the creator, but not always: users may delegate tasks to agents. + limit: Maximum number of runs to return model_id: Filter by model ID @@ -500,6 +509,7 @@ def list( "cursor": cursor, "environment_id": environment_id, "execution_location": execution_location, + "executor": executor, "limit": limit, "model_id": model_id, "name": name, diff --git a/src/oz_agent_sdk/types/agent/agent_create_params.py b/src/oz_agent_sdk/types/agent/agent_create_params.py index 5f0a737..59fc08d 100644 --- a/src/oz_agent_sdk/types/agent/agent_create_params.py +++ b/src/oz_agent_sdk/types/agent/agent_create_params.py @@ -2,11 +2,39 @@ from __future__ import annotations +from typing import Iterable, Optional from typing_extensions import Required, TypedDict -__all__ = ["AgentCreateParams"] +from ..._types import SequenceNotStr + +__all__ = ["AgentCreateParams", "Secret"] class AgentCreateParams(TypedDict, total=False): name: Required[str] """A name for the agent""" + + description: Optional[str] + """Optional description of the agent""" + + secrets: Iterable[Secret] + """ + Optional list of secrets associated with the agent. Duplicate names within a + single request are rejected. + """ + + skills: SequenceNotStr[str] + """ + Optional list of skill specs to associate with the agent. Format: + "{owner}/{repo}:{skill_path}" (e.g., + "warpdotdev/warp-server:.claude/skills/deploy/SKILL.md"). Each spec is validated + and normalized at attach time using the team's GitHub credentials; inaccessible + or malformed specs are rejected. + """ + + +class Secret(TypedDict, total=False): + """Reference to a managed secret by name.""" + + name: Required[str] + """Name of the managed secret.""" diff --git a/src/oz_agent_sdk/types/agent/agent_response.py b/src/oz_agent_sdk/types/agent/agent_response.py index d748157..8b46c85 100644 --- a/src/oz_agent_sdk/types/agent/agent_response.py +++ b/src/oz_agent_sdk/types/agent/agent_response.py @@ -1,10 +1,18 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +from typing import List, Optional from datetime import datetime from ..._models import BaseModel -__all__ = ["AgentResponse"] +__all__ = ["AgentResponse", "Secret"] + + +class Secret(BaseModel): + """Reference to a managed secret by name.""" + + name: str + """Name of the managed secret.""" class AgentResponse(BaseModel): @@ -17,5 +25,17 @@ class AgentResponse(BaseModel): name: str """Name of the agent""" + secrets: List[Secret] + """Secrets that this agent may access by default.""" + + skills: List[str] + """ + Ordered list of normalized skill specs associated with this agent. Always + present; empty when no skills are attached. + """ + uid: str """Unique identifier for the agent""" + + description: Optional[str] = None + """Optional description of the agent""" diff --git a/src/oz_agent_sdk/types/agent/agent_update_params.py b/src/oz_agent_sdk/types/agent/agent_update_params.py index e5aecdd..d3cc68a 100644 --- a/src/oz_agent_sdk/types/agent/agent_update_params.py +++ b/src/oz_agent_sdk/types/agent/agent_update_params.py @@ -2,11 +2,41 @@ from __future__ import annotations -from typing_extensions import TypedDict +from typing import Iterable, Optional +from typing_extensions import Required, TypedDict -__all__ = ["AgentUpdateParams"] +from ..._types import SequenceNotStr + +__all__ = ["AgentUpdateParams", "Secret"] class AgentUpdateParams(TypedDict, total=False): + description: Optional[str] + """Replacement description. + + Omit or pass `null` to leave unchanged, or use an empty value to clear. + """ + name: str """The new name for the agent""" + + secrets: Optional[Iterable[Secret]] + """Replacement list of secrets. + + Omit to leave unchanged, pass an empty array to clear, or pass a non-empty array + to replace. Duplicate names are rejected. + """ + + skills: Optional[SequenceNotStr[str]] + """Replacement list of skill specs. + + Omit to leave unchanged, pass an empty array to clear, or pass a non-empty array + to replace. + """ + + +class Secret(TypedDict, total=False): + """Reference to a managed secret by name.""" + + name: Required[str] + """Name of the managed secret.""" diff --git a/src/oz_agent_sdk/types/agent/run_item.py b/src/oz_agent_sdk/types/agent/run_item.py index 61dd012..5b802d8 100644 --- a/src/oz_agent_sdk/types/agent/run_item.py +++ b/src/oz_agent_sdk/types/agent/run_item.py @@ -168,6 +168,8 @@ class RunItem(BaseModel): - REMOTE: Executed by a remote/cloud worker """ + executor: Optional[UserProfile] = None + is_sandbox_running: Optional[bool] = None """Whether the sandbox environment is currently running""" diff --git a/src/oz_agent_sdk/types/agent/run_list_params.py b/src/oz_agent_sdk/types/agent/run_list_params.py index b53a299..2e2d36f 100644 --- a/src/oz_agent_sdk/types/agent/run_list_params.py +++ b/src/oz_agent_sdk/types/agent/run_list_params.py @@ -41,6 +41,13 @@ class RunListParams(TypedDict, total=False): execution_location: Literal["LOCAL", "REMOTE"] """Filter by where the run executed""" + executor: str + """Filter by the user or agent that executed the run. + + This will often be the same as the creator, but not always: users may delegate + tasks to agents. + """ + limit: int """Maximum number of runs to return""" diff --git a/src/oz_agent_sdk/types/ambient_agent_config.py b/src/oz_agent_sdk/types/ambient_agent_config.py index b90112c..148931d 100644 --- a/src/oz_agent_sdk/types/ambient_agent_config.py +++ b/src/oz_agent_sdk/types/ambient_agent_config.py @@ -17,12 +17,13 @@ class Harness(BaseModel): Default (nil/empty) uses Warp's built-in harness. """ - type: Optional[Literal["oz", "claude", "gemini"]] = None + type: Optional[Literal["oz", "claude", "gemini", "codex"]] = None """The harness type identifier. - oz: Warp's built-in harness (default) - claude: Claude Code harness - gemini: Gemini CLI harness + - codex: Codex CLI harness """ diff --git a/src/oz_agent_sdk/types/ambient_agent_config_param.py b/src/oz_agent_sdk/types/ambient_agent_config_param.py index 9031e46..f4c6ee4 100644 --- a/src/oz_agent_sdk/types/ambient_agent_config_param.py +++ b/src/oz_agent_sdk/types/ambient_agent_config_param.py @@ -16,12 +16,13 @@ class Harness(TypedDict, total=False): Default (nil/empty) uses Warp's built-in harness. """ - type: Literal["oz", "claude", "gemini"] + type: Literal["oz", "claude", "gemini", "codex"] """The harness type identifier. - oz: Warp's built-in harness (default) - claude: Claude Code harness - gemini: Gemini CLI harness + - codex: Codex CLI harness """ diff --git a/tests/api_resources/agent/test_agent_.py b/tests/api_resources/agent/test_agent_.py index 9bbc914..a23b05e 100644 --- a/tests/api_resources/agent/test_agent_.py +++ b/tests/api_resources/agent/test_agent_.py @@ -28,6 +28,17 @@ def test_method_create(self, client: OzAPI) -> None: ) assert_matches_type(AgentResponse, agent, path=["response"]) + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_create_with_all_params(self, client: OzAPI) -> None: + agent = client.agent.agent.create( + name="name", + description="description", + secrets=[{"name": "name"}], + skills=["string"], + ) + assert_matches_type(AgentResponse, agent, path=["response"]) + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_raw_response_create(self, client: OzAPI) -> None: @@ -67,7 +78,10 @@ def test_method_update(self, client: OzAPI) -> None: def test_method_update_with_all_params(self, client: OzAPI) -> None: agent = client.agent.agent.update( uid="uid", + description="description", name="name", + secrets=[{"name": "name"}], + skills=["string"], ) assert_matches_type(AgentResponse, agent, path=["response"]) @@ -189,6 +203,17 @@ async def test_method_create(self, async_client: AsyncOzAPI) -> None: ) assert_matches_type(AgentResponse, agent, path=["response"]) + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_create_with_all_params(self, async_client: AsyncOzAPI) -> None: + agent = await async_client.agent.agent.create( + name="name", + description="description", + secrets=[{"name": "name"}], + skills=["string"], + ) + assert_matches_type(AgentResponse, agent, path=["response"]) + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_raw_response_create(self, async_client: AsyncOzAPI) -> None: @@ -228,7 +253,10 @@ async def test_method_update(self, async_client: AsyncOzAPI) -> None: async def test_method_update_with_all_params(self, async_client: AsyncOzAPI) -> None: agent = await async_client.agent.agent.update( uid="uid", + description="description", name="name", + secrets=[{"name": "name"}], + skills=["string"], ) assert_matches_type(AgentResponse, agent, path=["response"]) diff --git a/tests/api_resources/agent/test_runs.py b/tests/api_resources/agent/test_runs.py index 55b95bb..cb77f95 100644 --- a/tests/api_resources/agent/test_runs.py +++ b/tests/api_resources/agent/test_runs.py @@ -82,6 +82,7 @@ def test_method_list_with_all_params(self, client: OzAPI) -> None: cursor="cursor", environment_id="environment_id", execution_location="LOCAL", + executor="executor", limit=1, model_id="model_id", name="name", @@ -315,6 +316,7 @@ async def test_method_list_with_all_params(self, async_client: AsyncOzAPI) -> No cursor="cursor", environment_id="environment_id", execution_location="LOCAL", + executor="executor", limit=1, model_id="model_id", name="name", From 1d4e049e5c64fdfe1f8eff8dbf7bc8256ed98182 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 30 Apr 2026 15:42:09 +0000 Subject: [PATCH 48/56] feat: [APP-3106] Specs: Explicit QueryMode for cloud agent run creation --- .stats.yml | 4 ++-- src/oz_agent_sdk/resources/agent/agent.py | 12 ++++++++++ src/oz_agent_sdk/resources/agent/runs.py | 24 +++++++++++++++++-- src/oz_agent_sdk/resources/agent/schedules.py | 22 +++++++++++++++++ .../types/agent/run_submit_followup_params.py | 9 ++++++- .../types/agent/schedule_create_params.py | 9 ++++++- .../types/agent/schedule_update_params.py | 9 ++++++- src/oz_agent_sdk/types/agent_run_params.py | 10 +++++++- tests/api_resources/agent/test_runs.py | 20 ++++++++++++++++ tests/api_resources/agent/test_schedules.py | 4 ++++ tests/api_resources/test_agent.py | 2 ++ 11 files changed, 117 insertions(+), 8 deletions(-) diff --git a/.stats.yml b/.stats.yml index 29b972a..4acf72c 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 22 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta/warp-api-8eb8e46de29b887cbcb25b90fec55d34e11ff82b174b7a5c1d1ce4ba4d7c2fb4.yml -openapi_spec_hash: a071b7c932453dc870e7e6cf39df0535 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta/warp-api-f4c3bab952ad19ea9d246794add1bda6d3911eb32d8372f0d7271b52267b6d0b.yml +openapi_spec_hash: 9fd38bfc2e640fb456258f50fccacf88 config_hash: c15534df6c8d861059e44d9dd5483b3f diff --git a/src/oz_agent_sdk/resources/agent/agent.py b/src/oz_agent_sdk/resources/agent/agent.py index ff5f385..8e8d1d0 100644 --- a/src/oz_agent_sdk/resources/agent/agent.py +++ b/src/oz_agent_sdk/resources/agent/agent.py @@ -262,6 +262,7 @@ def run( config: AmbientAgentConfigParam | Omit = omit, conversation_id: str | Omit = omit, interactive: bool | Omit = omit, + mode: Literal["normal", "plan", "orchestrate"] | Omit = omit, parent_run_id: str | Omit = omit, prompt: str | Omit = omit, skill: str | Omit = omit, @@ -293,6 +294,10 @@ def run( interactive: Whether the run should be interactive. If not set, defaults to false. + mode: Optional query mode for the run. Defaults to `normal` when omitted. The server + does not infer mode from prompt prefixes such as `/plan`, so callers should pass + this field explicitly to request non-normal behavior. + parent_run_id: Optional run ID of the parent that spawned this run. Used for orchestration hierarchies. @@ -329,6 +334,7 @@ def run( "config": config, "conversation_id": conversation_id, "interactive": interactive, + "mode": mode, "parent_run_id": parent_run_id, "prompt": prompt, "skill": skill, @@ -547,6 +553,7 @@ async def run( config: AmbientAgentConfigParam | Omit = omit, conversation_id: str | Omit = omit, interactive: bool | Omit = omit, + mode: Literal["normal", "plan", "orchestrate"] | Omit = omit, parent_run_id: str | Omit = omit, prompt: str | Omit = omit, skill: str | Omit = omit, @@ -578,6 +585,10 @@ async def run( interactive: Whether the run should be interactive. If not set, defaults to false. + mode: Optional query mode for the run. Defaults to `normal` when omitted. The server + does not infer mode from prompt prefixes such as `/plan`, so callers should pass + this field explicitly to request non-normal behavior. + parent_run_id: Optional run ID of the parent that spawned this run. Used for orchestration hierarchies. @@ -614,6 +625,7 @@ async def run( "config": config, "conversation_id": conversation_id, "interactive": interactive, + "mode": mode, "parent_run_id": parent_run_id, "prompt": prompt, "skill": skill, diff --git a/src/oz_agent_sdk/resources/agent/runs.py b/src/oz_agent_sdk/resources/agent/runs.py index 6b1ab06..c2d5075 100644 --- a/src/oz_agent_sdk/resources/agent/runs.py +++ b/src/oz_agent_sdk/resources/agent/runs.py @@ -302,6 +302,7 @@ def submit_followup( run_id: str, *, message: str, + mode: Literal["normal", "plan", "orchestrate"] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -319,6 +320,9 @@ def submit_followup( Args: message: The follow-up message to send to the run. + mode: Optional query mode for the follow-up. Defaults to `normal` when omitted. The + server does not infer mode from prompt prefixes such as `/plan`. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -331,7 +335,13 @@ def submit_followup( raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}") return self._post( path_template("/agent/runs/{run_id}/followups", run_id=run_id), - body=maybe_transform({"message": message}, run_submit_followup_params.RunSubmitFollowupParams), + body=maybe_transform( + { + "message": message, + "mode": mode, + }, + run_submit_followup_params.RunSubmitFollowupParams, + ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -612,6 +622,7 @@ async def submit_followup( run_id: str, *, message: str, + mode: Literal["normal", "plan", "orchestrate"] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -629,6 +640,9 @@ async def submit_followup( Args: message: The follow-up message to send to the run. + mode: Optional query mode for the follow-up. Defaults to `normal` when omitted. The + server does not infer mode from prompt prefixes such as `/plan`. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -641,7 +655,13 @@ async def submit_followup( raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}") return await self._post( path_template("/agent/runs/{run_id}/followups", run_id=run_id), - body=await async_maybe_transform({"message": message}, run_submit_followup_params.RunSubmitFollowupParams), + body=await async_maybe_transform( + { + "message": message, + "mode": mode, + }, + run_submit_followup_params.RunSubmitFollowupParams, + ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/oz_agent_sdk/resources/agent/schedules.py b/src/oz_agent_sdk/resources/agent/schedules.py index b29a979..2d0724f 100644 --- a/src/oz_agent_sdk/resources/agent/schedules.py +++ b/src/oz_agent_sdk/resources/agent/schedules.py @@ -2,6 +2,8 @@ from __future__ import annotations +from typing_extensions import Literal + import httpx from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given @@ -54,6 +56,7 @@ def create( agent_config: AmbientAgentConfigParam | Omit = omit, agent_uid: str | Omit = omit, enabled: bool | Omit = omit, + mode: Literal["normal", "plan", "orchestrate"] | Omit = omit, prompt: str | Omit = omit, team: bool | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -81,6 +84,9 @@ def create( enabled: Whether the schedule should be active immediately + mode: Optional query mode applied to every triggered run. Defaults to `normal` when + omitted. The server does not infer mode from prompt prefixes such as `/plan`. + prompt: The prompt/instruction for the agent to execute. Required unless agent_config.skill_spec is provided. @@ -104,6 +110,7 @@ def create( "agent_config": agent_config, "agent_uid": agent_uid, "enabled": enabled, + "mode": mode, "prompt": prompt, "team": team, }, @@ -158,6 +165,7 @@ def update( name: str, agent_config: AmbientAgentConfigParam | Omit = omit, agent_uid: str | Omit = omit, + mode: Literal["normal", "plan", "orchestrate"] | Omit = omit, prompt: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. @@ -183,6 +191,9 @@ def update( agent_uid: Agent UID to use as the execution principal for this schedule. Only valid for team-owned schedules. + mode: Optional query mode applied to every triggered run. Defaults to `normal` when + omitted. The server does not infer mode from prompt prefixes such as `/plan`. + prompt: The prompt/instruction for the agent to execute. Required unless agent_config.skill_spec is provided. @@ -205,6 +216,7 @@ def update( "name": name, "agent_config": agent_config, "agent_uid": agent_uid, + "mode": mode, "prompt": prompt, }, schedule_update_params.ScheduleUpdateParams, @@ -372,6 +384,7 @@ async def create( agent_config: AmbientAgentConfigParam | Omit = omit, agent_uid: str | Omit = omit, enabled: bool | Omit = omit, + mode: Literal["normal", "plan", "orchestrate"] | Omit = omit, prompt: str | Omit = omit, team: bool | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -399,6 +412,9 @@ async def create( enabled: Whether the schedule should be active immediately + mode: Optional query mode applied to every triggered run. Defaults to `normal` when + omitted. The server does not infer mode from prompt prefixes such as `/plan`. + prompt: The prompt/instruction for the agent to execute. Required unless agent_config.skill_spec is provided. @@ -422,6 +438,7 @@ async def create( "agent_config": agent_config, "agent_uid": agent_uid, "enabled": enabled, + "mode": mode, "prompt": prompt, "team": team, }, @@ -476,6 +493,7 @@ async def update( name: str, agent_config: AmbientAgentConfigParam | Omit = omit, agent_uid: str | Omit = omit, + mode: Literal["normal", "plan", "orchestrate"] | Omit = omit, prompt: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. @@ -501,6 +519,9 @@ async def update( agent_uid: Agent UID to use as the execution principal for this schedule. Only valid for team-owned schedules. + mode: Optional query mode applied to every triggered run. Defaults to `normal` when + omitted. The server does not infer mode from prompt prefixes such as `/plan`. + prompt: The prompt/instruction for the agent to execute. Required unless agent_config.skill_spec is provided. @@ -523,6 +544,7 @@ async def update( "name": name, "agent_config": agent_config, "agent_uid": agent_uid, + "mode": mode, "prompt": prompt, }, schedule_update_params.ScheduleUpdateParams, diff --git a/src/oz_agent_sdk/types/agent/run_submit_followup_params.py b/src/oz_agent_sdk/types/agent/run_submit_followup_params.py index 4912cd1..004341f 100644 --- a/src/oz_agent_sdk/types/agent/run_submit_followup_params.py +++ b/src/oz_agent_sdk/types/agent/run_submit_followup_params.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing_extensions import Required, TypedDict +from typing_extensions import Literal, Required, TypedDict __all__ = ["RunSubmitFollowupParams"] @@ -10,3 +10,10 @@ class RunSubmitFollowupParams(TypedDict, total=False): message: Required[str] """The follow-up message to send to the run.""" + + mode: Literal["normal", "plan", "orchestrate"] + """Optional query mode for the follow-up. + + Defaults to `normal` when omitted. The server does not infer mode from prompt + prefixes such as `/plan`. + """ diff --git a/src/oz_agent_sdk/types/agent/schedule_create_params.py b/src/oz_agent_sdk/types/agent/schedule_create_params.py index 8958fd0..5127f04 100644 --- a/src/oz_agent_sdk/types/agent/schedule_create_params.py +++ b/src/oz_agent_sdk/types/agent/schedule_create_params.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing_extensions import Required, TypedDict +from typing_extensions import Literal, Required, TypedDict from ..ambient_agent_config_param import AmbientAgentConfigParam @@ -31,6 +31,13 @@ class ScheduleCreateParams(TypedDict, total=False): enabled: bool """Whether the schedule should be active immediately""" + mode: Literal["normal", "plan", "orchestrate"] + """Optional query mode applied to every triggered run. + + Defaults to `normal` when omitted. The server does not infer mode from prompt + prefixes such as `/plan`. + """ + prompt: str """ The prompt/instruction for the agent to execute. Required unless diff --git a/src/oz_agent_sdk/types/agent/schedule_update_params.py b/src/oz_agent_sdk/types/agent/schedule_update_params.py index de71dc9..6ae2dbe 100644 --- a/src/oz_agent_sdk/types/agent/schedule_update_params.py +++ b/src/oz_agent_sdk/types/agent/schedule_update_params.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing_extensions import Required, TypedDict +from typing_extensions import Literal, Required, TypedDict from ..ambient_agent_config_param import AmbientAgentConfigParam @@ -28,6 +28,13 @@ class ScheduleUpdateParams(TypedDict, total=False): team-owned schedules. """ + mode: Literal["normal", "plan", "orchestrate"] + """Optional query mode applied to every triggered run. + + Defaults to `normal` when omitted. The server does not infer mode from prompt + prefixes such as `/plan`. + """ + prompt: str """ The prompt/instruction for the agent to execute. Required unless diff --git a/src/oz_agent_sdk/types/agent_run_params.py b/src/oz_agent_sdk/types/agent_run_params.py index 5d185a5..d1f9941 100644 --- a/src/oz_agent_sdk/types/agent_run_params.py +++ b/src/oz_agent_sdk/types/agent_run_params.py @@ -3,7 +3,7 @@ from __future__ import annotations from typing import Union, Iterable -from typing_extensions import Required, Annotated, TypedDict +from typing_extensions import Literal, Required, Annotated, TypedDict from .._types import Base64FileInput from .._utils import PropertyInfo @@ -38,6 +38,14 @@ class AgentRunParams(TypedDict, total=False): interactive: bool """Whether the run should be interactive. If not set, defaults to false.""" + mode: Literal["normal", "plan", "orchestrate"] + """Optional query mode for the run. + + Defaults to `normal` when omitted. The server does not infer mode from prompt + prefixes such as `/plan`, so callers should pass this field explicitly to + request non-normal behavior. + """ + parent_run_id: str """ Optional run ID of the parent that spawned this run. Used for orchestration diff --git a/tests/api_resources/agent/test_runs.py b/tests/api_resources/agent/test_runs.py index cb77f95..6af094f 100644 --- a/tests/api_resources/agent/test_runs.py +++ b/tests/api_resources/agent/test_runs.py @@ -213,6 +213,16 @@ def test_method_submit_followup(self, client: OzAPI) -> None: ) assert_matches_type(object, run, path=["response"]) + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_submit_followup_with_all_params(self, client: OzAPI) -> None: + run = client.agent.runs.submit_followup( + run_id="runId", + message="message", + mode="normal", + ) + assert_matches_type(object, run, path=["response"]) + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_raw_response_submit_followup(self, client: OzAPI) -> None: @@ -447,6 +457,16 @@ async def test_method_submit_followup(self, async_client: AsyncOzAPI) -> None: ) assert_matches_type(object, run, path=["response"]) + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_submit_followup_with_all_params(self, async_client: AsyncOzAPI) -> None: + run = await async_client.agent.runs.submit_followup( + run_id="runId", + message="message", + mode="normal", + ) + assert_matches_type(object, run, path=["response"]) + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_raw_response_submit_followup(self, async_client: AsyncOzAPI) -> None: diff --git a/tests/api_resources/agent/test_schedules.py b/tests/api_resources/agent/test_schedules.py index b37e9bc..0beb0e2 100644 --- a/tests/api_resources/agent/test_schedules.py +++ b/tests/api_resources/agent/test_schedules.py @@ -61,6 +61,7 @@ def test_method_create_with_all_params(self, client: OzAPI) -> None: }, agent_uid="agent_uid", enabled=True, + mode="normal", prompt="Review open pull requests and provide feedback", team=True, ) @@ -179,6 +180,7 @@ def test_method_update_with_all_params(self, client: OzAPI) -> None: "worker_host": "worker_host", }, agent_uid="agent_uid", + mode="normal", prompt="prompt", ) assert_matches_type(ScheduledAgentItem, schedule, path=["response"]) @@ -426,6 +428,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncOzAPI) -> }, agent_uid="agent_uid", enabled=True, + mode="normal", prompt="Review open pull requests and provide feedback", team=True, ) @@ -544,6 +547,7 @@ async def test_method_update_with_all_params(self, async_client: AsyncOzAPI) -> "worker_host": "worker_host", }, agent_uid="agent_uid", + mode="normal", prompt="prompt", ) assert_matches_type(ScheduledAgentItem, schedule, path=["response"]) diff --git a/tests/api_resources/test_agent.py b/tests/api_resources/test_agent.py index 78b54a4..a10a54e 100644 --- a/tests/api_resources/test_agent.py +++ b/tests/api_resources/test_agent.py @@ -182,6 +182,7 @@ def test_method_run_with_all_params(self, client: OzAPI) -> None: }, conversation_id="conversation_id", interactive=True, + mode="normal", parent_run_id="parent_run_id", prompt="prompt", skill="skill", @@ -378,6 +379,7 @@ async def test_method_run_with_all_params(self, async_client: AsyncOzAPI) -> Non }, conversation_id="conversation_id", interactive=True, + mode="normal", parent_run_id="parent_run_id", prompt="prompt", skill="skill", From bf8dcee9d0b9bea09a6710503c02d5ece6472557 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 30 Apr 2026 16:03:19 +0000 Subject: [PATCH 49/56] codegen metadata --- .stats.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.stats.yml b/.stats.yml index 4acf72c..13f5954 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 22 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta/warp-api-f4c3bab952ad19ea9d246794add1bda6d3911eb32d8372f0d7271b52267b6d0b.yml -openapi_spec_hash: 9fd38bfc2e640fb456258f50fccacf88 -config_hash: c15534df6c8d861059e44d9dd5483b3f +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta/warp-api-d48071a6426024cf1d8101e9b6dbf4143aad3ffbfe13f926f1b5631d2e2df96a.yml +openapi_spec_hash: 8c6526cec856a6b4782566e5e2b3f814 +config_hash: f52e7636f248f25c4ea0b086e7326816 From 4c1dc05e207307940d07a8ea9b6451dbbdd3ba76 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 30 Apr 2026 16:19:31 +0000 Subject: [PATCH 50/56] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index 13f5954..e65f93b 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 22 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta/warp-api-d48071a6426024cf1d8101e9b6dbf4143aad3ffbfe13f926f1b5631d2e2df96a.yml +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta/warp-api-b700b3377aa3a7840b9e2f180580bcd3c1ed308353de72ad0de015fad1ee9834.yml openapi_spec_hash: 8c6526cec856a6b4782566e5e2b3f814 config_hash: f52e7636f248f25c4ea0b086e7326816 From 86d389c610fb2b89d7fcd17ebfd06610ef2b0b90 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 30 Apr 2026 16:45:45 +0000 Subject: [PATCH 51/56] feat(api): api update --- .stats.yml | 6 ++--- src/oz_agent_sdk/resources/agent/agent.py | 12 ---------- src/oz_agent_sdk/resources/agent/runs.py | 24 ++----------------- src/oz_agent_sdk/resources/agent/schedules.py | 22 ----------------- .../types/agent/run_submit_followup_params.py | 9 +------ .../types/agent/schedule_create_params.py | 9 +------ .../types/agent/schedule_update_params.py | 9 +------ src/oz_agent_sdk/types/agent_run_params.py | 10 +------- tests/api_resources/agent/test_runs.py | 20 ---------------- tests/api_resources/agent/test_schedules.py | 4 ---- tests/api_resources/test_agent.py | 2 -- 11 files changed, 9 insertions(+), 118 deletions(-) diff --git a/.stats.yml b/.stats.yml index e65f93b..d40dcac 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 22 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta/warp-api-b700b3377aa3a7840b9e2f180580bcd3c1ed308353de72ad0de015fad1ee9834.yml -openapi_spec_hash: 8c6526cec856a6b4782566e5e2b3f814 -config_hash: f52e7636f248f25c4ea0b086e7326816 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta/warp-api-3eeaadc6a0c1eefbc3c3a7e1212b2be5c061bad7bcabedf5ee30eb2a7f992505.yml +openapi_spec_hash: a071b7c932453dc870e7e6cf39df0535 +config_hash: c15534df6c8d861059e44d9dd5483b3f diff --git a/src/oz_agent_sdk/resources/agent/agent.py b/src/oz_agent_sdk/resources/agent/agent.py index 8e8d1d0..ff5f385 100644 --- a/src/oz_agent_sdk/resources/agent/agent.py +++ b/src/oz_agent_sdk/resources/agent/agent.py @@ -262,7 +262,6 @@ def run( config: AmbientAgentConfigParam | Omit = omit, conversation_id: str | Omit = omit, interactive: bool | Omit = omit, - mode: Literal["normal", "plan", "orchestrate"] | Omit = omit, parent_run_id: str | Omit = omit, prompt: str | Omit = omit, skill: str | Omit = omit, @@ -294,10 +293,6 @@ def run( interactive: Whether the run should be interactive. If not set, defaults to false. - mode: Optional query mode for the run. Defaults to `normal` when omitted. The server - does not infer mode from prompt prefixes such as `/plan`, so callers should pass - this field explicitly to request non-normal behavior. - parent_run_id: Optional run ID of the parent that spawned this run. Used for orchestration hierarchies. @@ -334,7 +329,6 @@ def run( "config": config, "conversation_id": conversation_id, "interactive": interactive, - "mode": mode, "parent_run_id": parent_run_id, "prompt": prompt, "skill": skill, @@ -553,7 +547,6 @@ async def run( config: AmbientAgentConfigParam | Omit = omit, conversation_id: str | Omit = omit, interactive: bool | Omit = omit, - mode: Literal["normal", "plan", "orchestrate"] | Omit = omit, parent_run_id: str | Omit = omit, prompt: str | Omit = omit, skill: str | Omit = omit, @@ -585,10 +578,6 @@ async def run( interactive: Whether the run should be interactive. If not set, defaults to false. - mode: Optional query mode for the run. Defaults to `normal` when omitted. The server - does not infer mode from prompt prefixes such as `/plan`, so callers should pass - this field explicitly to request non-normal behavior. - parent_run_id: Optional run ID of the parent that spawned this run. Used for orchestration hierarchies. @@ -625,7 +614,6 @@ async def run( "config": config, "conversation_id": conversation_id, "interactive": interactive, - "mode": mode, "parent_run_id": parent_run_id, "prompt": prompt, "skill": skill, diff --git a/src/oz_agent_sdk/resources/agent/runs.py b/src/oz_agent_sdk/resources/agent/runs.py index c2d5075..6b1ab06 100644 --- a/src/oz_agent_sdk/resources/agent/runs.py +++ b/src/oz_agent_sdk/resources/agent/runs.py @@ -302,7 +302,6 @@ def submit_followup( run_id: str, *, message: str, - mode: Literal["normal", "plan", "orchestrate"] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -320,9 +319,6 @@ def submit_followup( Args: message: The follow-up message to send to the run. - mode: Optional query mode for the follow-up. Defaults to `normal` when omitted. The - server does not infer mode from prompt prefixes such as `/plan`. - extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -335,13 +331,7 @@ def submit_followup( raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}") return self._post( path_template("/agent/runs/{run_id}/followups", run_id=run_id), - body=maybe_transform( - { - "message": message, - "mode": mode, - }, - run_submit_followup_params.RunSubmitFollowupParams, - ), + body=maybe_transform({"message": message}, run_submit_followup_params.RunSubmitFollowupParams), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -622,7 +612,6 @@ async def submit_followup( run_id: str, *, message: str, - mode: Literal["normal", "plan", "orchestrate"] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -640,9 +629,6 @@ async def submit_followup( Args: message: The follow-up message to send to the run. - mode: Optional query mode for the follow-up. Defaults to `normal` when omitted. The - server does not infer mode from prompt prefixes such as `/plan`. - extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -655,13 +641,7 @@ async def submit_followup( raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}") return await self._post( path_template("/agent/runs/{run_id}/followups", run_id=run_id), - body=await async_maybe_transform( - { - "message": message, - "mode": mode, - }, - run_submit_followup_params.RunSubmitFollowupParams, - ), + body=await async_maybe_transform({"message": message}, run_submit_followup_params.RunSubmitFollowupParams), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/oz_agent_sdk/resources/agent/schedules.py b/src/oz_agent_sdk/resources/agent/schedules.py index 2d0724f..b29a979 100644 --- a/src/oz_agent_sdk/resources/agent/schedules.py +++ b/src/oz_agent_sdk/resources/agent/schedules.py @@ -2,8 +2,6 @@ from __future__ import annotations -from typing_extensions import Literal - import httpx from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given @@ -56,7 +54,6 @@ def create( agent_config: AmbientAgentConfigParam | Omit = omit, agent_uid: str | Omit = omit, enabled: bool | Omit = omit, - mode: Literal["normal", "plan", "orchestrate"] | Omit = omit, prompt: str | Omit = omit, team: bool | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -84,9 +81,6 @@ def create( enabled: Whether the schedule should be active immediately - mode: Optional query mode applied to every triggered run. Defaults to `normal` when - omitted. The server does not infer mode from prompt prefixes such as `/plan`. - prompt: The prompt/instruction for the agent to execute. Required unless agent_config.skill_spec is provided. @@ -110,7 +104,6 @@ def create( "agent_config": agent_config, "agent_uid": agent_uid, "enabled": enabled, - "mode": mode, "prompt": prompt, "team": team, }, @@ -165,7 +158,6 @@ def update( name: str, agent_config: AmbientAgentConfigParam | Omit = omit, agent_uid: str | Omit = omit, - mode: Literal["normal", "plan", "orchestrate"] | Omit = omit, prompt: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. @@ -191,9 +183,6 @@ def update( agent_uid: Agent UID to use as the execution principal for this schedule. Only valid for team-owned schedules. - mode: Optional query mode applied to every triggered run. Defaults to `normal` when - omitted. The server does not infer mode from prompt prefixes such as `/plan`. - prompt: The prompt/instruction for the agent to execute. Required unless agent_config.skill_spec is provided. @@ -216,7 +205,6 @@ def update( "name": name, "agent_config": agent_config, "agent_uid": agent_uid, - "mode": mode, "prompt": prompt, }, schedule_update_params.ScheduleUpdateParams, @@ -384,7 +372,6 @@ async def create( agent_config: AmbientAgentConfigParam | Omit = omit, agent_uid: str | Omit = omit, enabled: bool | Omit = omit, - mode: Literal["normal", "plan", "orchestrate"] | Omit = omit, prompt: str | Omit = omit, team: bool | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -412,9 +399,6 @@ async def create( enabled: Whether the schedule should be active immediately - mode: Optional query mode applied to every triggered run. Defaults to `normal` when - omitted. The server does not infer mode from prompt prefixes such as `/plan`. - prompt: The prompt/instruction for the agent to execute. Required unless agent_config.skill_spec is provided. @@ -438,7 +422,6 @@ async def create( "agent_config": agent_config, "agent_uid": agent_uid, "enabled": enabled, - "mode": mode, "prompt": prompt, "team": team, }, @@ -493,7 +476,6 @@ async def update( name: str, agent_config: AmbientAgentConfigParam | Omit = omit, agent_uid: str | Omit = omit, - mode: Literal["normal", "plan", "orchestrate"] | Omit = omit, prompt: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. @@ -519,9 +501,6 @@ async def update( agent_uid: Agent UID to use as the execution principal for this schedule. Only valid for team-owned schedules. - mode: Optional query mode applied to every triggered run. Defaults to `normal` when - omitted. The server does not infer mode from prompt prefixes such as `/plan`. - prompt: The prompt/instruction for the agent to execute. Required unless agent_config.skill_spec is provided. @@ -544,7 +523,6 @@ async def update( "name": name, "agent_config": agent_config, "agent_uid": agent_uid, - "mode": mode, "prompt": prompt, }, schedule_update_params.ScheduleUpdateParams, diff --git a/src/oz_agent_sdk/types/agent/run_submit_followup_params.py b/src/oz_agent_sdk/types/agent/run_submit_followup_params.py index 004341f..4912cd1 100644 --- a/src/oz_agent_sdk/types/agent/run_submit_followup_params.py +++ b/src/oz_agent_sdk/types/agent/run_submit_followup_params.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing_extensions import Literal, Required, TypedDict +from typing_extensions import Required, TypedDict __all__ = ["RunSubmitFollowupParams"] @@ -10,10 +10,3 @@ class RunSubmitFollowupParams(TypedDict, total=False): message: Required[str] """The follow-up message to send to the run.""" - - mode: Literal["normal", "plan", "orchestrate"] - """Optional query mode for the follow-up. - - Defaults to `normal` when omitted. The server does not infer mode from prompt - prefixes such as `/plan`. - """ diff --git a/src/oz_agent_sdk/types/agent/schedule_create_params.py b/src/oz_agent_sdk/types/agent/schedule_create_params.py index 5127f04..8958fd0 100644 --- a/src/oz_agent_sdk/types/agent/schedule_create_params.py +++ b/src/oz_agent_sdk/types/agent/schedule_create_params.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing_extensions import Literal, Required, TypedDict +from typing_extensions import Required, TypedDict from ..ambient_agent_config_param import AmbientAgentConfigParam @@ -31,13 +31,6 @@ class ScheduleCreateParams(TypedDict, total=False): enabled: bool """Whether the schedule should be active immediately""" - mode: Literal["normal", "plan", "orchestrate"] - """Optional query mode applied to every triggered run. - - Defaults to `normal` when omitted. The server does not infer mode from prompt - prefixes such as `/plan`. - """ - prompt: str """ The prompt/instruction for the agent to execute. Required unless diff --git a/src/oz_agent_sdk/types/agent/schedule_update_params.py b/src/oz_agent_sdk/types/agent/schedule_update_params.py index 6ae2dbe..de71dc9 100644 --- a/src/oz_agent_sdk/types/agent/schedule_update_params.py +++ b/src/oz_agent_sdk/types/agent/schedule_update_params.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing_extensions import Literal, Required, TypedDict +from typing_extensions import Required, TypedDict from ..ambient_agent_config_param import AmbientAgentConfigParam @@ -28,13 +28,6 @@ class ScheduleUpdateParams(TypedDict, total=False): team-owned schedules. """ - mode: Literal["normal", "plan", "orchestrate"] - """Optional query mode applied to every triggered run. - - Defaults to `normal` when omitted. The server does not infer mode from prompt - prefixes such as `/plan`. - """ - prompt: str """ The prompt/instruction for the agent to execute. Required unless diff --git a/src/oz_agent_sdk/types/agent_run_params.py b/src/oz_agent_sdk/types/agent_run_params.py index d1f9941..5d185a5 100644 --- a/src/oz_agent_sdk/types/agent_run_params.py +++ b/src/oz_agent_sdk/types/agent_run_params.py @@ -3,7 +3,7 @@ from __future__ import annotations from typing import Union, Iterable -from typing_extensions import Literal, Required, Annotated, TypedDict +from typing_extensions import Required, Annotated, TypedDict from .._types import Base64FileInput from .._utils import PropertyInfo @@ -38,14 +38,6 @@ class AgentRunParams(TypedDict, total=False): interactive: bool """Whether the run should be interactive. If not set, defaults to false.""" - mode: Literal["normal", "plan", "orchestrate"] - """Optional query mode for the run. - - Defaults to `normal` when omitted. The server does not infer mode from prompt - prefixes such as `/plan`, so callers should pass this field explicitly to - request non-normal behavior. - """ - parent_run_id: str """ Optional run ID of the parent that spawned this run. Used for orchestration diff --git a/tests/api_resources/agent/test_runs.py b/tests/api_resources/agent/test_runs.py index 6af094f..cb77f95 100644 --- a/tests/api_resources/agent/test_runs.py +++ b/tests/api_resources/agent/test_runs.py @@ -213,16 +213,6 @@ def test_method_submit_followup(self, client: OzAPI) -> None: ) assert_matches_type(object, run, path=["response"]) - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_method_submit_followup_with_all_params(self, client: OzAPI) -> None: - run = client.agent.runs.submit_followup( - run_id="runId", - message="message", - mode="normal", - ) - assert_matches_type(object, run, path=["response"]) - @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_raw_response_submit_followup(self, client: OzAPI) -> None: @@ -457,16 +447,6 @@ async def test_method_submit_followup(self, async_client: AsyncOzAPI) -> None: ) assert_matches_type(object, run, path=["response"]) - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_method_submit_followup_with_all_params(self, async_client: AsyncOzAPI) -> None: - run = await async_client.agent.runs.submit_followup( - run_id="runId", - message="message", - mode="normal", - ) - assert_matches_type(object, run, path=["response"]) - @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_raw_response_submit_followup(self, async_client: AsyncOzAPI) -> None: diff --git a/tests/api_resources/agent/test_schedules.py b/tests/api_resources/agent/test_schedules.py index 0beb0e2..b37e9bc 100644 --- a/tests/api_resources/agent/test_schedules.py +++ b/tests/api_resources/agent/test_schedules.py @@ -61,7 +61,6 @@ def test_method_create_with_all_params(self, client: OzAPI) -> None: }, agent_uid="agent_uid", enabled=True, - mode="normal", prompt="Review open pull requests and provide feedback", team=True, ) @@ -180,7 +179,6 @@ def test_method_update_with_all_params(self, client: OzAPI) -> None: "worker_host": "worker_host", }, agent_uid="agent_uid", - mode="normal", prompt="prompt", ) assert_matches_type(ScheduledAgentItem, schedule, path=["response"]) @@ -428,7 +426,6 @@ async def test_method_create_with_all_params(self, async_client: AsyncOzAPI) -> }, agent_uid="agent_uid", enabled=True, - mode="normal", prompt="Review open pull requests and provide feedback", team=True, ) @@ -547,7 +544,6 @@ async def test_method_update_with_all_params(self, async_client: AsyncOzAPI) -> "worker_host": "worker_host", }, agent_uid="agent_uid", - mode="normal", prompt="prompt", ) assert_matches_type(ScheduledAgentItem, schedule, path=["response"]) diff --git a/tests/api_resources/test_agent.py b/tests/api_resources/test_agent.py index a10a54e..78b54a4 100644 --- a/tests/api_resources/test_agent.py +++ b/tests/api_resources/test_agent.py @@ -182,7 +182,6 @@ def test_method_run_with_all_params(self, client: OzAPI) -> None: }, conversation_id="conversation_id", interactive=True, - mode="normal", parent_run_id="parent_run_id", prompt="prompt", skill="skill", @@ -379,7 +378,6 @@ async def test_method_run_with_all_params(self, async_client: AsyncOzAPI) -> Non }, conversation_id="conversation_id", interactive=True, - mode="normal", parent_run_id="parent_run_id", prompt="prompt", skill="skill", From db0e98ca667b0cfe5b8ab182db5b1d4a19584113 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 30 Apr 2026 19:36:43 +0000 Subject: [PATCH 52/56] feat: Apply service-account secrets at run creation --- .stats.yml | 6 +++--- src/oz_agent_sdk/resources/agent/agent_.py | 6 ++++-- src/oz_agent_sdk/types/agent/agent_create_params.py | 3 ++- src/oz_agent_sdk/types/ambient_agent_config.py | 3 +-- src/oz_agent_sdk/types/ambient_agent_config_param.py | 3 +-- 5 files changed, 11 insertions(+), 10 deletions(-) diff --git a/.stats.yml b/.stats.yml index d40dcac..baef5f7 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 22 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta/warp-api-3eeaadc6a0c1eefbc3c3a7e1212b2be5c061bad7bcabedf5ee30eb2a7f992505.yml -openapi_spec_hash: a071b7c932453dc870e7e6cf39df0535 -config_hash: c15534df6c8d861059e44d9dd5483b3f +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta/warp-api-f74133adb6e546317af84cb055755fb9fdaa4b9d5b4285bf0e25c5da2922b737.yml +openapi_spec_hash: 30edc04bccac2c6d4d1228807a372023 +config_hash: 44a1e8f98607a5cf03815a63bae63453 diff --git a/src/oz_agent_sdk/resources/agent/agent_.py b/src/oz_agent_sdk/resources/agent/agent_.py index b3e7a57..ab7835e 100644 --- a/src/oz_agent_sdk/resources/agent/agent_.py +++ b/src/oz_agent_sdk/resources/agent/agent_.py @@ -71,7 +71,8 @@ def create( description: Optional description of the agent secrets: Optional list of secrets associated with the agent. Duplicate names within a - single request are rejected. + single request are rejected. Each entry is unioned into the run-time secret + scope when the agent executes. skills: Optional list of skill specs to associate with the agent. Format: @@ -269,7 +270,8 @@ async def create( description: Optional description of the agent secrets: Optional list of secrets associated with the agent. Duplicate names within a - single request are rejected. + single request are rejected. Each entry is unioned into the run-time secret + scope when the agent executes. skills: Optional list of skill specs to associate with the agent. Format: diff --git a/src/oz_agent_sdk/types/agent/agent_create_params.py b/src/oz_agent_sdk/types/agent/agent_create_params.py index 59fc08d..5f31e19 100644 --- a/src/oz_agent_sdk/types/agent/agent_create_params.py +++ b/src/oz_agent_sdk/types/agent/agent_create_params.py @@ -20,7 +20,8 @@ class AgentCreateParams(TypedDict, total=False): secrets: Iterable[Secret] """ Optional list of secrets associated with the agent. Duplicate names within a - single request are rejected. + single request are rejected. Each entry is unioned into the run-time secret + scope when the agent executes. """ skills: SequenceNotStr[str] diff --git a/src/oz_agent_sdk/types/ambient_agent_config.py b/src/oz_agent_sdk/types/ambient_agent_config.py index 148931d..b90112c 100644 --- a/src/oz_agent_sdk/types/ambient_agent_config.py +++ b/src/oz_agent_sdk/types/ambient_agent_config.py @@ -17,13 +17,12 @@ class Harness(BaseModel): Default (nil/empty) uses Warp's built-in harness. """ - type: Optional[Literal["oz", "claude", "gemini", "codex"]] = None + type: Optional[Literal["oz", "claude", "gemini"]] = None """The harness type identifier. - oz: Warp's built-in harness (default) - claude: Claude Code harness - gemini: Gemini CLI harness - - codex: Codex CLI harness """ diff --git a/src/oz_agent_sdk/types/ambient_agent_config_param.py b/src/oz_agent_sdk/types/ambient_agent_config_param.py index f4c6ee4..9031e46 100644 --- a/src/oz_agent_sdk/types/ambient_agent_config_param.py +++ b/src/oz_agent_sdk/types/ambient_agent_config_param.py @@ -16,13 +16,12 @@ class Harness(TypedDict, total=False): Default (nil/empty) uses Warp's built-in harness. """ - type: Literal["oz", "claude", "gemini", "codex"] + type: Literal["oz", "claude", "gemini"] """The harness type identifier. - oz: Warp's built-in harness (default) - claude: Claude Code harness - gemini: Gemini CLI harness - - codex: Codex CLI harness """ From fd17af10c72ed943e4023a4e9e071ac7b8db08f7 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 30 Apr 2026 20:56:14 +0000 Subject: [PATCH 53/56] chore(internal): reformat pyproject.toml --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 01da747..ae72878 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -154,7 +154,7 @@ show_error_codes = true # # We also exclude our `tests` as mypy doesn't always infer # types correctly and Pyright will still catch any type errors. -exclude = ['src/oz_agent_sdk/_files.py', '_dev/.*.py', 'tests/.*'] +exclude = ["src/oz_agent_sdk/_files.py", "_dev/.*.py", "tests/.*"] strict_equality = true implicit_reexport = true From 654da597a10a63048c5a34ca67c9d6684c72b688 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 30 Apr 2026 21:34:04 +0000 Subject: [PATCH 54/56] feat(api): api update --- .stats.yml | 6 +++--- src/oz_agent_sdk/resources/agent/agent_.py | 6 ++---- src/oz_agent_sdk/types/agent/agent_create_params.py | 3 +-- src/oz_agent_sdk/types/ambient_agent_config.py | 3 ++- src/oz_agent_sdk/types/ambient_agent_config_param.py | 3 ++- 5 files changed, 10 insertions(+), 11 deletions(-) diff --git a/.stats.yml b/.stats.yml index baef5f7..d40dcac 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 22 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta/warp-api-f74133adb6e546317af84cb055755fb9fdaa4b9d5b4285bf0e25c5da2922b737.yml -openapi_spec_hash: 30edc04bccac2c6d4d1228807a372023 -config_hash: 44a1e8f98607a5cf03815a63bae63453 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta/warp-api-3eeaadc6a0c1eefbc3c3a7e1212b2be5c061bad7bcabedf5ee30eb2a7f992505.yml +openapi_spec_hash: a071b7c932453dc870e7e6cf39df0535 +config_hash: c15534df6c8d861059e44d9dd5483b3f diff --git a/src/oz_agent_sdk/resources/agent/agent_.py b/src/oz_agent_sdk/resources/agent/agent_.py index ab7835e..b3e7a57 100644 --- a/src/oz_agent_sdk/resources/agent/agent_.py +++ b/src/oz_agent_sdk/resources/agent/agent_.py @@ -71,8 +71,7 @@ def create( description: Optional description of the agent secrets: Optional list of secrets associated with the agent. Duplicate names within a - single request are rejected. Each entry is unioned into the run-time secret - scope when the agent executes. + single request are rejected. skills: Optional list of skill specs to associate with the agent. Format: @@ -270,8 +269,7 @@ async def create( description: Optional description of the agent secrets: Optional list of secrets associated with the agent. Duplicate names within a - single request are rejected. Each entry is unioned into the run-time secret - scope when the agent executes. + single request are rejected. skills: Optional list of skill specs to associate with the agent. Format: diff --git a/src/oz_agent_sdk/types/agent/agent_create_params.py b/src/oz_agent_sdk/types/agent/agent_create_params.py index 5f31e19..59fc08d 100644 --- a/src/oz_agent_sdk/types/agent/agent_create_params.py +++ b/src/oz_agent_sdk/types/agent/agent_create_params.py @@ -20,8 +20,7 @@ class AgentCreateParams(TypedDict, total=False): secrets: Iterable[Secret] """ Optional list of secrets associated with the agent. Duplicate names within a - single request are rejected. Each entry is unioned into the run-time secret - scope when the agent executes. + single request are rejected. """ skills: SequenceNotStr[str] diff --git a/src/oz_agent_sdk/types/ambient_agent_config.py b/src/oz_agent_sdk/types/ambient_agent_config.py index b90112c..148931d 100644 --- a/src/oz_agent_sdk/types/ambient_agent_config.py +++ b/src/oz_agent_sdk/types/ambient_agent_config.py @@ -17,12 +17,13 @@ class Harness(BaseModel): Default (nil/empty) uses Warp's built-in harness. """ - type: Optional[Literal["oz", "claude", "gemini"]] = None + type: Optional[Literal["oz", "claude", "gemini", "codex"]] = None """The harness type identifier. - oz: Warp's built-in harness (default) - claude: Claude Code harness - gemini: Gemini CLI harness + - codex: Codex CLI harness """ diff --git a/src/oz_agent_sdk/types/ambient_agent_config_param.py b/src/oz_agent_sdk/types/ambient_agent_config_param.py index 9031e46..f4c6ee4 100644 --- a/src/oz_agent_sdk/types/ambient_agent_config_param.py +++ b/src/oz_agent_sdk/types/ambient_agent_config_param.py @@ -16,12 +16,13 @@ class Harness(TypedDict, total=False): Default (nil/empty) uses Warp's built-in harness. """ - type: Literal["oz", "claude", "gemini"] + type: Literal["oz", "claude", "gemini", "codex"] """The harness type identifier. - oz: Warp's built-in harness (default) - claude: Claude Code harness - gemini: Gemini CLI harness + - codex: Codex CLI harness """ From 4a0d4fc0711f3fe0d3168c3f5f7ec2176d5b0010 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sun, 3 May 2026 07:42:12 +0000 Subject: [PATCH 55/56] feat(api): api update --- .stats.yml | 6 ++--- src/oz_agent_sdk/resources/agent/agent.py | 12 ++++++++++ src/oz_agent_sdk/resources/agent/agent_.py | 6 +++-- src/oz_agent_sdk/resources/agent/runs.py | 24 +++++++++++++++++-- src/oz_agent_sdk/resources/agent/schedules.py | 22 +++++++++++++++++ .../types/agent/agent_create_params.py | 3 ++- .../types/agent/run_submit_followup_params.py | 9 ++++++- .../types/agent/schedule_create_params.py | 9 ++++++- .../types/agent/schedule_update_params.py | 9 ++++++- src/oz_agent_sdk/types/agent_run_params.py | 10 +++++++- tests/api_resources/agent/test_runs.py | 20 ++++++++++++++++ tests/api_resources/agent/test_schedules.py | 4 ++++ tests/api_resources/test_agent.py | 2 ++ 13 files changed, 124 insertions(+), 12 deletions(-) diff --git a/.stats.yml b/.stats.yml index d40dcac..6d1f217 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 22 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta/warp-api-3eeaadc6a0c1eefbc3c3a7e1212b2be5c061bad7bcabedf5ee30eb2a7f992505.yml -openapi_spec_hash: a071b7c932453dc870e7e6cf39df0535 -config_hash: c15534df6c8d861059e44d9dd5483b3f +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta/warp-api-c58f2ee13e97acdf607650e199cb1377d2767c6bd6183b5f1212fa2666bb5f04.yml +openapi_spec_hash: 19295b9e19b2ab3093087d9b11a6095f +config_hash: f52e7636f248f25c4ea0b086e7326816 diff --git a/src/oz_agent_sdk/resources/agent/agent.py b/src/oz_agent_sdk/resources/agent/agent.py index ff5f385..8e8d1d0 100644 --- a/src/oz_agent_sdk/resources/agent/agent.py +++ b/src/oz_agent_sdk/resources/agent/agent.py @@ -262,6 +262,7 @@ def run( config: AmbientAgentConfigParam | Omit = omit, conversation_id: str | Omit = omit, interactive: bool | Omit = omit, + mode: Literal["normal", "plan", "orchestrate"] | Omit = omit, parent_run_id: str | Omit = omit, prompt: str | Omit = omit, skill: str | Omit = omit, @@ -293,6 +294,10 @@ def run( interactive: Whether the run should be interactive. If not set, defaults to false. + mode: Optional query mode for the run. Defaults to `normal` when omitted. The server + does not infer mode from prompt prefixes such as `/plan`, so callers should pass + this field explicitly to request non-normal behavior. + parent_run_id: Optional run ID of the parent that spawned this run. Used for orchestration hierarchies. @@ -329,6 +334,7 @@ def run( "config": config, "conversation_id": conversation_id, "interactive": interactive, + "mode": mode, "parent_run_id": parent_run_id, "prompt": prompt, "skill": skill, @@ -547,6 +553,7 @@ async def run( config: AmbientAgentConfigParam | Omit = omit, conversation_id: str | Omit = omit, interactive: bool | Omit = omit, + mode: Literal["normal", "plan", "orchestrate"] | Omit = omit, parent_run_id: str | Omit = omit, prompt: str | Omit = omit, skill: str | Omit = omit, @@ -578,6 +585,10 @@ async def run( interactive: Whether the run should be interactive. If not set, defaults to false. + mode: Optional query mode for the run. Defaults to `normal` when omitted. The server + does not infer mode from prompt prefixes such as `/plan`, so callers should pass + this field explicitly to request non-normal behavior. + parent_run_id: Optional run ID of the parent that spawned this run. Used for orchestration hierarchies. @@ -614,6 +625,7 @@ async def run( "config": config, "conversation_id": conversation_id, "interactive": interactive, + "mode": mode, "parent_run_id": parent_run_id, "prompt": prompt, "skill": skill, diff --git a/src/oz_agent_sdk/resources/agent/agent_.py b/src/oz_agent_sdk/resources/agent/agent_.py index b3e7a57..ab7835e 100644 --- a/src/oz_agent_sdk/resources/agent/agent_.py +++ b/src/oz_agent_sdk/resources/agent/agent_.py @@ -71,7 +71,8 @@ def create( description: Optional description of the agent secrets: Optional list of secrets associated with the agent. Duplicate names within a - single request are rejected. + single request are rejected. Each entry is unioned into the run-time secret + scope when the agent executes. skills: Optional list of skill specs to associate with the agent. Format: @@ -269,7 +270,8 @@ async def create( description: Optional description of the agent secrets: Optional list of secrets associated with the agent. Duplicate names within a - single request are rejected. + single request are rejected. Each entry is unioned into the run-time secret + scope when the agent executes. skills: Optional list of skill specs to associate with the agent. Format: diff --git a/src/oz_agent_sdk/resources/agent/runs.py b/src/oz_agent_sdk/resources/agent/runs.py index 6b1ab06..c2d5075 100644 --- a/src/oz_agent_sdk/resources/agent/runs.py +++ b/src/oz_agent_sdk/resources/agent/runs.py @@ -302,6 +302,7 @@ def submit_followup( run_id: str, *, message: str, + mode: Literal["normal", "plan", "orchestrate"] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -319,6 +320,9 @@ def submit_followup( Args: message: The follow-up message to send to the run. + mode: Optional query mode for the follow-up. Defaults to `normal` when omitted. The + server does not infer mode from prompt prefixes such as `/plan`. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -331,7 +335,13 @@ def submit_followup( raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}") return self._post( path_template("/agent/runs/{run_id}/followups", run_id=run_id), - body=maybe_transform({"message": message}, run_submit_followup_params.RunSubmitFollowupParams), + body=maybe_transform( + { + "message": message, + "mode": mode, + }, + run_submit_followup_params.RunSubmitFollowupParams, + ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -612,6 +622,7 @@ async def submit_followup( run_id: str, *, message: str, + mode: Literal["normal", "plan", "orchestrate"] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -629,6 +640,9 @@ async def submit_followup( Args: message: The follow-up message to send to the run. + mode: Optional query mode for the follow-up. Defaults to `normal` when omitted. The + server does not infer mode from prompt prefixes such as `/plan`. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -641,7 +655,13 @@ async def submit_followup( raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}") return await self._post( path_template("/agent/runs/{run_id}/followups", run_id=run_id), - body=await async_maybe_transform({"message": message}, run_submit_followup_params.RunSubmitFollowupParams), + body=await async_maybe_transform( + { + "message": message, + "mode": mode, + }, + run_submit_followup_params.RunSubmitFollowupParams, + ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/oz_agent_sdk/resources/agent/schedules.py b/src/oz_agent_sdk/resources/agent/schedules.py index b29a979..2d0724f 100644 --- a/src/oz_agent_sdk/resources/agent/schedules.py +++ b/src/oz_agent_sdk/resources/agent/schedules.py @@ -2,6 +2,8 @@ from __future__ import annotations +from typing_extensions import Literal + import httpx from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given @@ -54,6 +56,7 @@ def create( agent_config: AmbientAgentConfigParam | Omit = omit, agent_uid: str | Omit = omit, enabled: bool | Omit = omit, + mode: Literal["normal", "plan", "orchestrate"] | Omit = omit, prompt: str | Omit = omit, team: bool | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -81,6 +84,9 @@ def create( enabled: Whether the schedule should be active immediately + mode: Optional query mode applied to every triggered run. Defaults to `normal` when + omitted. The server does not infer mode from prompt prefixes such as `/plan`. + prompt: The prompt/instruction for the agent to execute. Required unless agent_config.skill_spec is provided. @@ -104,6 +110,7 @@ def create( "agent_config": agent_config, "agent_uid": agent_uid, "enabled": enabled, + "mode": mode, "prompt": prompt, "team": team, }, @@ -158,6 +165,7 @@ def update( name: str, agent_config: AmbientAgentConfigParam | Omit = omit, agent_uid: str | Omit = omit, + mode: Literal["normal", "plan", "orchestrate"] | Omit = omit, prompt: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. @@ -183,6 +191,9 @@ def update( agent_uid: Agent UID to use as the execution principal for this schedule. Only valid for team-owned schedules. + mode: Optional query mode applied to every triggered run. Defaults to `normal` when + omitted. The server does not infer mode from prompt prefixes such as `/plan`. + prompt: The prompt/instruction for the agent to execute. Required unless agent_config.skill_spec is provided. @@ -205,6 +216,7 @@ def update( "name": name, "agent_config": agent_config, "agent_uid": agent_uid, + "mode": mode, "prompt": prompt, }, schedule_update_params.ScheduleUpdateParams, @@ -372,6 +384,7 @@ async def create( agent_config: AmbientAgentConfigParam | Omit = omit, agent_uid: str | Omit = omit, enabled: bool | Omit = omit, + mode: Literal["normal", "plan", "orchestrate"] | Omit = omit, prompt: str | Omit = omit, team: bool | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -399,6 +412,9 @@ async def create( enabled: Whether the schedule should be active immediately + mode: Optional query mode applied to every triggered run. Defaults to `normal` when + omitted. The server does not infer mode from prompt prefixes such as `/plan`. + prompt: The prompt/instruction for the agent to execute. Required unless agent_config.skill_spec is provided. @@ -422,6 +438,7 @@ async def create( "agent_config": agent_config, "agent_uid": agent_uid, "enabled": enabled, + "mode": mode, "prompt": prompt, "team": team, }, @@ -476,6 +493,7 @@ async def update( name: str, agent_config: AmbientAgentConfigParam | Omit = omit, agent_uid: str | Omit = omit, + mode: Literal["normal", "plan", "orchestrate"] | Omit = omit, prompt: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. @@ -501,6 +519,9 @@ async def update( agent_uid: Agent UID to use as the execution principal for this schedule. Only valid for team-owned schedules. + mode: Optional query mode applied to every triggered run. Defaults to `normal` when + omitted. The server does not infer mode from prompt prefixes such as `/plan`. + prompt: The prompt/instruction for the agent to execute. Required unless agent_config.skill_spec is provided. @@ -523,6 +544,7 @@ async def update( "name": name, "agent_config": agent_config, "agent_uid": agent_uid, + "mode": mode, "prompt": prompt, }, schedule_update_params.ScheduleUpdateParams, diff --git a/src/oz_agent_sdk/types/agent/agent_create_params.py b/src/oz_agent_sdk/types/agent/agent_create_params.py index 59fc08d..5f31e19 100644 --- a/src/oz_agent_sdk/types/agent/agent_create_params.py +++ b/src/oz_agent_sdk/types/agent/agent_create_params.py @@ -20,7 +20,8 @@ class AgentCreateParams(TypedDict, total=False): secrets: Iterable[Secret] """ Optional list of secrets associated with the agent. Duplicate names within a - single request are rejected. + single request are rejected. Each entry is unioned into the run-time secret + scope when the agent executes. """ skills: SequenceNotStr[str] diff --git a/src/oz_agent_sdk/types/agent/run_submit_followup_params.py b/src/oz_agent_sdk/types/agent/run_submit_followup_params.py index 4912cd1..004341f 100644 --- a/src/oz_agent_sdk/types/agent/run_submit_followup_params.py +++ b/src/oz_agent_sdk/types/agent/run_submit_followup_params.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing_extensions import Required, TypedDict +from typing_extensions import Literal, Required, TypedDict __all__ = ["RunSubmitFollowupParams"] @@ -10,3 +10,10 @@ class RunSubmitFollowupParams(TypedDict, total=False): message: Required[str] """The follow-up message to send to the run.""" + + mode: Literal["normal", "plan", "orchestrate"] + """Optional query mode for the follow-up. + + Defaults to `normal` when omitted. The server does not infer mode from prompt + prefixes such as `/plan`. + """ diff --git a/src/oz_agent_sdk/types/agent/schedule_create_params.py b/src/oz_agent_sdk/types/agent/schedule_create_params.py index 8958fd0..5127f04 100644 --- a/src/oz_agent_sdk/types/agent/schedule_create_params.py +++ b/src/oz_agent_sdk/types/agent/schedule_create_params.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing_extensions import Required, TypedDict +from typing_extensions import Literal, Required, TypedDict from ..ambient_agent_config_param import AmbientAgentConfigParam @@ -31,6 +31,13 @@ class ScheduleCreateParams(TypedDict, total=False): enabled: bool """Whether the schedule should be active immediately""" + mode: Literal["normal", "plan", "orchestrate"] + """Optional query mode applied to every triggered run. + + Defaults to `normal` when omitted. The server does not infer mode from prompt + prefixes such as `/plan`. + """ + prompt: str """ The prompt/instruction for the agent to execute. Required unless diff --git a/src/oz_agent_sdk/types/agent/schedule_update_params.py b/src/oz_agent_sdk/types/agent/schedule_update_params.py index de71dc9..6ae2dbe 100644 --- a/src/oz_agent_sdk/types/agent/schedule_update_params.py +++ b/src/oz_agent_sdk/types/agent/schedule_update_params.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing_extensions import Required, TypedDict +from typing_extensions import Literal, Required, TypedDict from ..ambient_agent_config_param import AmbientAgentConfigParam @@ -28,6 +28,13 @@ class ScheduleUpdateParams(TypedDict, total=False): team-owned schedules. """ + mode: Literal["normal", "plan", "orchestrate"] + """Optional query mode applied to every triggered run. + + Defaults to `normal` when omitted. The server does not infer mode from prompt + prefixes such as `/plan`. + """ + prompt: str """ The prompt/instruction for the agent to execute. Required unless diff --git a/src/oz_agent_sdk/types/agent_run_params.py b/src/oz_agent_sdk/types/agent_run_params.py index 5d185a5..d1f9941 100644 --- a/src/oz_agent_sdk/types/agent_run_params.py +++ b/src/oz_agent_sdk/types/agent_run_params.py @@ -3,7 +3,7 @@ from __future__ import annotations from typing import Union, Iterable -from typing_extensions import Required, Annotated, TypedDict +from typing_extensions import Literal, Required, Annotated, TypedDict from .._types import Base64FileInput from .._utils import PropertyInfo @@ -38,6 +38,14 @@ class AgentRunParams(TypedDict, total=False): interactive: bool """Whether the run should be interactive. If not set, defaults to false.""" + mode: Literal["normal", "plan", "orchestrate"] + """Optional query mode for the run. + + Defaults to `normal` when omitted. The server does not infer mode from prompt + prefixes such as `/plan`, so callers should pass this field explicitly to + request non-normal behavior. + """ + parent_run_id: str """ Optional run ID of the parent that spawned this run. Used for orchestration diff --git a/tests/api_resources/agent/test_runs.py b/tests/api_resources/agent/test_runs.py index cb77f95..6af094f 100644 --- a/tests/api_resources/agent/test_runs.py +++ b/tests/api_resources/agent/test_runs.py @@ -213,6 +213,16 @@ def test_method_submit_followup(self, client: OzAPI) -> None: ) assert_matches_type(object, run, path=["response"]) + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_submit_followup_with_all_params(self, client: OzAPI) -> None: + run = client.agent.runs.submit_followup( + run_id="runId", + message="message", + mode="normal", + ) + assert_matches_type(object, run, path=["response"]) + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_raw_response_submit_followup(self, client: OzAPI) -> None: @@ -447,6 +457,16 @@ async def test_method_submit_followup(self, async_client: AsyncOzAPI) -> None: ) assert_matches_type(object, run, path=["response"]) + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_submit_followup_with_all_params(self, async_client: AsyncOzAPI) -> None: + run = await async_client.agent.runs.submit_followup( + run_id="runId", + message="message", + mode="normal", + ) + assert_matches_type(object, run, path=["response"]) + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_raw_response_submit_followup(self, async_client: AsyncOzAPI) -> None: diff --git a/tests/api_resources/agent/test_schedules.py b/tests/api_resources/agent/test_schedules.py index b37e9bc..0beb0e2 100644 --- a/tests/api_resources/agent/test_schedules.py +++ b/tests/api_resources/agent/test_schedules.py @@ -61,6 +61,7 @@ def test_method_create_with_all_params(self, client: OzAPI) -> None: }, agent_uid="agent_uid", enabled=True, + mode="normal", prompt="Review open pull requests and provide feedback", team=True, ) @@ -179,6 +180,7 @@ def test_method_update_with_all_params(self, client: OzAPI) -> None: "worker_host": "worker_host", }, agent_uid="agent_uid", + mode="normal", prompt="prompt", ) assert_matches_type(ScheduledAgentItem, schedule, path=["response"]) @@ -426,6 +428,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncOzAPI) -> }, agent_uid="agent_uid", enabled=True, + mode="normal", prompt="Review open pull requests and provide feedback", team=True, ) @@ -544,6 +547,7 @@ async def test_method_update_with_all_params(self, async_client: AsyncOzAPI) -> "worker_host": "worker_host", }, agent_uid="agent_uid", + mode="normal", prompt="prompt", ) assert_matches_type(ScheduledAgentItem, schedule, path=["response"]) diff --git a/tests/api_resources/test_agent.py b/tests/api_resources/test_agent.py index 78b54a4..a10a54e 100644 --- a/tests/api_resources/test_agent.py +++ b/tests/api_resources/test_agent.py @@ -182,6 +182,7 @@ def test_method_run_with_all_params(self, client: OzAPI) -> None: }, conversation_id="conversation_id", interactive=True, + mode="normal", parent_run_id="parent_run_id", prompt="prompt", skill="skill", @@ -378,6 +379,7 @@ async def test_method_run_with_all_params(self, async_client: AsyncOzAPI) -> Non }, conversation_id="conversation_id", interactive=True, + mode="normal", parent_run_id="parent_run_id", prompt="prompt", skill="skill", From 1ea3376c0e2783713d51159cd34e71f18663ac4e Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sun, 3 May 2026 07:42:49 +0000 Subject: [PATCH 56/56] release: 0.12.0 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 65 +++++++++++++++++++++++++++++++++++ pyproject.toml | 2 +- src/oz_agent_sdk/_version.py | 2 +- 4 files changed, 68 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index f7014c3..a713055 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.11.0" + ".": "0.12.0" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 543cbc1..f0f25b7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,70 @@ # Changelog +## 0.12.0 (2026-05-03) + +Full Changelog: [v0.11.0...v0.12.0](https://github.com/warpdotdev/oz-sdk-python/compare/v0.11.0...v0.12.0) + +### Features + +* [APP-3106] Specs: Explicit QueryMode for cloud agent run creation ([1d4e049](https://github.com/warpdotdev/oz-sdk-python/commit/1d4e049e5c64fdfe1f8eff8dbf7bc8256ed98182)) +* [REMOTE-1481] [3/N] Add executor filter to run list API ([2dbc229](https://github.com/warpdotdev/oz-sdk-python/commit/2dbc22949c6c9475a31e74cba5eadecb018277f3)) +* Accept and persist executor on schedule and integration create/update APIs ([a8500aa](https://github.com/warpdotdev/oz-sdk-python/commit/a8500aa0b3e74221cd931b01d7e7569ad191d1f3)) +* Add API support for public access on oz session link ([df940e0](https://github.com/warpdotdev/oz-sdk-python/commit/df940e09b23d2cc3d314407a8826f722b9428dca)) +* Add Codex as a third-party Oz harness. ([898e18f](https://github.com/warpdotdev/oz-sdk-python/commit/898e18f8e26a2064d3bb3bdda83c08adeb91088d)) +* Add Gemini as a third-party Oz harness. ([0128722](https://github.com/warpdotdev/oz-sdk-python/commit/0128722383f87f6d5a73fd0ecafc4206a3013342)) +* Add parent_run_id filter to List runs endpoint ([33cf04c](https://github.com/warpdotdev/oz-sdk-python/commit/33cf04c0777d53059f8a3c73b925b468276aba2a)) +* Add system prompt to resolve-prompt for harnesses. ([2b7afab](https://github.com/warpdotdev/oz-sdk-python/commit/2b7afabf4a54764ab162ac32f4dbe7fe4274ba72)) +* Add trigger URL to task source. ([9662dbe](https://github.com/warpdotdev/oz-sdk-python/commit/9662dbe10cc5392271b3e56c35cb8ef95ec80eed)) +* Add worker_host to AgentListSource in OpenAPI spec ([ec0982c](https://github.com/warpdotdev/oz-sdk-python/commit/ec0982ce786b2380ab89aa7298b28998c6eade46)) +* **api:** api update ([4a0d4fc](https://github.com/warpdotdev/oz-sdk-python/commit/4a0d4fc0711f3fe0d3168c3f5f7ec2176d5b0010)) +* **api:** api update ([654da59](https://github.com/warpdotdev/oz-sdk-python/commit/654da597a10a63048c5a34ca67c9d6684c72b688)) +* **api:** api update ([86d389c](https://github.com/warpdotdev/oz-sdk-python/commit/86d389c610fb2b89d7fcd17ebfd06610ef2b0b90)) +* **api:** api update ([15d68a1](https://github.com/warpdotdev/oz-sdk-python/commit/15d68a1db8178fd9cb5fae456ca6f341b60fd1e7)) +* **api:** api update ([54f5cdc](https://github.com/warpdotdev/oz-sdk-python/commit/54f5cdc819015611f7214b8ac6632df1cebf857d)) +* **api:** api update ([e290d3b](https://github.com/warpdotdev/oz-sdk-python/commit/e290d3b8cd2e8bd10a713e41992e282b704c624e)) +* **api:** api update ([35565ad](https://github.com/warpdotdev/oz-sdk-python/commit/35565ada13a8a16f9117b3ca0c12279d1708d184)) +* **api:** api update ([9cf2d03](https://github.com/warpdotdev/oz-sdk-python/commit/9cf2d0352242be5c7075fe971561cc36aaaf6e77)) +* **api:** api update ([ed871aa](https://github.com/warpdotdev/oz-sdk-python/commit/ed871aac657265138112d98be757a0de48796e02)) +* **api:** api update ([a44c455](https://github.com/warpdotdev/oz-sdk-python/commit/a44c455cb949e69b05f33f38571b40d9c0caed36)) +* **api:** api update ([e24ba64](https://github.com/warpdotdev/oz-sdk-python/commit/e24ba644c9d3624019f240fd43f51079adf7d8d4)) +* **api:** api update ([e5aea21](https://github.com/warpdotdev/oz-sdk-python/commit/e5aea2192017b1758d7b32d1e855015ce29e93ca)) +* **api:** api update ([f94b38b](https://github.com/warpdotdev/oz-sdk-python/commit/f94b38b2ffaf344a198e89ad7ace1d7b8e93c300)) +* **api:** api update ([7f419fa](https://github.com/warpdotdev/oz-sdk-python/commit/7f419faa01908e1b4a613ec2bdd708aed1a05871)) +* **api:** api update ([116f06e](https://github.com/warpdotdev/oz-sdk-python/commit/116f06e5c63e8d015e7dfea47fc22ede53ebb84e)) +* **api:** api update ([66c8521](https://github.com/warpdotdev/oz-sdk-python/commit/66c852194f355cedca2b34b944c398e796f064ab)) +* **api:** api update ([ebd2c55](https://github.com/warpdotdev/oz-sdk-python/commit/ebd2c5520128722d88285aea9dd0caf3242d9a31)) +* **api:** api update ([1ffc53b](https://github.com/warpdotdev/oz-sdk-python/commit/1ffc53b4d69eeb8060faac1903f1ba25f7a4c443)) +* **api:** api update ([cf28804](https://github.com/warpdotdev/oz-sdk-python/commit/cf288045d369ed927db45ac5e5ebd994ccebb547)) +* **api:** api update ([a6d82f1](https://github.com/warpdotdev/oz-sdk-python/commit/a6d82f1a71ad8e0ff5f10c43cc81938babc1444e)) +* **api:** api update ([b9872f2](https://github.com/warpdotdev/oz-sdk-python/commit/b9872f2642191ef6e1d4d5d3542a08f9e2784b9e)) +* **api:** api update ([0ef9c8f](https://github.com/warpdotdev/oz-sdk-python/commit/0ef9c8f483269d203a3edc7b5805f48f4263eb2f)) +* Apply service-account secrets at run creation ([db0e98c](https://github.com/warpdotdev/oz-sdk-python/commit/db0e98ca667b0cfe5b8ab182db5b1d4a19584113)) +* Extend service account API to support skills + secrets ([caf9c45](https://github.com/warpdotdev/oz-sdk-python/commit/caf9c4539ad1718ed194619ebf26425217265706)) +* implement server-side cloud-to-cloud handoff for agent follow-ups (REMOTE-1290) ([eb873a6](https://github.com/warpdotdev/oz-sdk-python/commit/eb873a6092aa1792ca6c23f5d27a7ee66c225ea0)) +* Inject auth secrets via ambient agent config. ([6032a0c](https://github.com/warpdotdev/oz-sdk-python/commit/6032a0ccfe2ce669ce1f815ad853b912d4ca575e)) +* Make conversation/session redirects public ([4c23bb6](https://github.com/warpdotdev/oz-sdk-python/commit/4c23bb6ebec32b5022a1731284d3e07b81a9f5ae)) +* Memory data model scaffolding. ([4ccbe03](https://github.com/warpdotdev/oz-sdk-python/commit/4ccbe0371e7bf02c454a14bc8bc2d412dcebf290)) +* support setting headers via env ([d3b4755](https://github.com/warpdotdev/oz-sdk-python/commit/d3b4755c7447d915a4e11be043b21b859f6c028d)) +* Update public API and graphql to support creating multiple service accounts and API keys ([8d537bc](https://github.com/warpdotdev/oz-sdk-python/commit/8d537bcbe75b344427bd04e5406ab066769f580a)) + + +### Bug Fixes + +* ensure file data are only sent as 1 parameter ([6720ea9](https://github.com/warpdotdev/oz-sdk-python/commit/6720ea9331a945cf2d030e20b8851a223697aab3)) +* use correct field name format for multipart file arrays ([f785ff2](https://github.com/warpdotdev/oz-sdk-python/commit/f785ff2bafbd319574974549a73c21643cdb5cc5)) + + +### Performance Improvements + +* **client:** optimize file structure copying in multipart requests ([b8e42cc](https://github.com/warpdotdev/oz-sdk-python/commit/b8e42cc08805eef08a3462088ba0e32cf79dac8c)) + + +### Chores + +* **internal:** more robust bootstrap script ([27c80e9](https://github.com/warpdotdev/oz-sdk-python/commit/27c80e953bc19de56ea730b0c2170aa8ffbc495a)) +* **internal:** reformat pyproject.toml ([fd17af1](https://github.com/warpdotdev/oz-sdk-python/commit/fd17af10c72ed943e4023a4e9e071ac7b8db08f7)) +* update SDK settings ([f2dd099](https://github.com/warpdotdev/oz-sdk-python/commit/f2dd099128bf4f98e304778556d55e80a4fd219c)) + ## 0.11.0 (2026-04-09) Full Changelog: [v0.10.1...v0.11.0](https://github.com/warpdotdev/oz-sdk-python/compare/v0.10.1...v0.11.0) diff --git a/pyproject.toml b/pyproject.toml index ae72878..367b68a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "oz-agent-sdk" -version = "0.11.0" +version = "0.12.0" description = "The official Python library for the oz-api API" dynamic = ["readme"] license = "Apache-2.0" diff --git a/src/oz_agent_sdk/_version.py b/src/oz_agent_sdk/_version.py index 113b87a..b96fedf 100644 --- a/src/oz_agent_sdk/_version.py +++ b/src/oz_agent_sdk/_version.py @@ -1,4 +1,4 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. __title__ = "oz_agent_sdk" -__version__ = "0.11.0" # x-release-please-version +__version__ = "0.12.0" # x-release-please-version