diff --git a/src/truefoundry_gateway_sdk/agents/agent_session.py b/src/truefoundry_gateway_sdk/agents/agent_session.py index 3f876f5..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,6 +141,21 @@ def prepare_turn( input: typing.Optional[typing.Sequence[TurnInputItem]] = None, previous_turn_id: typing.Optional[PreviousTurnIdInput] = None, ) -> PreparedTurn: + """ + 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, @@ -119,6 +170,23 @@ def list_turns( limit: typing.Optional[int] = 10, request_options: typing.Optional[RequestOptions] = None, ) -> SyncPager[Turn, ListTurnsResponse]: + """ + 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 ) @@ -130,10 +198,37 @@ def get_turn( *, request_options: typing.Optional[RequestOptions] = None, ) -> Turn: + """ + 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. + + 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) @@ -156,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( @@ -184,6 +315,21 @@ def prepare_turn( input: typing.Optional[typing.Sequence[TurnInputItem]] = None, previous_turn_id: typing.Optional[PreviousTurnIdInput] = None, ) -> AsyncPreparedTurn: + """ + 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, @@ -198,6 +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. + + 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 ) @@ -209,8 +372,35 @@ async def get_turn( *, request_options: typing.Optional[RequestOptions] = None, ) -> AsyncTurn: + """ + 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. + + 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 286de18..d0f7842 100644 --- a/src/truefoundry_gateway_sdk/agents/agent_session_client.py +++ b/src/truefoundry_gateway_sdk/agents/agent_session_client.py @@ -92,6 +92,21 @@ def create_session( agent_name: str, request_options: typing.Optional[RequestOptions] = None, ) -> AgentSession: + """ + 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) @@ -106,6 +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. + + 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, @@ -123,6 +163,21 @@ def get_session( *, request_options: typing.Optional[RequestOptions] = None, ) -> AgentSession: + """ + 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) @@ -166,6 +221,21 @@ async def create_session( agent_name: str, request_options: typing.Optional[RequestOptions] = None, ) -> AsyncAgentSession: + """ + 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) @@ -180,6 +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. + + 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, @@ -197,5 +292,20 @@ async def get_session( *, request_options: typing.Optional[RequestOptions] = None, ) -> AsyncAgentSession: + """ + 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 ef014cb..2d96573 100644 --- a/src/truefoundry_gateway_sdk/agents/event_delta.py +++ b/src/truefoundry_gateway_sdk/agents/event_delta.py @@ -14,10 +14,38 @@ def is_event_delta(event: TurnStreamingEvent) -> bool: + """ + 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: + """ + 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 f56946e..3d55504 100644 --- a/src/truefoundry_gateway_sdk/agents/prepared_turn.py +++ b/src/truefoundry_gateway_sdk/agents/prepared_turn.py @@ -48,34 +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]: + """ + 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] @@ -106,6 +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``. + + 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 @@ -122,11 +192,39 @@ def stream( after_sequence_number: typing.Optional[int] = None, request_options: typing.Optional[RequestOptions] = None, ) -> typing.Iterator[TurnStreamData]: + """ + 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. + + 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 @@ -136,11 +234,38 @@ def wait_for_completion( poll_interval_ms: int = 3000, request_options: typing.Optional[RequestOptions] = None, ) -> TurnState: + """ + 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. + + 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( @@ -151,6 +276,25 @@ def list_events( order: typing.Optional[ListEventsOrder] = None, request_options: typing.Optional[RequestOptions] = None, ) -> SyncPager[TurnEvent, ListEventsResponse]: + """ + 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 ) @@ -256,34 +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]: + """ + 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] @@ -314,6 +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``. + + 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 @@ -330,12 +544,40 @@ async def stream( after_sequence_number: typing.Optional[int] = None, request_options: typing.Optional[RequestOptions] = None, ) -> typing.AsyncIterator[TurnStreamData]: + """ + 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. + + 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 @@ -345,11 +587,38 @@ async def wait_for_completion( poll_interval_ms: int = 3000, request_options: typing.Optional[RequestOptions] = None, ) -> TurnState: + """ + 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. + + 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( @@ -360,6 +629,25 @@ async def list_events( order: typing.Optional[ListEventsOrder] = None, request_options: typing.Optional[RequestOptions] = None, ) -> AsyncPager[TurnEvent, ListEventsResponse]: + """ + 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 e46c6c8..92b19fd 100644 --- a/src/truefoundry_gateway_sdk/agents/turn.py +++ b/src/truefoundry_gateway_sdk/agents/turn.py @@ -55,34 +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: + """ + 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: @@ -96,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 @@ -107,6 +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 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): @@ -120,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, @@ -131,6 +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. + + 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( @@ -141,6 +242,25 @@ def list_events( order: typing.Optional[ListEventsOrder] = None, request_options: typing.Optional[RequestOptions] = None, ) -> SyncPager[TurnEvent, ListEventsResponse]: + """ + 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, @@ -179,34 +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: + """ + 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: @@ -220,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 ) @@ -233,6 +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 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: @@ -248,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, @@ -259,6 +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. + + 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( @@ -269,6 +490,25 @@ async def list_events( order: typing.Optional[ListEventsOrder] = None, request_options: typing.Optional[RequestOptions] = None, ) -> AsyncPager[TurnEvent, ListEventsResponse]: + """ + 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 191ea16..86cd014 100644 --- a/src/truefoundry_gateway_sdk/agents/turn_stream_data.py +++ b/src/truefoundry_gateway_sdk/agents/turn_stream_data.py @@ -6,6 +6,15 @@ @dataclasses.dataclass class TurnStreamData: + """ + 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] event: TurnStreamingEvent diff --git a/src/truefoundry_gateway_sdk/client.py b/src/truefoundry_gateway_sdk/client.py index 4058056..e391e37 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,20 @@ def __init__( @property def agents(self) -> AgentsClient: + """ + 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 class AsyncTrueFoundryGateway(AsyncBaseTrueFoundryGateway): + """Asynchronous client for the TrueFoundry Gateway API.""" + def __init__( self, *, @@ -78,6 +88,12 @@ def __init__( @property def agents(self) -> AsyncAgentsClient: + """ + 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