agentex-sdk 0.7.0__py3-none-any.whl → 0.7.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (26) hide show
  1. agentex/_version.py +1 -1
  2. agentex/lib/adk/providers/_modules/sync_provider.py +116 -15
  3. agentex/lib/cli/commands/init.py +16 -1
  4. agentex/lib/cli/templates/temporal-openai-agents/.dockerignore.j2 +43 -0
  5. agentex/lib/cli/templates/temporal-openai-agents/Dockerfile-uv.j2 +48 -0
  6. agentex/lib/cli/templates/temporal-openai-agents/Dockerfile.j2 +48 -0
  7. agentex/lib/cli/templates/temporal-openai-agents/README.md.j2 +224 -0
  8. agentex/lib/cli/templates/temporal-openai-agents/dev.ipynb.j2 +126 -0
  9. agentex/lib/cli/templates/temporal-openai-agents/environments.yaml.j2 +64 -0
  10. agentex/lib/cli/templates/temporal-openai-agents/manifest.yaml.j2 +140 -0
  11. agentex/lib/cli/templates/temporal-openai-agents/project/acp.py.j2 +80 -0
  12. agentex/lib/cli/templates/temporal-openai-agents/project/activities.py.j2 +116 -0
  13. agentex/lib/cli/templates/temporal-openai-agents/project/run_worker.py.j2 +56 -0
  14. agentex/lib/cli/templates/temporal-openai-agents/project/workflow.py.j2 +169 -0
  15. agentex/lib/cli/templates/temporal-openai-agents/pyproject.toml.j2 +35 -0
  16. agentex/lib/cli/templates/temporal-openai-agents/requirements.txt.j2 +4 -0
  17. agentex/lib/cli/templates/temporal-openai-agents/test_agent.py.j2 +147 -0
  18. agentex/resources/messages/messages.py +155 -3
  19. agentex/types/__init__.py +2 -0
  20. agentex/types/message_list_paginated_params.py +19 -0
  21. agentex/types/message_list_paginated_response.py +21 -0
  22. {agentex_sdk-0.7.0.dist-info → agentex_sdk-0.7.2.dist-info}/METADATA +1 -1
  23. {agentex_sdk-0.7.0.dist-info → agentex_sdk-0.7.2.dist-info}/RECORD +26 -10
  24. {agentex_sdk-0.7.0.dist-info → agentex_sdk-0.7.2.dist-info}/WHEEL +0 -0
  25. {agentex_sdk-0.7.0.dist-info → agentex_sdk-0.7.2.dist-info}/entry_points.txt +0 -0
  26. {agentex_sdk-0.7.0.dist-info → agentex_sdk-0.7.2.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,169 @@
1
+ import json
2
+ import os
3
+
4
+ from temporalio import workflow
5
+
6
+ from agentex.lib import adk
7
+ from agentex.lib.types.acp import CreateTaskParams, SendEventParams
8
+ from agentex.lib.core.temporal.workflows.workflow import BaseWorkflow
9
+ from agentex.lib.core.temporal.types.workflow import SignalName
10
+ from agentex.lib.utils.logging import make_logger
11
+ from agentex.types.text_content import TextContent
12
+ from agentex.lib.environment_variables import EnvironmentVariables
13
+ from agents import Agent, Runner
14
+ from agentex.lib.core.temporal.plugins.openai_agents.hooks.hooks import TemporalStreamingHooks
15
+ from pydantic import BaseModel
16
+ from typing import List, Dict, Any
17
+ from temporalio.contrib import openai_agents
18
+ from project.activities import get_weather
19
+ from agentex.lib.core.tracing.tracing_processor_manager import (
20
+ add_tracing_processor_config,
21
+ )
22
+ from agentex.lib.types.tracing import SGPTracingProcessorConfig
23
+ from datetime import timedelta
24
+
25
+
26
+ environment_variables = EnvironmentVariables.refresh()
27
+
28
+ if environment_variables.WORKFLOW_NAME is None:
29
+ raise ValueError("Environment variable WORKFLOW_NAME is not set")
30
+
31
+ if environment_variables.AGENT_NAME is None:
32
+ raise ValueError("Environment variable AGENT_NAME is not set")
33
+
34
+ logger = make_logger(__name__)
35
+
36
+ # Setup tracing for SGP (Scale GenAI Platform)
37
+ # This enables visibility into your agent's execution in the SGP dashboard
38
+ add_tracing_processor_config(
39
+ SGPTracingProcessorConfig(
40
+ sgp_api_key=os.environ.get("SGP_API_KEY", ""),
41
+ sgp_account_id=os.environ.get("SGP_ACCOUNT_ID", ""),
42
+ )
43
+ )
44
+
45
+
46
+ class StateModel(BaseModel):
47
+ """
48
+ State model for preserving conversation history across turns.
49
+
50
+ This allows the agent to maintain context throughout the conversation,
51
+ making it possible to reference previous messages and build on the discussion.
52
+
53
+ Attributes:
54
+ input_list: The conversation history in OpenAI message format.
55
+ turn_number: Counter for tracking conversation turns (useful for tracing).
56
+ """
57
+
58
+ input_list: List[Dict[str, Any]]
59
+ turn_number: int
60
+
61
+
62
+ class TurnInput(BaseModel):
63
+ """Input model for tracing spans."""
64
+ input_list: List[Dict[str, Any]]
65
+
66
+
67
+ class TurnOutput(BaseModel):
68
+ """Output model for tracing spans."""
69
+ final_output: Any
70
+
71
+
72
+ @workflow.defn(name=environment_variables.WORKFLOW_NAME)
73
+ class {{ workflow_class }}(BaseWorkflow):
74
+ """
75
+ Workflow for {{ agent_name }} agent using OpenAI Agents SDK.
76
+
77
+ This workflow:
78
+ - Maintains conversation state across turns
79
+ - Creates tracing spans for each turn
80
+ - Runs an OpenAI agent with tools (activities)
81
+ - Streams responses back to the client
82
+ """
83
+
84
+ def __init__(self):
85
+ super().__init__(display_name=environment_variables.AGENT_NAME)
86
+ self._complete_task = False
87
+ self._state: StateModel = StateModel(input_list=[], turn_number=0)
88
+ self._task_id = None
89
+ self._trace_id = None
90
+ self._parent_span_id = None
91
+
92
+ @workflow.signal(name=SignalName.RECEIVE_EVENT)
93
+ async def on_task_event_send(self, params: SendEventParams) -> None:
94
+ logger.info(f"Received task message instruction: {params}")
95
+
96
+ # Increment turn number for tracing
97
+ self._state.turn_number += 1
98
+
99
+ self._task_id = params.task.id
100
+ self._trace_id = params.task.id
101
+ self._parent_span_id = params.task.id
102
+
103
+ # Add the user message to conversation history
104
+ self._state.input_list.append({"role": "user", "content": params.event.content.content})
105
+
106
+ # Echo back the client's message to show it in the UI
107
+ await adk.messages.create(task_id=params.task.id, content=params.event.content)
108
+
109
+ temporal_streaming_hooks = TemporalStreamingHooks(task_id=params.task.id)
110
+
111
+ # Create a span to track this turn of the conversation
112
+ turn_input = TurnInput(
113
+ input_list=self._state.input_list,
114
+ )
115
+ async with adk.tracing.span(
116
+ trace_id=params.task.id,
117
+ name=f"Turn {self._state.turn_number}",
118
+ input=turn_input.model_dump(),
119
+ ) as span:
120
+ self._parent_span_id = span.id if span else None
121
+
122
+ # Create the OpenAI agent with tools
123
+ # Add your activities as tools using activity_as_tool()
124
+ agent = Agent(
125
+ name="{{ agent_name }}",
126
+ instructions="You are a helpful assistant. Use your tools to help the user.",
127
+ model="gpt-4o-mini",
128
+ tools=[
129
+ openai_agents.workflow.activity_as_tool(
130
+ get_weather,
131
+ start_to_close_timeout=timedelta(minutes=5),
132
+ ),
133
+ # Add more tools here as you create new activities:
134
+ # openai_agents.workflow.activity_as_tool(
135
+ # your_new_activity,
136
+ # start_to_close_timeout=timedelta(minutes=5),
137
+ # ),
138
+ ],
139
+ )
140
+
141
+ # Run the agent with hooks to enable streaming responses
142
+ result = await Runner.run(agent, self._state.input_list, hooks=temporal_streaming_hooks)
143
+
144
+ # Update the state with the assistant's response for the next turn
145
+ self._state.input_list = result.to_input_list() # type: ignore[assignment]
146
+
147
+ # Set span output for tracing - include full state
148
+ if span:
149
+ turn_output = TurnOutput(final_output=result.final_output)
150
+ span.output = turn_output.model_dump()
151
+
152
+ @workflow.run
153
+ async def on_task_create(self, params: CreateTaskParams) -> str:
154
+ logger.info(f"Received task create params: {params}")
155
+
156
+ # Acknowledge that the task has been created
157
+ await adk.messages.create(
158
+ task_id=params.task.id,
159
+ content=TextContent(
160
+ author="agent",
161
+ content=f"Hello! I'm {{ agent_name }}, your AI assistant. How can I help you today?\n\nParams received:\n{json.dumps(params.params, indent=2)}",
162
+ ),
163
+ )
164
+
165
+ await workflow.wait_condition(
166
+ lambda: self._complete_task,
167
+ timeout=None,
168
+ )
169
+ return "Task completed"
@@ -0,0 +1,35 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "{{ project_name }}"
7
+ version = "0.1.0"
8
+ description = "{{ description }}"
9
+ requires-python = ">=3.12"
10
+ dependencies = [
11
+ "agentex-sdk",
12
+ "scale-gp",
13
+ "temporalio",
14
+ "openai-agents>=0.4.2",
15
+ ]
16
+
17
+ [project.optional-dependencies]
18
+ dev = [
19
+ "pytest",
20
+ "black",
21
+ "isort",
22
+ "flake8",
23
+ "debugpy>=1.8.15",
24
+ ]
25
+
26
+ [tool.hatch.build.targets.wheel]
27
+ packages = ["project"]
28
+
29
+ [tool.black]
30
+ line-length = 88
31
+ target-version = ['py312']
32
+
33
+ [tool.isort]
34
+ profile = "black"
35
+ line_length = 88
@@ -0,0 +1,4 @@
1
+ agentex-sdk
2
+ scale-gp
3
+ temporalio
4
+ openai-agents>=0.4.2
@@ -0,0 +1,147 @@
1
+ """
2
+ Sample tests for AgentEx ACP agent.
3
+
4
+ This test suite demonstrates how to test the main AgentEx API functions:
5
+ - Non-streaming event sending and polling
6
+ - Streaming event sending
7
+
8
+ To run these tests:
9
+ 1. Make sure the agent is running (via docker-compose or `agentex agents run`)
10
+ 2. Set the AGENTEX_API_BASE_URL environment variable if not using default
11
+ 3. Run: pytest test_agent.py -v
12
+
13
+ Configuration:
14
+ - AGENTEX_API_BASE_URL: Base URL for the AgentEx server (default: http://localhost:5003)
15
+ - AGENT_NAME: Name of the agent to test (default: {{ agent_name }})
16
+ """
17
+
18
+ import os
19
+ import uuid
20
+ import asyncio
21
+ import pytest
22
+ import pytest_asyncio
23
+ from agentex import AsyncAgentex
24
+ from agentex.types import TaskMessage
25
+ from agentex.types.agent_rpc_params import ParamsCreateTaskRequest
26
+ from agentex.types.text_content_param import TextContentParam
27
+ from test_utils.async_utils import (
28
+ poll_for_agent_response,
29
+ send_event_and_poll_yielding,
30
+ stream_agent_response,
31
+ validate_text_in_response,
32
+ poll_messages,
33
+ )
34
+
35
+
36
+ # Configuration from environment variables
37
+ AGENTEX_API_BASE_URL = os.environ.get("AGENTEX_API_BASE_URL", "http://localhost:5003")
38
+ AGENT_NAME = os.environ.get("AGENT_NAME", "{{ agent_name }}")
39
+
40
+
41
+ @pytest_asyncio.fixture
42
+ async def client():
43
+ """Create an AsyncAgentex client instance for testing."""
44
+ client = AsyncAgentex(base_url=AGENTEX_API_BASE_URL)
45
+ yield client
46
+ await client.close()
47
+
48
+
49
+ @pytest.fixture
50
+ def agent_name():
51
+ """Return the agent name for testing."""
52
+ return AGENT_NAME
53
+
54
+
55
+ @pytest_asyncio.fixture
56
+ async def agent_id(client, agent_name):
57
+ """Retrieve the agent ID based on the agent name."""
58
+ agents = await client.agents.list()
59
+ for agent in agents:
60
+ if agent.name == agent_name:
61
+ return agent.id
62
+ raise ValueError(f"Agent with name {agent_name} not found.")
63
+
64
+
65
+ class TestNonStreamingEvents:
66
+ """Test non-streaming event sending and polling."""
67
+
68
+ @pytest.mark.asyncio
69
+ async def test_send_event_and_poll(self, client: AsyncAgentex, _agent_name: str, agent_id: str):
70
+ """Test sending an event and polling for the response."""
71
+ # TODO: Create a task for this conversation
72
+ # task_response = await client.agents.create_task(agent_id, params=ParamsCreateTaskRequest(name=uuid.uuid1().hex))
73
+ # task = task_response.result
74
+ # assert task is not None
75
+
76
+ # TODO: Poll for the initial task creation message (if your agent sends one)
77
+ # async for message in poll_messages(
78
+ # client=client,
79
+ # task_id=task.id,
80
+ # timeout=30,
81
+ # sleep_interval=1.0,
82
+ # ):
83
+ # assert isinstance(message, TaskMessage)
84
+ # if message.content and message.content.type == "text" and message.content.author == "agent":
85
+ # # Check for your expected initial message
86
+ # assert "expected initial text" in message.content.content
87
+ # break
88
+
89
+ # TODO: Send an event and poll for response using the yielding helper function
90
+ # user_message = "Your test message here"
91
+ # async for message in send_event_and_poll_yielding(
92
+ # client=client,
93
+ # agent_id=agent_id,
94
+ # task_id=task.id,
95
+ # user_message=user_message,
96
+ # timeout=30,
97
+ # sleep_interval=1.0,
98
+ # ):
99
+ # assert isinstance(message, TaskMessage)
100
+ # if message.content and message.content.type == "text" and message.content.author == "agent":
101
+ # # Check for your expected response
102
+ # assert "expected response text" in message.content.content
103
+ # break
104
+ pass
105
+
106
+
107
+ class TestStreamingEvents:
108
+ """Test streaming event sending."""
109
+
110
+ @pytest.mark.asyncio
111
+ async def test_send_event_and_stream(self, client: AsyncAgentex, _agent_name: str, agent_id: str):
112
+ """Test sending an event and streaming the response."""
113
+ # TODO: Create a task for this conversation
114
+ # task_response = await client.agents.create_task(agent_id, params=ParamsCreateTaskRequest(name=uuid.uuid1().hex))
115
+ # task = task_response.result
116
+ # assert task is not None
117
+
118
+ # user_message = "Your test message here"
119
+
120
+ # # Collect events from stream
121
+ # all_events = []
122
+
123
+ # async def collect_stream_events():
124
+ # async for event in stream_agent_response(
125
+ # client=client,
126
+ # task_id=task.id,
127
+ # timeout=30,
128
+ # ):
129
+ # all_events.append(event)
130
+
131
+ # # Start streaming task
132
+ # stream_task = asyncio.create_task(collect_stream_events())
133
+
134
+ # # Send the event
135
+ # event_content = TextContentParam(type="text", author="user", content=user_message)
136
+ # await client.agents.send_event(agent_id=agent_id, params={"task_id": task.id, "content": event_content})
137
+
138
+ # # Wait for streaming to complete
139
+ # await stream_task
140
+
141
+ # # TODO: Add your validation here
142
+ # assert len(all_events) > 0, "No events received in streaming response"
143
+ pass
144
+
145
+
146
+ if __name__ == "__main__":
147
+ pytest.main([__file__, "-v"])
@@ -15,7 +15,12 @@ from .batch import (
15
15
  BatchResourceWithStreamingResponse,
16
16
  AsyncBatchResourceWithStreamingResponse,
17
17
  )
18
- from ...types import message_list_params, message_create_params, message_update_params
18
+ from ...types import (
19
+ message_list_params,
20
+ message_create_params,
21
+ message_update_params,
22
+ message_list_paginated_params,
23
+ )
19
24
  from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given
20
25
  from ..._utils import maybe_transform, async_maybe_transform
21
26
  from ..._compat import cached_property
@@ -30,6 +35,7 @@ from ..._base_client import make_request_options
30
35
  from ...types.task_message import TaskMessage
31
36
  from ...types.message_list_response import MessageListResponse
32
37
  from ...types.task_message_content_param import TaskMessageContentParam
38
+ from ...types.message_list_paginated_response import MessageListPaginatedResponse
33
39
 
34
40
  __all__ = ["MessagesResource", "AsyncMessagesResource"]
35
41
 
@@ -192,7 +198,10 @@ class MessagesResource(SyncAPIResource):
192
198
  timeout: float | httpx.Timeout | None | NotGiven = not_given,
193
199
  ) -> MessageListResponse:
