diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 1b77f506..1bc57136 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.7.0" + ".": "0.7.1" } \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index 8ff7dd44..3b293f90 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 34 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/sgp%2Fagentex-sdk-00b021144c274cce2211ea6c6f90b60b6f88f33a7286a6bf38f4f803ae4c1643.yml -openapi_spec_hash: d48de43356b6d0edc3f7a44b5980f7a0 +configured_endpoints: 35 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/sgp%2Fagentex-sdk-6feb0601dafb255298a2f1da01d64541d40da90aeb527e2f444c49c993e8c162.yml +openapi_spec_hash: 973cd2ed3c945818d15b7deee0b25d71 config_hash: 32eb65911c08ac84d117cecdf2759869 diff --git a/CHANGELOG.md b/CHANGELOG.md index 1bf4d6e3..4c32a705 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## 0.7.1 (2025-12-09) + +Full Changelog: [v0.7.0...v0.7.1](https://github.com/scaleapi/scale-agentex-python/compare/v0.7.0...v0.7.1) + +### Features + +* **api:** api update ([92b2710](https://github.com/scaleapi/scale-agentex-python/commit/92b2710e0f060a8d59f8d8237c3ca7b8e923867a)) + ## 0.7.0 (2025-12-09) Full Changelog: [v0.6.7...v0.7.0](https://github.com/scaleapi/scale-agentex-python/compare/v0.6.7...v0.7.0) diff --git a/api.md b/api.md index cefce8cd..f70f9b19 100644 --- a/api.md +++ b/api.md @@ -72,6 +72,7 @@ from agentex.types import ( ToolRequestContent, ToolResponseContent, MessageListResponse, + MessageListPaginatedResponse, ) ``` @@ -81,6 +82,7 @@ Methods: - client.messages.retrieve(message_id) -> TaskMessage - client.messages.update(message_id, \*\*params) -> TaskMessage - client.messages.list(\*\*params) -> MessageListResponse +- client.messages.list_paginated(\*\*params) -> MessageListPaginatedResponse ## Batch diff --git a/pyproject.toml b/pyproject.toml index 3eed8b99..04414573 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "agentex-sdk" -version = "0.7.0" +version = "0.7.1" description = "The official Python library for the agentex API" dynamic = ["readme"] license = "Apache-2.0" diff --git a/src/agentex/_version.py b/src/agentex/_version.py index 24f2919e..37c1d677 100644 --- a/src/agentex/_version.py +++ b/src/agentex/_version.py @@ -1,4 +1,4 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. __title__ = "agentex" -__version__ = "0.7.0" # x-release-please-version +__version__ = "0.7.1" # x-release-please-version diff --git a/src/agentex/resources/messages/messages.py b/src/agentex/resources/messages/messages.py index 401acccb..e1256449 100644 --- a/src/agentex/resources/messages/messages.py +++ b/src/agentex/resources/messages/messages.py @@ -15,7 +15,12 @@ BatchResourceWithStreamingResponse, AsyncBatchResourceWithStreamingResponse, ) -from ...types import message_list_params, message_create_params, message_update_params +from ...types import ( + message_list_params, + message_create_params, + message_update_params, + message_list_paginated_params, +) from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given from ..._utils import maybe_transform, async_maybe_transform from ..._compat import cached_property @@ -30,6 +35,7 @@ from ...types.task_message import TaskMessage from ...types.message_list_response import MessageListResponse from ...types.task_message_content_param import TaskMessageContentParam +from ...types.message_list_paginated_response import MessageListPaginatedResponse __all__ = ["MessagesResource", "AsyncMessagesResource"] @@ -192,7 +198,10 @@ def list( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> MessageListResponse: """ - List Messages + List messages for a task with offset-based pagination. + + For cursor-based pagination with infinite scroll support, use + /messages/paginated. Args: task_id: The task ID @@ -226,6 +235,70 @@ def list( cast_to=MessageListResponse, ) + def list_paginated( + self, + *, + task_id: str, + cursor: Optional[str] | Omit = omit, + direction: Literal["older", "newer"] | Omit = omit, + limit: int | 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, + ) -> MessageListPaginatedResponse: + """ + List messages for a task with cursor-based pagination. + + This endpoint is designed for infinite scroll UIs where new messages may arrive + while paginating through older ones. + + Args: task_id: The task ID to filter messages by limit: Maximum number of + messages to return (default: 50) cursor: Opaque cursor string for pagination. + Pass the `next_cursor` from a previous response to get the next page. direction: + Pagination direction - "older" to get older messages (default), "newer" to get + newer messages. + + Returns: PaginatedMessagesResponse with: - data: List of messages (newest first + when direction="older") - next_cursor: Cursor for fetching the next page (null + if no more pages) - has_more: Whether there are more messages to fetch + + Example: First request: GET /messages/paginated?task_id=xxx&limit=50 Next page: + GET /messages/paginated?task_id=xxx&limit=50&cursor= + + Args: + task_id: The task ID + + 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( + "/messages/paginated", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "task_id": task_id, + "cursor": cursor, + "direction": direction, + "limit": limit, + }, + message_list_paginated_params.MessageListPaginatedParams, + ), + ), + cast_to=MessageListPaginatedResponse, + ) + class AsyncMessagesResource(AsyncAPIResource): @cached_property @@ -385,7 +458,10 @@ async def list( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> MessageListResponse: """ - List Messages + List messages for a task with offset-based pagination. + + For cursor-based pagination with infinite scroll support, use + /messages/paginated. Args: task_id: The task ID @@ -419,6 +495,70 @@ async def list( cast_to=MessageListResponse, ) + async def list_paginated( + self, + *, + task_id: str, + cursor: Optional[str] | Omit = omit, + direction: Literal["older", "newer"] | Omit = omit, + limit: int | 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, + ) -> MessageListPaginatedResponse: + """ + List messages for a task with cursor-based pagination. + + This endpoint is designed for infinite scroll UIs where new messages may arrive + while paginating through older ones. + + Args: task_id: The task ID to filter messages by limit: Maximum number of + messages to return (default: 50) cursor: Opaque cursor string for pagination. + Pass the `next_cursor` from a previous response to get the next page. direction: + Pagination direction - "older" to get older messages (default), "newer" to get + newer messages. + + Returns: PaginatedMessagesResponse with: - data: List of messages (newest first + when direction="older") - next_cursor: Cursor for fetching the next page (null + if no more pages) - has_more: Whether there are more messages to fetch + + Example: First request: GET /messages/paginated?task_id=xxx&limit=50 Next page: + GET /messages/paginated?task_id=xxx&limit=50&cursor= + + Args: + task_id: The task ID + + 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( + "/messages/paginated", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=await async_maybe_transform( + { + "task_id": task_id, + "cursor": cursor, + "direction": direction, + "limit": limit, + }, + message_list_paginated_params.MessageListPaginatedParams, + ), + ), + cast_to=MessageListPaginatedResponse, + ) + class MessagesResourceWithRawResponse: def __init__(self, messages: MessagesResource) -> None: @@ -436,6 +576,9 @@ def __init__(self, messages: MessagesResource) -> None: self.list = to_raw_response_wrapper( messages.list, ) + self.list_paginated = to_raw_response_wrapper( + messages.list_paginated, + ) @cached_property def batch(self) -> BatchResourceWithRawResponse: @@ -458,6 +601,9 @@ def __init__(self, messages: AsyncMessagesResource) -> None: self.list = async_to_raw_response_wrapper( messages.list, ) + self.list_paginated = async_to_raw_response_wrapper( + messages.list_paginated, + ) @cached_property def batch(self) -> AsyncBatchResourceWithRawResponse: @@ -480,6 +626,9 @@ def __init__(self, messages: MessagesResource) -> None: self.list = to_streamed_response_wrapper( messages.list, ) + self.list_paginated = to_streamed_response_wrapper( + messages.list_paginated, + ) @cached_property def batch(self) -> BatchResourceWithStreamingResponse: @@ -502,6 +651,9 @@ def __init__(self, messages: AsyncMessagesResource) -> None: self.list = async_to_streamed_response_wrapper( messages.list, ) + self.list_paginated = async_to_streamed_response_wrapper( + messages.list_paginated, + ) @cached_property def batch(self) -> AsyncBatchResourceWithStreamingResponse: diff --git a/src/agentex/types/__init__.py b/src/agentex/types/__init__.py index 218239d8..04a3b059 100644 --- a/src/agentex/types/__init__.py +++ b/src/agentex/types/__init__.py @@ -64,5 +64,7 @@ from .tool_response_content_param import ToolResponseContentParam as ToolResponseContentParam from .task_retrieve_by_name_params import TaskRetrieveByNameParams as TaskRetrieveByNameParams from .deployment_history_list_params import DeploymentHistoryListParams as DeploymentHistoryListParams +from .message_list_paginated_params import MessageListPaginatedParams as MessageListPaginatedParams from .task_retrieve_by_name_response import TaskRetrieveByNameResponse as TaskRetrieveByNameResponse from .deployment_history_list_response import DeploymentHistoryListResponse as DeploymentHistoryListResponse +from .message_list_paginated_response import MessageListPaginatedResponse as MessageListPaginatedResponse diff --git a/src/agentex/types/message_list_paginated_params.py b/src/agentex/types/message_list_paginated_params.py new file mode 100644 index 00000000..6dfe1e7e --- /dev/null +++ b/src/agentex/types/message_list_paginated_params.py @@ -0,0 +1,19 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Optional +from typing_extensions import Literal, Required, TypedDict + +__all__ = ["MessageListPaginatedParams"] + + +class MessageListPaginatedParams(TypedDict, total=False): + task_id: Required[str] + """The task ID""" + + cursor: Optional[str] + + direction: Literal["older", "newer"] + + limit: int diff --git a/src/agentex/types/message_list_paginated_response.py b/src/agentex/types/message_list_paginated_response.py new file mode 100644 index 00000000..40af0b4a --- /dev/null +++ b/src/agentex/types/message_list_paginated_response.py @@ -0,0 +1,21 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional + +from .._models import BaseModel +from .task_message import TaskMessage + +__all__ = ["MessageListPaginatedResponse"] + + +class MessageListPaginatedResponse(BaseModel): + """Response with cursor pagination metadata.""" + + data: List[TaskMessage] + """List of messages""" + + has_more: Optional[bool] = None + """Whether there are more messages to fetch""" + + next_cursor: Optional[str] = None + """Cursor for fetching the next page of older messages""" diff --git a/tests/api_resources/test_messages.py b/tests/api_resources/test_messages.py index fb5991fa..19a51ae7 100644 --- a/tests/api_resources/test_messages.py +++ b/tests/api_resources/test_messages.py @@ -11,6 +11,7 @@ from agentex.types import ( TaskMessage, MessageListResponse, + MessageListPaginatedResponse, ) from ..utils import assert_matches_type @@ -273,6 +274,51 @@ def test_streaming_response_list(self, client: Agentex) -> None: assert cast(Any, response.is_closed) is True + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_list_paginated(self, client: Agentex) -> None: + message = client.messages.list_paginated( + task_id="task_id", + ) + assert_matches_type(MessageListPaginatedResponse, message, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_list_paginated_with_all_params(self, client: Agentex) -> None: + message = client.messages.list_paginated( + task_id="task_id", + cursor="cursor", + direction="older", + limit=0, + ) + assert_matches_type(MessageListPaginatedResponse, message, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_list_paginated(self, client: Agentex) -> None: + response = client.messages.with_raw_response.list_paginated( + task_id="task_id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + message = response.parse() + assert_matches_type(MessageListPaginatedResponse, message, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_list_paginated(self, client: Agentex) -> None: + with client.messages.with_streaming_response.list_paginated( + task_id="task_id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + message = response.parse() + assert_matches_type(MessageListPaginatedResponse, message, path=["response"]) + + assert cast(Any, response.is_closed) is True + class TestAsyncMessages: parametrize = pytest.mark.parametrize( @@ -530,3 +576,48 @@ async def test_streaming_response_list(self, async_client: AsyncAgentex) -> None assert_matches_type(MessageListResponse, message, path=["response"]) assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_list_paginated(self, async_client: AsyncAgentex) -> None: + message = await async_client.messages.list_paginated( + task_id="task_id", + ) + assert_matches_type(MessageListPaginatedResponse, message, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_list_paginated_with_all_params(self, async_client: AsyncAgentex) -> None: + message = await async_client.messages.list_paginated( + task_id="task_id", + cursor="cursor", + direction="older", + limit=0, + ) + assert_matches_type(MessageListPaginatedResponse, message, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_list_paginated(self, async_client: AsyncAgentex) -> None: + response = await async_client.messages.with_raw_response.list_paginated( + task_id="task_id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + message = await response.parse() + assert_matches_type(MessageListPaginatedResponse, message, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_list_paginated(self, async_client: AsyncAgentex) -> None: + async with async_client.messages.with_streaming_response.list_paginated( + task_id="task_id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + message = await response.parse() + assert_matches_type(MessageListPaginatedResponse, message, path=["response"]) + + assert cast(Any, response.is_closed) is True