From 0d30d94ffc89c91ac9c6ad9fda8cc9c39302ef6a Mon Sep 17 00:00:00 2001 From: Bhavesh Patel Date: Wed, 1 Jul 2026 14:08:01 +0530 Subject: [PATCH 1/2] AGE-1122: Align public API docstrings across manual agent SDK code --- .../agents/agent_session.py | 8 ++++++++ .../agents/agent_session_client.py | 6 ++++++ src/truefoundry_gateway_sdk/agents/event_delta.py | 2 ++ .../agents/prepared_turn.py | 14 ++++++++++++++ src/truefoundry_gateway_sdk/agents/turn.py | 8 ++++++++ .../agents/turn_stream_data.py | 2 ++ src/truefoundry_gateway_sdk/client.py | 6 ++++++ 7 files changed, 46 insertions(+) diff --git a/src/truefoundry_gateway_sdk/agents/agent_session.py b/src/truefoundry_gateway_sdk/agents/agent_session.py index 3f876f5..158072e 100644 --- a/src/truefoundry_gateway_sdk/agents/agent_session.py +++ b/src/truefoundry_gateway_sdk/agents/agent_session.py @@ -105,6 +105,7 @@ def prepare_turn( input: typing.Optional[typing.Sequence[TurnInputItem]] = None, previous_turn_id: typing.Optional[PreviousTurnIdInput] = None, ) -> PreparedTurn: + """Stage a turn locally (no HTTP). Omit ``previous_turn_id`` to chain to the session's last turn (server default ``auto``). Call ``execute()`` once to start ``create_turn``.""" return PreparedTurn( input=input, previous_turn_id=previous_turn_id, @@ -119,6 +120,7 @@ def list_turns( limit: typing.Optional[int] = 10, request_options: typing.Optional[RequestOptions] = None, ) -> SyncPager[Turn, ListTurnsResponse]: + """List turns in this session.""" raw_pager = self._client.agents.sessions.list_turns( self._id, page_token=page_token, limit=limit, request_options=request_options ) @@ -130,10 +132,12 @@ def get_turn( *, request_options: typing.Optional[RequestOptions] = None, ) -> Turn: + """Fetch a turn by ID.""" response = self._client.agents.sessions.get_turn(self._id, turn_id, request_options=request_options) return Turn(response.data, self, self._client) def cancel(self, *, request_options: typing.Optional[RequestOptions] = None) -> None: + """Cancel the running last turn for the session.""" self._client.agents.sessions.cancel(self._id, request_options=request_options) @@ -184,6 +188,7 @@ def prepare_turn( input: typing.Optional[typing.Sequence[TurnInputItem]] = None, previous_turn_id: typing.Optional[PreviousTurnIdInput] = None, ) -> AsyncPreparedTurn: + """Stage a turn locally (no HTTP). Omit ``previous_turn_id`` to chain to the session's last turn (server default ``auto``). Call ``execute()`` once to start ``create_turn``.""" return AsyncPreparedTurn( input=input, previous_turn_id=previous_turn_id, @@ -198,6 +203,7 @@ async def list_turns( limit: typing.Optional[int] = 10, request_options: typing.Optional[RequestOptions] = None, ) -> AsyncPager[AsyncTurn, ListTurnsResponse]: + """List turns in this session.""" raw_pager = await self._client.agents.sessions.list_turns( self._id, page_token=page_token, limit=limit, request_options=request_options ) @@ -209,8 +215,10 @@ async def get_turn( *, request_options: typing.Optional[RequestOptions] = None, ) -> AsyncTurn: + """Fetch a turn by ID.""" response = await self._client.agents.sessions.get_turn(self._id, turn_id, request_options=request_options) return AsyncTurn(response.data, self, self._client) async def cancel(self, *, request_options: typing.Optional[RequestOptions] = None) -> None: + """Cancel the running last turn for the session.""" await self._client.agents.sessions.cancel(self._id, request_options=request_options) diff --git a/src/truefoundry_gateway_sdk/agents/agent_session_client.py b/src/truefoundry_gateway_sdk/agents/agent_session_client.py index 286de18..d72995d 100644 --- a/src/truefoundry_gateway_sdk/agents/agent_session_client.py +++ b/src/truefoundry_gateway_sdk/agents/agent_session_client.py @@ -92,6 +92,7 @@ def create_session( agent_name: str, request_options: typing.Optional[RequestOptions] = None, ) -> AgentSession: + """Create a new session for a named agent.""" response = self._client.agents.sessions.create(agent_name=agent_name, request_options=request_options) return AgentSession(response.data, self._client) @@ -106,6 +107,7 @@ def list_sessions( end_timestamp: typing.Optional[str] = None, request_options: typing.Optional[RequestOptions] = None, ) -> SyncPager[AgentSession, ListSessionsResponse]: + """List sessions for an agent.""" raw_pager = self._client.agents.sessions.list( agent_name=agent_name, limit=limit, @@ -123,6 +125,7 @@ def get_session( *, request_options: typing.Optional[RequestOptions] = None, ) -> AgentSession: + """Fetch a session by ID.""" response = self._client.agents.sessions.get(session_id, request_options=request_options) return AgentSession(response.data, self._client) @@ -166,6 +169,7 @@ async def create_session( agent_name: str, request_options: typing.Optional[RequestOptions] = None, ) -> AsyncAgentSession: + """Create a new session for a named agent.""" response = await self._client.agents.sessions.create(agent_name=agent_name, request_options=request_options) return AsyncAgentSession(response.data, self._client) @@ -180,6 +184,7 @@ async def list_sessions( end_timestamp: typing.Optional[str] = None, request_options: typing.Optional[RequestOptions] = None, ) -> AsyncPager[AsyncAgentSession, ListSessionsResponse]: + """List sessions for an agent.""" raw_pager = await self._client.agents.sessions.list( agent_name=agent_name, limit=limit, @@ -197,5 +202,6 @@ async def get_session( *, request_options: typing.Optional[RequestOptions] = None, ) -> AsyncAgentSession: + """Fetch a session by ID.""" response = await self._client.agents.sessions.get(session_id, request_options=request_options) return AsyncAgentSession(response.data, self._client) diff --git a/src/truefoundry_gateway_sdk/agents/event_delta.py b/src/truefoundry_gateway_sdk/agents/event_delta.py index ef014cb..4b57455 100644 --- a/src/truefoundry_gateway_sdk/agents/event_delta.py +++ b/src/truefoundry_gateway_sdk/agents/event_delta.py @@ -14,10 +14,12 @@ def is_event_delta(event: TurnStreamingEvent) -> bool: + """True for incremental SSE chunks (e.g. ``model.message.delta``).""" return event.type.endswith(".delta") def merge_event_delta(base: TurnEvent, delta: DeltaEvents) -> None: + """Apply a delta chunk to its full event in place when streaming (same ``id`` required).""" if base.id != delta.id: raise ValueError(f'Cannot merge delta into a different event: base id "{base.id}" != delta id "{delta.id}".') if isinstance(delta, ModelMessageDeltaEvent) and isinstance(base, ModelMessageEvent): diff --git a/src/truefoundry_gateway_sdk/agents/prepared_turn.py b/src/truefoundry_gateway_sdk/agents/prepared_turn.py index f56946e..078345d 100644 --- a/src/truefoundry_gateway_sdk/agents/prepared_turn.py +++ b/src/truefoundry_gateway_sdk/agents/prepared_turn.py @@ -56,6 +56,7 @@ def session_id(self) -> str: @property def id(self) -> typing.Optional[str]: + """None until ``execute()`` has started the turn.""" return self._turn.id if self._turn is not None else None @property @@ -106,6 +107,7 @@ def execute( poll_interval_ms: int = 3000, request_options: typing.Optional[RequestOptions] = None, ) -> typing.Union[typing.Iterator[TurnStreamData], TurnState]: + """Start the turn via create_turn. ``stream=True`` (default) yields SSE from that POST (not resumable; after disconnect call ``stream()`` to subscribe_to_turn). ``stream=False`` polls ``get_turn`` until done, cancelled, or error.""" if self._started: raise RuntimeError("Turn already started; use stream() / wait_for_completion().") self._started = True @@ -122,11 +124,13 @@ def stream( after_sequence_number: typing.Optional[int] = None, request_options: typing.Optional[RequestOptions] = None, ) -> typing.Iterator[TurnStreamData]: + """Subscribe to live SSE via subscribe_to_turn after ``execute()`` has started the turn. Pass ``after_sequence_number`` to resume; updates state from turn.created and turn.done.""" yield from self._must_get_turn().stream( after_sequence_number=after_sequence_number, request_options=request_options ) def refresh(self, *, request_options: typing.Optional[RequestOptions] = None) -> "PreparedTurn": + """Refetch from the server, update state in-place and return self.""" self._must_get_turn().refresh(request_options=request_options) return self @@ -136,11 +140,13 @@ def wait_for_completion( poll_interval_ms: int = 3000, request_options: typing.Optional[RequestOptions] = None, ) -> TurnState: + """Poll ``get_turn`` until the turn is done, cancelled, or errored. ``poll_interval_ms`` minimum is 3000.""" return self._must_get_turn().wait_for_completion( poll_interval_ms=poll_interval_ms, request_options=request_options ) def cancel(self, *, request_options: typing.Optional[RequestOptions] = None) -> None: + """Cancel the running last turn for the session.""" return self._must_get_turn().cancel(request_options=request_options) def list_events( @@ -151,6 +157,7 @@ def list_events( order: typing.Optional[ListEventsOrder] = None, request_options: typing.Optional[RequestOptions] = None, ) -> SyncPager[TurnEvent, ListEventsResponse]: + """Paginated persisted TurnEvent history (no streaming deltas). Use ``stream()`` for live TurnStreamingEvent SSE.""" return self._must_get_turn().list_events( page_token=page_token, limit=limit, order=order, request_options=request_options ) @@ -264,6 +271,7 @@ def session_id(self) -> str: @property def id(self) -> typing.Optional[str]: + """None until ``execute()`` has started the turn.""" return self._turn.id if self._turn is not None else None @property @@ -314,6 +322,7 @@ def execute( poll_interval_ms: int = 3000, request_options: typing.Optional[RequestOptions] = None, ) -> typing.Union[typing.AsyncIterator[TurnStreamData], "typing.Coroutine[typing.Any, typing.Any, TurnState]"]: + """Start the turn via create_turn. ``stream=True`` (default) yields SSE from that POST (not resumable; after disconnect call ``stream()`` to subscribe_to_turn). ``stream=False`` polls ``get_turn`` until done, cancelled, or error.""" if self._started: raise RuntimeError("Turn already started; use stream() / wait_for_completion().") self._started = True @@ -330,12 +339,14 @@ async def stream( after_sequence_number: typing.Optional[int] = None, request_options: typing.Optional[RequestOptions] = None, ) -> typing.AsyncIterator[TurnStreamData]: + """Subscribe to live SSE via subscribe_to_turn after ``execute()`` has started the turn. Pass ``after_sequence_number`` to resume; updates state from turn.created and turn.done.""" async for item in self._must_get_turn().stream( after_sequence_number=after_sequence_number, request_options=request_options ): yield item async def refresh(self, *, request_options: typing.Optional[RequestOptions] = None) -> "AsyncPreparedTurn": + """Refetch from the server, update state in-place and return self.""" await self._must_get_turn().refresh(request_options=request_options) return self @@ -345,11 +356,13 @@ async def wait_for_completion( poll_interval_ms: int = 3000, request_options: typing.Optional[RequestOptions] = None, ) -> TurnState: + """Poll ``get_turn`` until the turn is done, cancelled, or errored. ``poll_interval_ms`` minimum is 3000.""" return await self._must_get_turn().wait_for_completion( poll_interval_ms=poll_interval_ms, request_options=request_options ) async def cancel(self, *, request_options: typing.Optional[RequestOptions] = None) -> None: + """Cancel the running last turn for the session.""" return await self._must_get_turn().cancel(request_options=request_options) async def list_events( @@ -360,6 +373,7 @@ async def list_events( order: typing.Optional[ListEventsOrder] = None, request_options: typing.Optional[RequestOptions] = None, ) -> AsyncPager[TurnEvent, ListEventsResponse]: + """Paginated persisted TurnEvent history (no streaming deltas). Use ``stream()`` for live TurnStreamingEvent SSE.""" return await self._must_get_turn().list_events( page_token=page_token, limit=limit, order=order, request_options=request_options ) diff --git a/src/truefoundry_gateway_sdk/agents/turn.py b/src/truefoundry_gateway_sdk/agents/turn.py index e46c6c8..4f94ac8 100644 --- a/src/truefoundry_gateway_sdk/agents/turn.py +++ b/src/truefoundry_gateway_sdk/agents/turn.py @@ -79,6 +79,7 @@ def created_at(self) -> str: @property def state(self) -> TurnState: + """Updated by ``refresh()``, ``stream()``, and ``wait_for_completion()``.""" return self._state @property @@ -107,6 +108,7 @@ def wait_for_completion( poll_interval_ms: int = _DEFAULT_POLL_INTERVAL_MS, request_options: typing.Optional[RequestOptions] = None, ) -> TurnState: + """Poll ``get_turn`` until the turn is done, cancelled, or errored. ``poll_interval_ms`` minimum is 3000.""" if poll_interval_ms < _MIN_POLL_INTERVAL_MS: raise ValueError(f"poll_interval_ms must be at least {_MIN_POLL_INTERVAL_MS}ms") while not self._is_terminal(self._state): @@ -131,6 +133,7 @@ def stream( yield TurnStreamData(sequence_number=None, event=event) def cancel(self, *, request_options: typing.Optional[RequestOptions] = None) -> None: + """Cancel the running last turn for the session.""" self._client.agents.sessions.cancel(self._session_id, request_options=request_options) def list_events( @@ -141,6 +144,7 @@ def list_events( order: typing.Optional[ListEventsOrder] = None, request_options: typing.Optional[RequestOptions] = None, ) -> SyncPager[TurnEvent, ListEventsResponse]: + """Paginated persisted TurnEvent history (no streaming deltas). Use ``stream()`` for live TurnStreamingEvent SSE.""" return self._client.agents.sessions.list_turn_events( self._session_id, self._id, @@ -203,6 +207,7 @@ def created_at(self) -> str: @property def state(self) -> TurnState: + """Updated by ``refresh()``, ``stream()``, and ``wait_for_completion()``.""" return self._state @property @@ -233,6 +238,7 @@ async def wait_for_completion( poll_interval_ms: int = _DEFAULT_POLL_INTERVAL_MS, request_options: typing.Optional[RequestOptions] = None, ) -> TurnState: + """Poll ``get_turn`` until the turn is done, cancelled, or errored. ``poll_interval_ms`` minimum is 3000.""" import asyncio if poll_interval_ms < _MIN_POLL_INTERVAL_MS: @@ -259,6 +265,7 @@ async def stream( yield TurnStreamData(sequence_number=None, event=event) async def cancel(self, *, request_options: typing.Optional[RequestOptions] = None) -> None: + """Cancel the running last turn for the session.""" await self._client.agents.sessions.cancel(self._session_id, request_options=request_options) async def list_events( @@ -269,6 +276,7 @@ async def list_events( order: typing.Optional[ListEventsOrder] = None, request_options: typing.Optional[RequestOptions] = None, ) -> AsyncPager[TurnEvent, ListEventsResponse]: + """Paginated persisted TurnEvent history (no streaming deltas). Use ``stream()`` for live TurnStreamingEvent SSE.""" return await self._client.agents.sessions.list_turn_events( self._session_id, self._id, diff --git a/src/truefoundry_gateway_sdk/agents/turn_stream_data.py b/src/truefoundry_gateway_sdk/agents/turn_stream_data.py index 191ea16..fd271de 100644 --- a/src/truefoundry_gateway_sdk/agents/turn_stream_data.py +++ b/src/truefoundry_gateway_sdk/agents/turn_stream_data.py @@ -6,6 +6,8 @@ @dataclasses.dataclass class TurnStreamData: + """An SSE item with a TurnStreamingEvent; ``sequence_number`` is the SSE event id for resuming via ``subscribe_to_turn``.""" + # Sequence number from the SSE event id. None when not available from the underlying stream. sequence_number: typing.Optional[int] event: TurnStreamingEvent diff --git a/src/truefoundry_gateway_sdk/client.py b/src/truefoundry_gateway_sdk/client.py index 4058056..b149380 100644 --- a/src/truefoundry_gateway_sdk/client.py +++ b/src/truefoundry_gateway_sdk/client.py @@ -10,6 +10,8 @@ class TrueFoundryGateway(BaseTrueFoundryGateway): + """Synchronous client for the TrueFoundry Gateway API.""" + def __init__( self, *, @@ -40,12 +42,15 @@ def __init__( @property def agents(self) -> AgentsClient: + """Agent sessions and turns.""" if self._agents is None: self._agents = AgentsClient(client_wrapper=self._client_wrapper) return self._agents class AsyncTrueFoundryGateway(AsyncBaseTrueFoundryGateway): + """Asynchronous client for the TrueFoundry Gateway API.""" + def __init__( self, *, @@ -78,6 +83,7 @@ def __init__( @property def agents(self) -> AsyncAgentsClient: + """Agent sessions and turns.""" if self._agents is None: self._agents = AsyncAgentsClient(client_wrapper=self._client_wrapper) return self._agents From f13752a6d03c513a7025c3c136abfbc88644dbf2 Mon Sep 17 00:00:00 2001 From: Bhavesh Patel Date: Wed, 1 Jul 2026 16:37:25 +0530 Subject: [PATCH 2/2] Add param and return docs to manual agent API --- .../agents/agent_session.py | 198 +++++++++++- .../agents/agent_session_client.py | 116 ++++++- .../agents/event_delta.py | 30 +- .../agents/prepared_turn.py | 302 +++++++++++++++++- src/truefoundry_gateway_sdk/agents/turn.py | 256 ++++++++++++++- .../agents/turn_stream_data.py | 9 +- src/truefoundry_gateway_sdk/client.py | 14 +- 7 files changed, 880 insertions(+), 45 deletions(-) diff --git a/src/truefoundry_gateway_sdk/agents/agent_session.py b/src/truefoundry_gateway_sdk/agents/agent_session.py index 158072e..f92f261 100644 --- a/src/truefoundry_gateway_sdk/agents/agent_session.py +++ b/src/truefoundry_gateway_sdk/agents/agent_session.py @@ -77,26 +77,62 @@ def __repr__(self) -> str: @property def id(self) -> str: + """ + Returns + ------- + str + Unique identifier of this session. + """ return self._id @property def agent_name(self) -> str: + """ + Returns + ------- + str + Name of the agent for this session. + """ return self._agent_name @property def title(self) -> typing.Optional[str]: + """ + Returns + ------- + typing.Optional[str] + Optional user-visible title for the session. + """ return self._title @property def created_by_subject(self) -> Subject: + """ + Returns + ------- + Subject + Subject that created this session. + """ return self._created_by_subject @property def created_at(self) -> str: + """ + Returns + ------- + str + ISO-8601 timestamp when the session was created. + """ return self._created_at @property def updated_at(self) -> str: + """ + Returns + ------- + str + ISO-8601 timestamp when the session was last updated. + """ return self._updated_at def prepare_turn( @@ -105,7 +141,21 @@ def prepare_turn( input: typing.Optional[typing.Sequence[TurnInputItem]] = None, previous_turn_id: typing.Optional[PreviousTurnIdInput] = None, ) -> PreparedTurn: - """Stage a turn locally (no HTTP). Omit ``previous_turn_id`` to chain to the session's last turn (server default ``auto``). Call ``execute()`` once to start ``create_turn``.""" + """ + Stage a turn locally; call ``execute()`` to start ``create_turn``. + + Parameters + ---------- + input : typing.Optional[typing.Sequence[TurnInputItem]] + Turn input items passed to create turn. + previous_turn_id : typing.Optional[PreviousTurnIdInput] + Previous turn to chain from. Defaults to ``auto``. + + Returns + ------- + PreparedTurn + Staged turn. + """ return PreparedTurn( input=input, previous_turn_id=previous_turn_id, @@ -120,7 +170,23 @@ def list_turns( limit: typing.Optional[int] = 10, request_options: typing.Optional[RequestOptions] = None, ) -> SyncPager[Turn, ListTurnsResponse]: - """List turns in this session.""" + """ + List turns in this session. + + Parameters + ---------- + page_token : typing.Optional[str] + Token from the previous response ``next_page_token``. + limit : typing.Optional[int] + Page size. Default 10. + request_options : typing.Optional[RequestOptions] + Overrides client timeout, retries, headers, and stream reconnect. + + Returns + ------- + SyncPager[Turn, ListTurnsResponse] + Paginated turns. + """ raw_pager = self._client.agents.sessions.list_turns( self._id, page_token=page_token, limit=limit, request_options=request_options ) @@ -132,12 +198,37 @@ def get_turn( *, request_options: typing.Optional[RequestOptions] = None, ) -> Turn: - """Fetch a turn by ID.""" + """ + Fetch a turn by ID. + + Parameters + ---------- + turn_id : str + Unique identifier of the turn to fetch. + request_options : typing.Optional[RequestOptions] + Overrides client timeout, retries, headers, and stream reconnect. + + Returns + ------- + Turn + Turn data. + """ response = self._client.agents.sessions.get_turn(self._id, turn_id, request_options=request_options) return Turn(response.data, self, self._client) def cancel(self, *, request_options: typing.Optional[RequestOptions] = None) -> None: - """Cancel the running last turn for the session.""" + """ + Cancel the running last turn for the session. + + Parameters + ---------- + request_options : typing.Optional[RequestOptions] + Overrides client timeout, retries, headers, and stream reconnect. + + Returns + ------- + None + """ self._client.agents.sessions.cancel(self._id, request_options=request_options) @@ -160,26 +251,62 @@ def __repr__(self) -> str: @property def id(self) -> str: + """ + Returns + ------- + str + Unique identifier of this session. + """ return self._id @property def agent_name(self) -> str: + """ + Returns + ------- + str + Name of the agent for this session. + """ return self._agent_name @property def title(self) -> typing.Optional[str]: + """ + Returns + ------- + typing.Optional[str] + Optional user-visible title for the session. + """ return self._title @property def created_by_subject(self) -> Subject: + """ + Returns + ------- + Subject + Subject that created this session. + """ return self._created_by_subject @property def created_at(self) -> str: + """ + Returns + ------- + str + ISO-8601 timestamp when the session was created. + """ return self._created_at @property def updated_at(self) -> str: + """ + Returns + ------- + str + ISO-8601 timestamp when the session was last updated. + """ return self._updated_at def prepare_turn( @@ -188,7 +315,21 @@ def prepare_turn( input: typing.Optional[typing.Sequence[TurnInputItem]] = None, previous_turn_id: typing.Optional[PreviousTurnIdInput] = None, ) -> AsyncPreparedTurn: - """Stage a turn locally (no HTTP). Omit ``previous_turn_id`` to chain to the session's last turn (server default ``auto``). Call ``execute()`` once to start ``create_turn``.""" + """ + Stage a turn locally; call ``execute()`` to start ``create_turn``. + + Parameters + ---------- + input : typing.Optional[typing.Sequence[TurnInputItem]] + Turn input items passed to create turn. + previous_turn_id : typing.Optional[PreviousTurnIdInput] + Previous turn to chain from. Defaults to ``auto``. + + Returns + ------- + AsyncPreparedTurn + Staged turn. + """ return AsyncPreparedTurn( input=input, previous_turn_id=previous_turn_id, @@ -203,7 +344,23 @@ async def list_turns( limit: typing.Optional[int] = 10, request_options: typing.Optional[RequestOptions] = None, ) -> AsyncPager[AsyncTurn, ListTurnsResponse]: - """List turns in this session.""" + """ + List turns in this session. + + Parameters + ---------- + page_token : typing.Optional[str] + Token from the previous response ``next_page_token``. + limit : typing.Optional[int] + Page size. Default 10. + request_options : typing.Optional[RequestOptions] + Overrides client timeout, retries, headers, and stream reconnect. + + Returns + ------- + AsyncPager[AsyncTurn, ListTurnsResponse] + Paginated turns. + """ raw_pager = await self._client.agents.sessions.list_turns( self._id, page_token=page_token, limit=limit, request_options=request_options ) @@ -215,10 +372,35 @@ async def get_turn( *, request_options: typing.Optional[RequestOptions] = None, ) -> AsyncTurn: - """Fetch a turn by ID.""" + """ + Fetch a turn by ID. + + Parameters + ---------- + turn_id : str + Unique identifier of the turn to fetch. + request_options : typing.Optional[RequestOptions] + Overrides client timeout, retries, headers, and stream reconnect. + + Returns + ------- + AsyncTurn + Turn data. + """ response = await self._client.agents.sessions.get_turn(self._id, turn_id, request_options=request_options) return AsyncTurn(response.data, self, self._client) async def cancel(self, *, request_options: typing.Optional[RequestOptions] = None) -> None: - """Cancel the running last turn for the session.""" + """ + Cancel the running last turn for the session. + + Parameters + ---------- + request_options : typing.Optional[RequestOptions] + Overrides client timeout, retries, headers, and stream reconnect. + + Returns + ------- + None + """ await self._client.agents.sessions.cancel(self._id, request_options=request_options) diff --git a/src/truefoundry_gateway_sdk/agents/agent_session_client.py b/src/truefoundry_gateway_sdk/agents/agent_session_client.py index d72995d..d0f7842 100644 --- a/src/truefoundry_gateway_sdk/agents/agent_session_client.py +++ b/src/truefoundry_gateway_sdk/agents/agent_session_client.py @@ -92,7 +92,21 @@ def create_session( agent_name: str, request_options: typing.Optional[RequestOptions] = None, ) -> AgentSession: - """Create a new session for a named agent.""" + """ + Create a new session for a named agent. + + Parameters + ---------- + agent_name : str + Name of the agent to create a session for. + request_options : typing.Optional[RequestOptions] + Overrides client timeout, retries, headers, and stream reconnect. + + Returns + ------- + AgentSession + Session created. + """ response = self._client.agents.sessions.create(agent_name=agent_name, request_options=request_options) return AgentSession(response.data, self._client) @@ -107,7 +121,31 @@ def list_sessions( end_timestamp: typing.Optional[str] = None, request_options: typing.Optional[RequestOptions] = None, ) -> SyncPager[AgentSession, ListSessionsResponse]: - """List sessions for an agent.""" + """ + List sessions for an agent. + + Parameters + ---------- + agent_name : str + Name of the agent whose sessions to list. + limit : typing.Optional[int] + Page size. Default 10. + order : typing.Optional[ListSessionsOrder] + Sort by creation time. Default ``desc``. + page_token : typing.Optional[str] + Token from the previous response ``next_page_token``. + start_timestamp : typing.Optional[str] + Inclusive lower bound on ``created_at`` (ISO-8601). + end_timestamp : typing.Optional[str] + Inclusive upper bound on ``created_at`` (ISO-8601). + request_options : typing.Optional[RequestOptions] + Overrides client timeout, retries, headers, and stream reconnect. + + Returns + ------- + SyncPager[AgentSession, ListSessionsResponse] + Paginated sessions. + """ raw_pager = self._client.agents.sessions.list( agent_name=agent_name, limit=limit, @@ -125,7 +163,21 @@ def get_session( *, request_options: typing.Optional[RequestOptions] = None, ) -> AgentSession: - """Fetch a session by ID.""" + """ + Fetch a session by ID. + + Parameters + ---------- + session_id : str + Unique identifier of the session to fetch. + request_options : typing.Optional[RequestOptions] + Overrides client timeout, retries, headers, and stream reconnect. + + Returns + ------- + AgentSession + Session data. + """ response = self._client.agents.sessions.get(session_id, request_options=request_options) return AgentSession(response.data, self._client) @@ -169,7 +221,21 @@ async def create_session( agent_name: str, request_options: typing.Optional[RequestOptions] = None, ) -> AsyncAgentSession: - """Create a new session for a named agent.""" + """ + Create a new session for a named agent. + + Parameters + ---------- + agent_name : str + Name of the agent to create a session for. + request_options : typing.Optional[RequestOptions] + Overrides client timeout, retries, headers, and stream reconnect. + + Returns + ------- + AsyncAgentSession + Session created. + """ response = await self._client.agents.sessions.create(agent_name=agent_name, request_options=request_options) return AsyncAgentSession(response.data, self._client) @@ -184,7 +250,31 @@ async def list_sessions( end_timestamp: typing.Optional[str] = None, request_options: typing.Optional[RequestOptions] = None, ) -> AsyncPager[AsyncAgentSession, ListSessionsResponse]: - """List sessions for an agent.""" + """ + List sessions for an agent. + + Parameters + ---------- + agent_name : str + Name of the agent whose sessions to list. + limit : typing.Optional[int] + Page size. Default 10. + order : typing.Optional[ListSessionsOrder] + Sort by creation time. Default ``desc``. + page_token : typing.Optional[str] + Token from the previous response ``next_page_token``. + start_timestamp : typing.Optional[str] + Inclusive lower bound on ``created_at`` (ISO-8601). + end_timestamp : typing.Optional[str] + Inclusive upper bound on ``created_at`` (ISO-8601). + request_options : typing.Optional[RequestOptions] + Overrides client timeout, retries, headers, and stream reconnect. + + Returns + ------- + AsyncPager[AsyncAgentSession, ListSessionsResponse] + Paginated sessions. + """ raw_pager = await self._client.agents.sessions.list( agent_name=agent_name, limit=limit, @@ -202,6 +292,20 @@ async def get_session( *, request_options: typing.Optional[RequestOptions] = None, ) -> AsyncAgentSession: - """Fetch a session by ID.""" + """ + Fetch a session by ID. + + Parameters + ---------- + session_id : str + Unique identifier of the session to fetch. + request_options : typing.Optional[RequestOptions] + Overrides client timeout, retries, headers, and stream reconnect. + + Returns + ------- + AsyncAgentSession + Session data. + """ response = await self._client.agents.sessions.get(session_id, request_options=request_options) return AsyncAgentSession(response.data, self._client) diff --git a/src/truefoundry_gateway_sdk/agents/event_delta.py b/src/truefoundry_gateway_sdk/agents/event_delta.py index 4b57455..2d96573 100644 --- a/src/truefoundry_gateway_sdk/agents/event_delta.py +++ b/src/truefoundry_gateway_sdk/agents/event_delta.py @@ -14,12 +14,38 @@ def is_event_delta(event: TurnStreamingEvent) -> bool: - """True for incremental SSE chunks (e.g. ``model.message.delta``).""" + """ + True for ``.delta`` streaming events. + + Parameters + ---------- + event : TurnStreamingEvent + Streaming event to check for delta type. + + Returns + ------- + bool + True if the event is a delta chunk. + """ return event.type.endswith(".delta") def merge_event_delta(base: TurnEvent, delta: DeltaEvents) -> None: - """Apply a delta chunk to its full event in place when streaming (same ``id`` required).""" + """ + Merge ``delta`` into ``base`` in place (same ``id`` required). + + Parameters + ---------- + base : TurnEvent + Base event to merge delta chunks into. + delta : DeltaEvents + Delta chunk to merge into the base event. + + Returns + ------- + None + Updates ``base`` in place. + """ if base.id != delta.id: raise ValueError(f'Cannot merge delta into a different event: base id "{base.id}" != delta id "{delta.id}".') if isinstance(delta, ModelMessageDeltaEvent) and isinstance(base, ModelMessageEvent): diff --git a/src/truefoundry_gateway_sdk/agents/prepared_turn.py b/src/truefoundry_gateway_sdk/agents/prepared_turn.py index 078345d..3d55504 100644 --- a/src/truefoundry_gateway_sdk/agents/prepared_turn.py +++ b/src/truefoundry_gateway_sdk/agents/prepared_turn.py @@ -48,35 +48,82 @@ def __repr__(self) -> str: @property def session(self) -> "AgentSession": + """ + Returns + ------- + AgentSession + Parent session this prepared turn belongs to. + """ return self._session @property def session_id(self) -> str: + """ + Returns + ------- + str + Identifier of the parent session. + """ return self._session_id @property def id(self) -> typing.Optional[str]: - """None until ``execute()`` has started the turn.""" + """ + Returns + ------- + typing.Optional[str] + None until ``execute()`` starts the turn. + """ return self._turn.id if self._turn is not None else None @property def previous_turn_id(self) -> typing.Optional[str]: + """ + Returns + ------- + typing.Optional[str] + None until ``execute()`` starts the turn. + """ return self._turn.previous_turn_id if self._turn is not None else None @property def state(self) -> typing.Optional[TurnState]: + """ + Returns + ------- + typing.Optional[TurnState] + None until ``execute()`` starts the turn. + """ return self._turn.state if self._turn is not None else None @property def created_by_subject(self) -> typing.Optional[Subject]: + """ + Returns + ------- + typing.Optional[Subject] + None until ``execute()`` starts the turn. + """ return self._turn.created_by_subject if self._turn is not None else None @property def created_at(self) -> typing.Optional[str]: + """ + Returns + ------- + typing.Optional[str] + None until ``execute()`` starts the turn. + """ return self._turn.created_at if self._turn is not None else None @property def input(self) -> typing.Optional[typing.List[TurnInputItem]]: + """ + Returns + ------- + typing.Optional[typing.List[TurnInputItem]] + Staged input before ``execute()``; inner turn input after. + """ if self._turn is not None: return self._turn.input return self._input # type: ignore[return-value] @@ -107,7 +154,28 @@ def execute( poll_interval_ms: int = 3000, request_options: typing.Optional[RequestOptions] = None, ) -> typing.Union[typing.Iterator[TurnStreamData], TurnState]: - """Start the turn via create_turn. ``stream=True`` (default) yields SSE from that POST (not resumable; after disconnect call ``stream()`` to subscribe_to_turn). ``stream=False`` polls ``get_turn`` until done, cancelled, or error.""" + """ + Start the turn via ``create_turn``. + + Parameters + ---------- + stream : bool + Stream ``create_turn`` SSE when true. Default true. + poll_interval_ms : int + Poll interval ms when ``stream=False``. Minimum 3000. + request_options : typing.Optional[RequestOptions] + Overrides client timeout, retries, headers, and stream reconnect. + + Returns + ------- + TurnState + Terminal turn state. + + Yields + ------ + TurnStreamData + SSE stream from create_turn. + """ if self._started: raise RuntimeError("Turn already started; use stream() / wait_for_completion().") self._started = True @@ -124,13 +192,39 @@ def stream( after_sequence_number: typing.Optional[int] = None, request_options: typing.Optional[RequestOptions] = None, ) -> typing.Iterator[TurnStreamData]: - """Subscribe to live SSE via subscribe_to_turn after ``execute()`` has started the turn. Pass ``after_sequence_number`` to resume; updates state from turn.created and turn.done.""" + """ + Resubscribe via ``subscribe_to_turn`` after ``execute()``. + + Parameters + ---------- + after_sequence_number : typing.Optional[int] + Sequence number to resume SSE subscription after. + request_options : typing.Optional[RequestOptions] + Overrides client timeout, retries, headers, and stream reconnect. + + Yields + ------ + TurnStreamData + SSE stream items. + """ yield from self._must_get_turn().stream( after_sequence_number=after_sequence_number, request_options=request_options ) def refresh(self, *, request_options: typing.Optional[RequestOptions] = None) -> "PreparedTurn": - """Refetch from the server, update state in-place and return self.""" + """ + Refetch from the server, update state in-place and return self. + + Parameters + ---------- + request_options : typing.Optional[RequestOptions] + Overrides client timeout, retries, headers, and stream reconnect. + + Returns + ------- + PreparedTurn + This prepared turn with updated state. + """ self._must_get_turn().refresh(request_options=request_options) return self @@ -140,13 +234,38 @@ def wait_for_completion( poll_interval_ms: int = 3000, request_options: typing.Optional[RequestOptions] = None, ) -> TurnState: - """Poll ``get_turn`` until the turn is done, cancelled, or errored. ``poll_interval_ms`` minimum is 3000.""" + """ + Poll ``get_turn`` until terminal. + + Parameters + ---------- + poll_interval_ms : int + Poll interval ms while waiting for completion. Minimum 3000. + request_options : typing.Optional[RequestOptions] + Overrides client timeout, retries, headers, and stream reconnect. + + Returns + ------- + TurnState + Terminal turn state. + """ return self._must_get_turn().wait_for_completion( poll_interval_ms=poll_interval_ms, request_options=request_options ) def cancel(self, *, request_options: typing.Optional[RequestOptions] = None) -> None: - """Cancel the running last turn for the session.""" + """ + Cancel the running last turn for the session. + + Parameters + ---------- + request_options : typing.Optional[RequestOptions] + Overrides client timeout, retries, headers, and stream reconnect. + + Returns + ------- + None + """ return self._must_get_turn().cancel(request_options=request_options) def list_events( @@ -157,7 +276,25 @@ def list_events( order: typing.Optional[ListEventsOrder] = None, request_options: typing.Optional[RequestOptions] = None, ) -> SyncPager[TurnEvent, ListEventsResponse]: - """Paginated persisted TurnEvent history (no streaming deltas). Use ``stream()`` for live TurnStreamingEvent SSE.""" + """ + Paginated persisted events; use ``stream()`` for live SSE. + + Parameters + ---------- + page_token : typing.Optional[str] + Token from the previous response ``next_page_token``. + limit : typing.Optional[int] + Page size. Default 25. + order : typing.Optional[ListEventsOrder] + Sort by creation time. Default ``asc``. + request_options : typing.Optional[RequestOptions] + Overrides client timeout, retries, headers, and stream reconnect. + + Returns + ------- + SyncPager[TurnEvent, ListEventsResponse] + Paginated turn events. + """ return self._must_get_turn().list_events( page_token=page_token, limit=limit, order=order, request_options=request_options ) @@ -263,35 +400,82 @@ def __repr__(self) -> str: @property def session(self) -> "AsyncAgentSession": + """ + Returns + ------- + AsyncAgentSession + Parent session this prepared turn belongs to. + """ return self._session @property def session_id(self) -> str: + """ + Returns + ------- + str + Identifier of the parent session. + """ return self._session_id @property def id(self) -> typing.Optional[str]: - """None until ``execute()`` has started the turn.""" + """ + Returns + ------- + typing.Optional[str] + None until ``execute()`` starts the turn. + """ return self._turn.id if self._turn is not None else None @property def previous_turn_id(self) -> typing.Optional[str]: + """ + Returns + ------- + typing.Optional[str] + None until ``execute()`` starts the turn. + """ return self._turn.previous_turn_id if self._turn is not None else None @property def state(self) -> typing.Optional[TurnState]: + """ + Returns + ------- + typing.Optional[TurnState] + None until ``execute()`` starts the turn. + """ return self._turn.state if self._turn is not None else None @property def created_by_subject(self) -> typing.Optional[Subject]: + """ + Returns + ------- + typing.Optional[Subject] + None until ``execute()`` starts the turn. + """ return self._turn.created_by_subject if self._turn is not None else None @property def created_at(self) -> typing.Optional[str]: + """ + Returns + ------- + typing.Optional[str] + None until ``execute()`` starts the turn. + """ return self._turn.created_at if self._turn is not None else None @property def input(self) -> typing.Optional[typing.List[TurnInputItem]]: + """ + Returns + ------- + typing.Optional[typing.List[TurnInputItem]] + Staged input before ``execute()``; inner turn input after. + """ if self._turn is not None: return self._turn.input return self._input # type: ignore[return-value] @@ -322,7 +506,28 @@ def execute( poll_interval_ms: int = 3000, request_options: typing.Optional[RequestOptions] = None, ) -> typing.Union[typing.AsyncIterator[TurnStreamData], "typing.Coroutine[typing.Any, typing.Any, TurnState]"]: - """Start the turn via create_turn. ``stream=True`` (default) yields SSE from that POST (not resumable; after disconnect call ``stream()`` to subscribe_to_turn). ``stream=False`` polls ``get_turn`` until done, cancelled, or error.""" + """ + Start the turn via ``create_turn``. + + Parameters + ---------- + stream : bool + Stream ``create_turn`` SSE when true. Default true. + poll_interval_ms : int + Poll interval ms when ``stream=False``. Minimum 3000. + request_options : typing.Optional[RequestOptions] + Overrides client timeout, retries, headers, and stream reconnect. + + Returns + ------- + TurnState + Terminal turn state. + + Yields + ------ + TurnStreamData + SSE stream from create_turn. + """ if self._started: raise RuntimeError("Turn already started; use stream() / wait_for_completion().") self._started = True @@ -339,14 +544,40 @@ async def stream( after_sequence_number: typing.Optional[int] = None, request_options: typing.Optional[RequestOptions] = None, ) -> typing.AsyncIterator[TurnStreamData]: - """Subscribe to live SSE via subscribe_to_turn after ``execute()`` has started the turn. Pass ``after_sequence_number`` to resume; updates state from turn.created and turn.done.""" + """ + Resubscribe via ``subscribe_to_turn`` after ``execute()``. + + Parameters + ---------- + after_sequence_number : typing.Optional[int] + Sequence number to resume SSE subscription after. + request_options : typing.Optional[RequestOptions] + Overrides client timeout, retries, headers, and stream reconnect. + + Yields + ------ + TurnStreamData + SSE stream items. + """ async for item in self._must_get_turn().stream( after_sequence_number=after_sequence_number, request_options=request_options ): yield item async def refresh(self, *, request_options: typing.Optional[RequestOptions] = None) -> "AsyncPreparedTurn": - """Refetch from the server, update state in-place and return self.""" + """ + Refetch from the server, update state in-place and return self. + + Parameters + ---------- + request_options : typing.Optional[RequestOptions] + Overrides client timeout, retries, headers, and stream reconnect. + + Returns + ------- + AsyncPreparedTurn + This prepared turn with updated state. + """ await self._must_get_turn().refresh(request_options=request_options) return self @@ -356,13 +587,38 @@ async def wait_for_completion( poll_interval_ms: int = 3000, request_options: typing.Optional[RequestOptions] = None, ) -> TurnState: - """Poll ``get_turn`` until the turn is done, cancelled, or errored. ``poll_interval_ms`` minimum is 3000.""" + """ + Poll ``get_turn`` until terminal. + + Parameters + ---------- + poll_interval_ms : int + Poll interval ms while waiting for completion. Minimum 3000. + request_options : typing.Optional[RequestOptions] + Overrides client timeout, retries, headers, and stream reconnect. + + Returns + ------- + TurnState + Terminal turn state. + """ return await self._must_get_turn().wait_for_completion( poll_interval_ms=poll_interval_ms, request_options=request_options ) async def cancel(self, *, request_options: typing.Optional[RequestOptions] = None) -> None: - """Cancel the running last turn for the session.""" + """ + Cancel the running last turn for the session. + + Parameters + ---------- + request_options : typing.Optional[RequestOptions] + Overrides client timeout, retries, headers, and stream reconnect. + + Returns + ------- + None + """ return await self._must_get_turn().cancel(request_options=request_options) async def list_events( @@ -373,7 +629,25 @@ async def list_events( order: typing.Optional[ListEventsOrder] = None, request_options: typing.Optional[RequestOptions] = None, ) -> AsyncPager[TurnEvent, ListEventsResponse]: - """Paginated persisted TurnEvent history (no streaming deltas). Use ``stream()`` for live TurnStreamingEvent SSE.""" + """ + Paginated persisted events; use ``stream()`` for live SSE. + + Parameters + ---------- + page_token : typing.Optional[str] + Token from the previous response ``next_page_token``. + limit : typing.Optional[int] + Page size. Default 25. + order : typing.Optional[ListEventsOrder] + Sort by creation time. Default ``asc``. + request_options : typing.Optional[RequestOptions] + Overrides client timeout, retries, headers, and stream reconnect. + + Returns + ------- + AsyncPager[TurnEvent, ListEventsResponse] + Paginated turn events. + """ return await self._must_get_turn().list_events( page_token=page_token, limit=limit, order=order, request_options=request_options ) diff --git a/src/truefoundry_gateway_sdk/agents/turn.py b/src/truefoundry_gateway_sdk/agents/turn.py index 4f94ac8..92b19fd 100644 --- a/src/truefoundry_gateway_sdk/agents/turn.py +++ b/src/truefoundry_gateway_sdk/agents/turn.py @@ -55,35 +55,82 @@ def __repr__(self) -> str: @property def id(self) -> str: + """ + Returns + ------- + str + Unique identifier of this turn. + """ return self._id @property def session_id(self) -> str: + """ + Returns + ------- + str + Identifier of the parent session. + """ return self._session_id @property def previous_turn_id(self) -> typing.Optional[str]: + """ + Returns + ------- + typing.Optional[str] + Previous turn id in the chain, if any. + """ return self._previous_turn_id @property def input(self) -> typing.Optional[typing.List[TurnInputItem]]: + """ + Returns + ------- + typing.Optional[typing.List[TurnInputItem]] + Input items sent when the turn was created. + """ return self._input @property def created_by_subject(self) -> Subject: + """ + Returns + ------- + Subject + Subject that started this turn. + """ return self._created_by_subject @property def created_at(self) -> str: + """ + Returns + ------- + str + ISO-8601 timestamp when the turn was created. + """ return self._created_at @property def state(self) -> TurnState: - """Updated by ``refresh()``, ``stream()``, and ``wait_for_completion()``.""" + """ + Returns + ------- + TurnState + Updated by ``refresh()``, ``stream()``, and ``wait_for_completion()``. + """ return self._state @property def session(self) -> "AgentSession": + """ + Returns + ------- + AgentSession + Parent session this turn belongs to. + """ return self._session def _is_terminal(self, state: TurnState) -> bool: @@ -97,7 +144,19 @@ def _apply_event(self, event: TurnStreamingEvent) -> None: self._state = event.state def refresh(self, *, request_options: typing.Optional[RequestOptions] = None) -> "Turn": - """Refetch from the server, update state in-place and return self.""" + """ + Refetch from the server, update state in-place and return self. + + Parameters + ---------- + request_options : typing.Optional[RequestOptions] + Overrides client timeout, retries, headers, and stream reconnect. + + Returns + ------- + Turn + This turn with updated state. + """ response = self._client.agents.sessions.get_turn(self._session_id, self._id, request_options=request_options) self._state = response.data.state return self @@ -108,7 +167,21 @@ def wait_for_completion( poll_interval_ms: int = _DEFAULT_POLL_INTERVAL_MS, request_options: typing.Optional[RequestOptions] = None, ) -> TurnState: - """Poll ``get_turn`` until the turn is done, cancelled, or errored. ``poll_interval_ms`` minimum is 3000.""" + """ + Poll ``get_turn`` until terminal. + + Parameters + ---------- + poll_interval_ms : int + Poll interval ms while waiting for completion. Minimum 3000. + request_options : typing.Optional[RequestOptions] + Overrides client timeout, retries, headers, and stream reconnect. + + Returns + ------- + TurnState + Terminal turn state. + """ if poll_interval_ms < _MIN_POLL_INTERVAL_MS: raise ValueError(f"poll_interval_ms must be at least {_MIN_POLL_INTERVAL_MS}ms") while not self._is_terminal(self._state): @@ -122,7 +195,21 @@ def stream( after_sequence_number: typing.Optional[int] = None, request_options: typing.Optional[RequestOptions] = None, ) -> typing.Iterator[TurnStreamData]: - """Reconnect to the turn's SSE. Updates state in-place from lifecycle events.""" + """ + Reconnect to the turn's SSE. Updates state in-place from lifecycle events. + + Parameters + ---------- + after_sequence_number : typing.Optional[int] + Sequence number to resume SSE subscription after. + request_options : typing.Optional[RequestOptions] + Overrides client timeout, retries, headers, and stream reconnect. + + Yields + ------ + TurnStreamData + SSE stream items. + """ for event in self._client.agents.sessions.subscribe_to_turn( self._session_id, self._id, @@ -133,7 +220,18 @@ def stream( yield TurnStreamData(sequence_number=None, event=event) def cancel(self, *, request_options: typing.Optional[RequestOptions] = None) -> None: - """Cancel the running last turn for the session.""" + """ + Cancel the running last turn for the session. + + Parameters + ---------- + request_options : typing.Optional[RequestOptions] + Overrides client timeout, retries, headers, and stream reconnect. + + Returns + ------- + None + """ self._client.agents.sessions.cancel(self._session_id, request_options=request_options) def list_events( @@ -144,7 +242,25 @@ def list_events( order: typing.Optional[ListEventsOrder] = None, request_options: typing.Optional[RequestOptions] = None, ) -> SyncPager[TurnEvent, ListEventsResponse]: - """Paginated persisted TurnEvent history (no streaming deltas). Use ``stream()`` for live TurnStreamingEvent SSE.""" + """ + Paginated persisted events; use ``stream()`` for live SSE. + + Parameters + ---------- + page_token : typing.Optional[str] + Token from the previous response ``next_page_token``. + limit : typing.Optional[int] + Page size. Default 25. + order : typing.Optional[ListEventsOrder] + Sort by creation time. Default ``asc``. + request_options : typing.Optional[RequestOptions] + Overrides client timeout, retries, headers, and stream reconnect. + + Returns + ------- + SyncPager[TurnEvent, ListEventsResponse] + Paginated turn events. + """ return self._client.agents.sessions.list_turn_events( self._session_id, self._id, @@ -183,35 +299,82 @@ def __repr__(self) -> str: @property def id(self) -> str: + """ + Returns + ------- + str + Unique identifier of this turn. + """ return self._id @property def session_id(self) -> str: + """ + Returns + ------- + str + Identifier of the parent session. + """ return self._session_id @property def previous_turn_id(self) -> typing.Optional[str]: + """ + Returns + ------- + typing.Optional[str] + Previous turn id in the chain, if any. + """ return self._previous_turn_id @property def input(self) -> typing.Optional[typing.List[TurnInputItem]]: + """ + Returns + ------- + typing.Optional[typing.List[TurnInputItem]] + Input items sent when the turn was created. + """ return self._input @property def created_by_subject(self) -> Subject: + """ + Returns + ------- + Subject + Subject that started this turn. + """ return self._created_by_subject @property def created_at(self) -> str: + """ + Returns + ------- + str + ISO-8601 timestamp when the turn was created. + """ return self._created_at @property def state(self) -> TurnState: - """Updated by ``refresh()``, ``stream()``, and ``wait_for_completion()``.""" + """ + Returns + ------- + TurnState + Updated by ``refresh()``, ``stream()``, and ``wait_for_completion()``. + """ return self._state @property def session(self) -> "AsyncAgentSession": + """ + Returns + ------- + AsyncAgentSession + Parent session this turn belongs to. + """ return self._session def _is_terminal(self, state: TurnState) -> bool: @@ -225,7 +388,19 @@ def _apply_event(self, event: TurnStreamingEvent) -> None: self._state = event.state async def refresh(self, *, request_options: typing.Optional[RequestOptions] = None) -> "AsyncTurn": - """Refetch from the server, update state in-place and return self.""" + """ + Refetch from the server, update state in-place and return self. + + Parameters + ---------- + request_options : typing.Optional[RequestOptions] + Overrides client timeout, retries, headers, and stream reconnect. + + Returns + ------- + AsyncTurn + This turn with updated state. + """ response = await self._client.agents.sessions.get_turn( self._session_id, self._id, request_options=request_options ) @@ -238,7 +413,21 @@ async def wait_for_completion( poll_interval_ms: int = _DEFAULT_POLL_INTERVAL_MS, request_options: typing.Optional[RequestOptions] = None, ) -> TurnState: - """Poll ``get_turn`` until the turn is done, cancelled, or errored. ``poll_interval_ms`` minimum is 3000.""" + """ + Poll ``get_turn`` until terminal. + + Parameters + ---------- + poll_interval_ms : int + Poll interval ms while waiting for completion. Minimum 3000. + request_options : typing.Optional[RequestOptions] + Overrides client timeout, retries, headers, and stream reconnect. + + Returns + ------- + TurnState + Terminal turn state. + """ import asyncio if poll_interval_ms < _MIN_POLL_INTERVAL_MS: @@ -254,7 +443,21 @@ async def stream( after_sequence_number: typing.Optional[int] = None, request_options: typing.Optional[RequestOptions] = None, ) -> typing.AsyncIterator[TurnStreamData]: - """Reconnect to the turn's SSE. Updates state in-place from lifecycle events.""" + """ + Reconnect to the turn's SSE. Updates state in-place from lifecycle events. + + Parameters + ---------- + after_sequence_number : typing.Optional[int] + Sequence number to resume SSE subscription after. + request_options : typing.Optional[RequestOptions] + Overrides client timeout, retries, headers, and stream reconnect. + + Yields + ------ + TurnStreamData + SSE stream items. + """ async for event in self._client.agents.sessions.subscribe_to_turn( self._session_id, self._id, @@ -265,7 +468,18 @@ async def stream( yield TurnStreamData(sequence_number=None, event=event) async def cancel(self, *, request_options: typing.Optional[RequestOptions] = None) -> None: - """Cancel the running last turn for the session.""" + """ + Cancel the running last turn for the session. + + Parameters + ---------- + request_options : typing.Optional[RequestOptions] + Overrides client timeout, retries, headers, and stream reconnect. + + Returns + ------- + None + """ await self._client.agents.sessions.cancel(self._session_id, request_options=request_options) async def list_events( @@ -276,7 +490,25 @@ async def list_events( order: typing.Optional[ListEventsOrder] = None, request_options: typing.Optional[RequestOptions] = None, ) -> AsyncPager[TurnEvent, ListEventsResponse]: - """Paginated persisted TurnEvent history (no streaming deltas). Use ``stream()`` for live TurnStreamingEvent SSE.""" + """ + Paginated persisted events; use ``stream()`` for live SSE. + + Parameters + ---------- + page_token : typing.Optional[str] + Token from the previous response ``next_page_token``. + limit : typing.Optional[int] + Page size. Default 25. + order : typing.Optional[ListEventsOrder] + Sort by creation time. Default ``asc``. + request_options : typing.Optional[RequestOptions] + Overrides client timeout, retries, headers, and stream reconnect. + + Returns + ------- + AsyncPager[TurnEvent, ListEventsResponse] + Paginated turn events. + """ return await self._client.agents.sessions.list_turn_events( self._session_id, self._id, diff --git a/src/truefoundry_gateway_sdk/agents/turn_stream_data.py b/src/truefoundry_gateway_sdk/agents/turn_stream_data.py index fd271de..86cd014 100644 --- a/src/truefoundry_gateway_sdk/agents/turn_stream_data.py +++ b/src/truefoundry_gateway_sdk/agents/turn_stream_data.py @@ -6,7 +6,14 @@ @dataclasses.dataclass class TurnStreamData: - """An SSE item with a TurnStreamingEvent; ``sequence_number`` is the SSE event id for resuming via ``subscribe_to_turn``.""" + """ + Attributes + ---------- + sequence_number : typing.Optional[int] + SSE event id for resume; None if unavailable from the stream. + event : TurnStreamingEvent + Streaming event payload. + """ # Sequence number from the SSE event id. None when not available from the underlying stream. sequence_number: typing.Optional[int] diff --git a/src/truefoundry_gateway_sdk/client.py b/src/truefoundry_gateway_sdk/client.py index b149380..e391e37 100644 --- a/src/truefoundry_gateway_sdk/client.py +++ b/src/truefoundry_gateway_sdk/client.py @@ -42,7 +42,12 @@ def __init__( @property def agents(self) -> AgentsClient: - """Agent sessions and turns.""" + """ + Returns + ------- + AgentsClient + Low-level agents client. Prefer ``AgentSessionClient`` for the high-level API. + """ if self._agents is None: self._agents = AgentsClient(client_wrapper=self._client_wrapper) return self._agents @@ -83,7 +88,12 @@ def __init__( @property def agents(self) -> AsyncAgentsClient: - """Agent sessions and turns.""" + """ + Returns + ------- + AsyncAgentsClient + Low-level agents client. Prefer ``AsyncAgentSessionClient`` for the high-level API. + """ if self._agents is None: self._agents = AsyncAgentsClient(client_wrapper=self._client_wrapper) return self._agents