194
200
  """
195
- List Messages
201
+ List messages for a task with offset-based pagination.
202
+
203
+ For cursor-based pagination with infinite scroll support, use
204
+ /messages/paginated.
196
205
 
197
206
  Args:
198
207
  task_id: The task ID
@@ -226,6 +235,70 @@ class MessagesResource(SyncAPIResource):
226
235
  cast_to=MessageListResponse,
227
236
  )
228
237
 
238
+ def list_paginated(
239
+ self,
240
+ *,
241
+ task_id: str,
242
+ cursor: Optional[str] | Omit = omit,
243
+ direction: Literal["older", "newer"] | Omit = omit,
244
+ limit: int | Omit = omit,
245
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
246
+ # The extra values given here take precedence over values defined on the client or passed to this method.
247
+ extra_headers: Headers | None = None,
248
+ extra_query: Query | None = None,
249
+ extra_body: Body | None = None,
250
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
251
+ ) -> MessageListPaginatedResponse:
252
+ """
253
+ List messages for a task with cursor-based pagination.
254
+
255
+ This endpoint is designed for infinite scroll UIs where new messages may arrive
256
+ while paginating through older ones.
257
+
258
+ Args: task_id: The task ID to filter messages by limit: Maximum number of
259
+ messages to return (default: 50) cursor: Opaque cursor string for pagination.
260
+ Pass the `next_cursor` from a previous response to get the next page. direction:
261
+ Pagination direction - "older" to get older messages (default), "newer" to get
262
+ newer messages.
263
+
264
+ Returns: PaginatedMessagesResponse with: - data: List of messages (newest first
265
+ when direction="older") - next_cursor: Cursor for fetching the next page (null
266
+ if no more pages) - has_more: Whether there are more messages to fetch
267
+
268
+ Example: First request: GET /messages/paginated?task_id=xxx&limit=50 Next page:
269
+ GET /messages/paginated?task_id=xxx&limit=50&cursor=<next_cursor>
270
+
271
+ Args:
272
+ task_id: The task ID
273
+
274
+ extra_headers: Send extra headers
275
+
276
+ extra_query: Add additional query parameters to the request
277
+
278
+ extra_body: Add additional JSON properties to the request
279
+
280
+ timeout: Override the client-level default timeout for this request, in seconds
281
+ """
282
+ return self._get(
283
+ "/messages/paginated",
284
+ options=make_request_options(
285
+ extra_headers=extra_headers,
286
+ extra_query=extra_query,
287
+ extra_body=extra_body,
288
+ timeout=timeout,
289
+ query=maybe_transform(
290
+ {
291
+ "task_id": task_id,
292
+ "cursor": cursor,
293
+ "direction": direction,
294
+ "limit": limit,
295
+ },
296
+ message_list_paginated_params.MessageListPaginatedParams,
297
+ ),
298
+ ),
299
+ cast_to=MessageListPaginatedResponse,
300
+ )
301
+
229
302
 
230
303
  class AsyncMessagesResource(AsyncAPIResource):
231
304
  @cached_property
@@ -385,7 +458,10 @@ class AsyncMessagesResource(AsyncAPIResource):
385
458
  timeout: float | httpx.Timeout | None | NotGiven = not_given,
386
459
  ) -> MessageListResponse:
387
460
  """
