diff --git a/src/runloop_api_client/sdk/__init__.py b/src/runloop_api_client/sdk/__init__.py index 5207da1e6..752d5857c 100644 --- a/src/runloop_api_client/sdk/__init__.py +++ b/src/runloop_api_client/sdk/__init__.py @@ -5,8 +5,10 @@ from __future__ import annotations -from .sync import DevboxOps, RunloopSDK, SnapshotOps, BlueprintOps, StorageObjectOps +from .sync import AgentOps, DevboxOps, RunloopSDK, SnapshotOps, BlueprintOps, StorageObjectOps +from .agent import Agent from .async_ import ( + AsyncAgentOps, AsyncDevboxOps, AsyncRunloopSDK, AsyncSnapshotOps, @@ -17,6 +19,7 @@ from .snapshot import Snapshot from .blueprint import Blueprint from .execution import Execution +from .async_agent import AsyncAgent from .async_devbox import AsyncDevbox from .async_snapshot import AsyncSnapshot from .storage_object import StorageObject @@ -31,6 +34,8 @@ "RunloopSDK", "AsyncRunloopSDK", # Management interfaces + "AgentOps", + "AsyncAgentOps", "DevboxOps", "AsyncDevboxOps", "BlueprintOps", @@ -40,6 +45,8 @@ "StorageObjectOps", "AsyncStorageObjectOps", # Resource classes + "Agent", + "AsyncAgent", "Devbox", "AsyncDevbox", "Execution", diff --git a/src/runloop_api_client/sdk/_types.py b/src/runloop_api_client/sdk/_types.py index 7ac404055..0ddde081b 100644 --- a/src/runloop_api_client/sdk/_types.py +++ b/src/runloop_api_client/sdk/_types.py @@ -5,8 +5,10 @@ from .._types import Body, Query, Headers, Timeout, NotGiven from ..lib.polling import PollingConfig +from ..types.agent_list_params import AgentListParams from ..types.devbox_list_params import DevboxListParams from ..types.object_list_params import ObjectListParams +from ..types.agent_create_params import AgentCreateParams from ..types.devbox_create_params import DevboxCreateParams, DevboxBaseCreateParams from ..types.object_create_params import ObjectCreateParams from ..types.blueprint_list_params import BlueprintListParams @@ -142,3 +144,11 @@ class SDKObjectCreateParams(ObjectCreateParams, LongRequestOptions): class SDKObjectDownloadParams(ObjectDownloadParams, RequestOptions): pass + + +class SDKAgentCreateParams(AgentCreateParams, LongRequestOptions): + pass + + +class SDKAgentListParams(AgentListParams, RequestOptions): + pass diff --git a/src/runloop_api_client/sdk/agent.py b/src/runloop_api_client/sdk/agent.py new file mode 100644 index 000000000..2484cdd1f --- /dev/null +++ b/src/runloop_api_client/sdk/agent.py @@ -0,0 +1,58 @@ +"""Agent resource class for synchronous operations.""" + +from __future__ import annotations + +from typing_extensions import Unpack, override + +from ._types import ( + RequestOptions, +) +from .._client import Runloop +from ..types.agent_view import AgentView + + +class Agent: + """Wrapper around synchronous agent operations.""" + + def __init__( + self, + client: Runloop, + agent_id: str, + ) -> None: + """Initialize the wrapper. + + :param client: Generated Runloop client + :type client: Runloop + :param agent_id: Agent identifier returned by the API + :type agent_id: str + """ + self._client = client + self._id = agent_id + + @override + def __repr__(self) -> str: + return f"" + + @property + def id(self) -> str: + """Return the agent identifier. + + :return: Unique agent ID + :rtype: str + """ + return self._id + + def get_info( + self, + **options: Unpack[RequestOptions], + ) -> AgentView: + """Retrieve the latest agent information. + + :param options: Optional request configuration + :return: Agent details + :rtype: AgentView + """ + return self._client.agents.retrieve( + self._id, + **options, + ) diff --git a/src/runloop_api_client/sdk/async_.py b/src/runloop_api_client/sdk/async_.py index ef3191791..c3acb10eb 100644 --- a/src/runloop_api_client/sdk/async_.py +++ b/src/runloop_api_client/sdk/async_.py @@ -10,8 +10,10 @@ from ._types import ( LongRequestOptions, + SDKAgentListParams, SDKDevboxListParams, SDKObjectListParams, + SDKAgentCreateParams, SDKDevboxCreateParams, SDKObjectCreateParams, SDKBlueprintListParams, @@ -22,6 +24,7 @@ from .._types import Timeout, NotGiven, not_given from .._client import DEFAULT_MAX_RETRIES, AsyncRunloop from ._helpers import detect_content_type +from .async_agent import AsyncAgent from .async_devbox import AsyncDevbox from .async_snapshot import AsyncSnapshot from .async_blueprint import AsyncBlueprint @@ -415,6 +418,67 @@ async def upload_from_bytes( return obj +class AsyncAgentOps: + """High-level async manager for creating and managing agents. + + Accessed via ``runloop.agent`` from :class:`AsyncRunloopSDK`, provides + coroutines to create, retrieve, and list agents. + + Example: + >>> runloop = AsyncRunloopSDK() + >>> agent = await runloop.agent.create(name="my-agent") + >>> agents = await runloop.agent.list(limit=10) + """ + + def __init__(self, client: AsyncRunloop) -> None: + """Initialize the manager. + + :param client: Generated AsyncRunloop client to wrap + :type client: AsyncRunloop + """ + self._client = client + + async def create( + self, + **params: Unpack[SDKAgentCreateParams], + ) -> AsyncAgent: + """Create a new agent. + + :param params: See :typeddict:`~runloop_api_client.sdk._types.SDKAgentCreateParams` for available parameters + :return: Wrapper bound to the newly created agent + :rtype: AsyncAgent + """ + agent_view = await self._client.agents.create( + **params, + ) + return AsyncAgent(self._client, agent_view.id) + + def from_id(self, agent_id: str) -> AsyncAgent: + """Attach to an existing agent by ID. + + :param agent_id: Existing agent ID + :type agent_id: str + :return: Wrapper bound to the requested agent + :rtype: AsyncAgent + """ + return AsyncAgent(self._client, agent_id) + + async def list( + self, + **params: Unpack[SDKAgentListParams], + ) -> list[AsyncAgent]: + """List agents accessible to the caller. + + :param params: See :typeddict:`~runloop_api_client.sdk._types.SDKAgentListParams` for available parameters + :return: Collection of agent wrappers + :rtype: list[AsyncAgent] + """ + page = await self._client.agents.list( + **params, + ) + return [AsyncAgent(self._client, item.id) for item in page.agents] + + class AsyncRunloopSDK: """High-level asynchronous entry point for the Runloop SDK. @@ -424,6 +488,8 @@ class AsyncRunloopSDK: :ivar api: Direct access to the generated async REST API client :vartype api: AsyncRunloop + :ivar agent: High-level async interface for agent management + :vartype agent: AsyncAgentOps :ivar devbox: High-level async interface for devbox management :vartype devbox: AsyncDevboxOps :ivar blueprint: High-level async interface for blueprint management @@ -442,6 +508,7 @@ class AsyncRunloopSDK: """ api: AsyncRunloop + agent: AsyncAgentOps devbox: AsyncDevboxOps blueprint: AsyncBlueprintOps snapshot: AsyncSnapshotOps @@ -485,6 +552,7 @@ def __init__( http_client=http_client, ) + self.agent = AsyncAgentOps(self.api) self.devbox = AsyncDevboxOps(self.api) self.blueprint = AsyncBlueprintOps(self.api) self.snapshot = AsyncSnapshotOps(self.api) diff --git a/src/runloop_api_client/sdk/async_agent.py b/src/runloop_api_client/sdk/async_agent.py new file mode 100644 index 000000000..2d143a5dc --- /dev/null +++ b/src/runloop_api_client/sdk/async_agent.py @@ -0,0 +1,58 @@ +"""Agent resource class for asynchronous operations.""" + +from __future__ import annotations + +from typing_extensions import Unpack, override + +from ._types import ( + RequestOptions, +) +from .._client import AsyncRunloop +from ..types.agent_view import AgentView + + +class AsyncAgent: + """Async wrapper around agent operations.""" + + def __init__( + self, + client: AsyncRunloop, + agent_id: str, + ) -> None: + """Initialize the wrapper. + + :param client: Generated AsyncRunloop client + :type client: AsyncRunloop + :param agent_id: Agent identifier returned by the API + :type agent_id: str + """ + self._client = client + self._id = agent_id + + @override + def __repr__(self) -> str: + return f"" + + @property + def id(self) -> str: + """Return the agent identifier. + + :return: Unique agent ID + :rtype: str + """ + return self._id + + async def get_info( + self, + **options: Unpack[RequestOptions], + ) -> AgentView: + """Retrieve the latest agent information. + + :param options: Optional request configuration + :return: Agent details + :rtype: AgentView + """ + return await self._client.agents.retrieve( + self._id, + **options, + ) diff --git a/src/runloop_api_client/sdk/sync.py b/src/runloop_api_client/sdk/sync.py index 04d9b67cf..ec6d9c7b1 100644 --- a/src/runloop_api_client/sdk/sync.py +++ b/src/runloop_api_client/sdk/sync.py @@ -8,10 +8,13 @@ import httpx +from .agent import Agent from ._types import ( LongRequestOptions, + SDKAgentListParams, SDKDevboxListParams, SDKObjectListParams, + SDKAgentCreateParams, SDKDevboxCreateParams, SDKObjectCreateParams, SDKBlueprintListParams, @@ -415,6 +418,67 @@ def upload_from_bytes( return obj +class AgentOps: + """High-level manager for creating and managing agents. + + Accessed via ``runloop.agent`` from :class:`RunloopSDK`, provides methods to + create, retrieve, and list agents. + + Example: + >>> runloop = RunloopSDK() + >>> agent = runloop.agent.create(name="my-agent") + >>> agents = runloop.agent.list(limit=10) + """ + + def __init__(self, client: Runloop) -> None: + """Initialize the manager. + + :param client: Generated Runloop client to wrap + :type client: Runloop + """ + self._client = client + + def create( + self, + **params: Unpack[SDKAgentCreateParams], + ) -> Agent: + """Create a new agent. + + :param params: See :typeddict:`~runloop_api_client.sdk._types.SDKAgentCreateParams` for available parameters + :return: Wrapper bound to the newly created agent + :rtype: Agent + """ + agent_view = self._client.agents.create( + **params, + ) + return Agent(self._client, agent_view.id) + + def from_id(self, agent_id: str) -> Agent: + """Attach to an existing agent by ID. + + :param agent_id: Existing agent ID + :type agent_id: str + :return: Wrapper bound to the requested agent + :rtype: Agent + """ + return Agent(self._client, agent_id) + + def list( + self, + **params: Unpack[SDKAgentListParams], + ) -> list[Agent]: + """List agents accessible to the caller. + + :param params: See :typeddict:`~runloop_api_client.sdk._types.SDKAgentListParams` for available parameters + :return: Collection of agent wrappers + :rtype: list[Agent] + """ + page = self._client.agents.list( + **params, + ) + return [Agent(self._client, item.id) for item in page.agents] + + class RunloopSDK: """High-level synchronous entry point for the Runloop SDK. @@ -424,6 +488,8 @@ class RunloopSDK: :ivar api: Direct access to the generated REST API client :vartype api: Runloop + :ivar agent: High-level interface for agent management + :vartype agent: AgentOps :ivar devbox: High-level interface for devbox management :vartype devbox: DevboxOps :ivar blueprint: High-level interface for blueprint management @@ -442,6 +508,7 @@ class RunloopSDK: """ api: Runloop + agent: AgentOps devbox: DevboxOps blueprint: BlueprintOps snapshot: SnapshotOps @@ -485,6 +552,7 @@ def __init__( http_client=http_client, ) + self.agent = AgentOps(self.api) self.devbox = DevboxOps(self.api) self.blueprint = BlueprintOps(self.api) self.snapshot = SnapshotOps(self.api)