388
- List Messages
461
+ List messages for a task with offset-based pagination.
462
+
463
+ For cursor-based pagination with infinite scroll support, use
464
+ /messages/paginated.
389
465
 
390
466
  Args:
391
467
  task_id: The task ID
@@ -419,6 +495,70 @@ class AsyncMessagesResource(AsyncAPIResource):
419
495
  cast_to=MessageListResponse,
420
496
  )
421
497
 
498
+ async def list_paginated(
499
+ self,
500
+ *,
501
+ task_id: str,
502
+ cursor: Optional[str] | Omit = omit,
503
+ direction: Literal["older", "newer"] | Omit = omit,
504
+ limit: int | Omit = omit,
505
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
506
+ # The extra values given here take precedence over values defined on the client or passed to this method.
507
+ extra_headers: Headers | None = None,
508
+ extra_query: Query | None = None,
509
+ extra_body: Body | None = None,
510
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
511
+ ) -> MessageListPaginatedResponse:
512
+ """
513
+ List messages for a task with cursor-based pagination.
514
+
515
+ This endpoint is designed for infinite scroll UIs where new messages may arrive
516
+ while paginating through older ones.
517
+
518
+ Args: task_id: The task ID to filter messages by limit: Maximum number of
519
+ messages to return (default: 50) cursor: Opaque cursor string for pagination.
520
+ Pass the `next_cursor` from a previous response to get the next page. direction:
521
+ Pagination direction - "older" to get older messages (default), "newer" to get
522
+ newer messages.
523
+
524
+ Returns: PaginatedMessagesResponse with: - data: List of messages (newest first
525
+ when direction="older") - next_cursor: Cursor for fetching the next page (null
526
+ if no more pages) - has_more: Whether there are more messages to fetch
527
+
528
+ Example: First request: GET /messages/paginated?task_id=xxx&limit=50 Next page:
529
+ GET /messages/paginated?task_id=xxx&limit=50&cursor=<next_cursor>
530
+
531
+ Args:
532
+ task_id: The task ID
533
+
534
+ extra_headers: Send extra headers
535
+
536
+ extra_query: Add additional query parameters to the request
537
+
538
+ extra_body: Add additional JSON properties to the request
539
+
540
+ timeout: Override the client-level default timeout for this request, in seconds
541
+ """
542
+ return await self._get(
543
+ "/messages/paginated",
544
+ options=make_request_options(
545
+ extra_headers=extra_headers,
546
+ extra_query=extra_query,
547
+ extra_body=extra_body,
548
+ timeout=timeout,
549
+ query=await async_maybe_transform(
550
+ {
551
+ "task_id": task_id,
552
+ "cursor": cursor,
553
+ "direction": direction,
554
+ "limit": limit,
555
+ },
556
+ message_list_paginated_params.MessageListPaginatedParams,
557
+ ),
558
+ ),
559
+ cast_to=MessageListPaginatedResponse,
560
+ )
561
+
422
562
 
423
563
  class MessagesResourceWithRawResponse:
424
564
  def __init__(self, messages: MessagesResource) -> None:
@@ -436,6 +576,9 @@ class MessagesResourceWithRawResponse:
436
576
  self.list = to_raw_response_wrapper(
437
577
  messages.list,
438
578
  )
579
+ self.list_paginated = to_raw_response_wrapper(
580
+ messages.list_paginated,
581
+ )
439
582
 
440
583
  @cached_property
441
584
  def batch(self) -> BatchResourceWithRawResponse:
@@ -458,6 +601,9 @@ class AsyncMessagesResourceWithRawResponse:
458
601
  self.list = async_to_raw_response_wrapper(
459
602
  messages.list,
460
603
  )
604
+ self.list_paginated = async_to_raw_response_wrapper(
605
+ messages.list_paginated,
606
+ )
461
607
 
462
608
  @cached_property
463
609
  def batch(self) -> AsyncBatchResourceWithRawResponse:
@@ -480,6 +626,9 @@ class MessagesResourceWithStreamingResponse:
480
626
  self.list = to_streamed_response_wrapper(
481
627
  messages.list,
482
628
  )
629
+ self.list_paginated = to_streamed_response_wrapper(
630
+ messages.list_paginated,
631
+ )
483
632
 
484
633
  @cached_property
485
634
  def batch(self) -> BatchResourceWithStreamingResponse:
@@ -502,6 +651,9 @@ class AsyncMessagesResourceWithStreamingResponse:
502
651
  self.list = async_to_streamed_response_wrapper(
503
652
  messages.list,
504
653
  )
654
+ self.list_paginated = async_to_streamed_response_wrapper(
655
+ messages.list_paginated,
656
+ )
505
657
 
506
658
  @cached_property
507
659
  def batch(self) -> AsyncBatchResourceWithStreamingResponse:
agentex/types/__init__.py CHANGED
@@ -63,6 +63,8 @@ from .task_message_content_param import TaskMessageContentParam as TaskMessageCo
63
63
  from .tool_request_content_param import ToolRequestContentParam as ToolRequestContentParam
64
64
  from .tool_response_content_param import ToolResponseContentParam as ToolResponseContentParam
65
65
  from .task_retrieve_by_name_params import TaskRetrieveByNameParams as TaskRetrieveByNameParams
66
+ from .message_list_paginated_params import MessageListPaginatedParams as MessageListPaginatedParams
66
67
  from .deployment_history_list_params import DeploymentHistoryListParams as DeploymentHistoryListParams
67
68
  from .task_retrieve_by_name_response import TaskRetrieveByNameResponse as TaskRetrieveByNameResponse
69
+ from .message_list_paginated_response import MessageListPaginatedResponse as MessageListPaginatedResponse
68
70
  from .deployment_history_list_response import DeploymentHistoryListResponse as DeploymentHistoryListResponse
@@ -0,0 +1,19 @@
1
+ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Optional
6
+ from typing_extensions import Literal, Required, TypedDict
7
+
8
+ __all__ = ["MessageListPaginatedParams"]
9
+
10
+
11
+ class MessageListPaginatedParams(TypedDict, total=False):
12
+ task_id: Required[str]
13
+ """The task ID"""
14
+
15
+ cursor: Optional[str]
16
+
17
+ direction: Literal["older", "newer"]
18
+
19
+ limit: int
@@ -0,0 +1,21 @@
1
+ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2
+
3
+ from typing import List, Optional
4
+
5
+ from .._models import BaseModel
6
+ from .task_message import TaskMessage
7
+
8
+ __all__ = ["MessageListPaginatedResponse"]
9
+
10
+
11
+ class MessageListPaginatedResponse(BaseModel):
12
+ """Response with cursor pagination metadata."""
13
+
14
+ data: List[TaskMessage]
15
+ """List of messages"""
16
+
17
+ has_more: Optional[bool] = None
18
+ """Whether there are more messages to fetch"""
19
+
20
+ next_cursor: Optional[str] = None
21
+ """Cursor for fetching the next page of older messages"""
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: agentex-sdk
3
- Version: 0.7.0
3
+ Version: 0.7.2
4
4
  Summary: The official Python library for the agentex API
5
5
  Project-URL: Homepage, https://github.com/scaleapi/scale-agentex-python
6
6
  Project-URL: Repository, https://github.com/scaleapi/scale-agentex-python