Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions scripts/lint
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,8 @@ uv run mypy .
echo "==> Running lints"
uv run ruff check . "$@"

echo "==> Running format check"
uv run ruff format --check .

echo "==> Making sure it imports"
uv run python -c 'import runloop_api_client'
8 changes: 8 additions & 0 deletions src/runloop_api_client/sdk/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
SnapshotOps,
BenchmarkOps,
BlueprintOps,
GatewayConfigOps,
NetworkPolicyOps,
StorageObjectOps,
)
Expand All @@ -28,6 +29,7 @@
AsyncSnapshotOps,
AsyncBenchmarkOps,
AsyncBlueprintOps,
AsyncGatewayConfigOps,
AsyncNetworkPolicyOps,
AsyncStorageObjectOps,
)
Expand All @@ -45,6 +47,7 @@
from .benchmark_run import BenchmarkRun
from .async_scenario import AsyncScenario
from .async_snapshot import AsyncSnapshot
from .gateway_config import GatewayConfig
from .network_policy import NetworkPolicy
from .storage_object import StorageObject
from .async_benchmark import AsyncBenchmark
Expand All @@ -54,6 +57,7 @@
from .scenario_builder import ScenarioBuilder
from .async_scenario_run import AsyncScenarioRun
from .async_benchmark_run import AsyncBenchmarkRun
from .async_gateway_config import AsyncGatewayConfig
from .async_network_policy import AsyncNetworkPolicy
from .async_storage_object import AsyncStorageObject
from .async_execution_result import AsyncExecutionResult
Expand Down Expand Up @@ -82,6 +86,8 @@
"AsyncStorageObjectOps",
"NetworkPolicyOps",
"AsyncNetworkPolicyOps",
"GatewayConfigOps",
"AsyncGatewayConfigOps",
# Resource classes
"Agent",
"AsyncAgent",
Expand Down Expand Up @@ -112,6 +118,8 @@
"AsyncStorageObject",
"NetworkPolicy",
"AsyncNetworkPolicy",
"GatewayConfig",
"AsyncGatewayConfig",
"NamedShell",
"AsyncNamedShell",
]
15 changes: 15 additions & 0 deletions src/runloop_api_client/sdk/_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,15 @@
BenchmarkUpdateParams,
BlueprintCreateParams,
DevboxUploadFileParams,
GatewayConfigListParams,
NetworkPolicyListParams,
DevboxCreateTunnelParams,
DevboxDownloadFileParams,
DevboxEnableTunnelParams,
DevboxRemoveTunnelParams,
DevboxSnapshotDiskParams,
GatewayConfigCreateParams,
GatewayConfigUpdateParams,
NetworkPolicyCreateParams,
NetworkPolicyUpdateParams,
DevboxReadFileContentsParams,
Expand Down Expand Up @@ -262,3 +265,15 @@ class SDKNetworkPolicyListParams(NetworkPolicyListParams, BaseRequestOptions):

class SDKNetworkPolicyUpdateParams(NetworkPolicyUpdateParams, LongRequestOptions):
pass


class SDKGatewayConfigCreateParams(GatewayConfigCreateParams, LongRequestOptions):
pass


class SDKGatewayConfigListParams(GatewayConfigListParams, BaseRequestOptions):
pass


class SDKGatewayConfigUpdateParams(GatewayConfigUpdateParams, LongRequestOptions):
pass
91 changes: 91 additions & 0 deletions src/runloop_api_client/sdk/async_.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@
SDKBenchmarkCreateParams,
SDKBlueprintCreateParams,
SDKDiskSnapshotListParams,
SDKGatewayConfigListParams,
SDKNetworkPolicyListParams,
SDKGatewayConfigCreateParams,
SDKNetworkPolicyCreateParams,
SDKDevboxCreateFromImageParams,
)
Expand All @@ -41,6 +43,7 @@
from .async_benchmark import AsyncBenchmark
from .async_blueprint import AsyncBlueprint
from ..lib.context_loader import TarFilter, build_directory_tar
from .async_gateway_config import AsyncGatewayConfig
from .async_network_policy import AsyncNetworkPolicy
from .async_storage_object import AsyncStorageObject
from .async_scenario_builder import AsyncScenarioBuilder
Expand Down Expand Up @@ -924,6 +927,90 @@ async def list(self, **params: Unpack[SDKNetworkPolicyListParams]) -> list[Async
return [AsyncNetworkPolicy(self._client, item.id) for item in page.network_policies]


class AsyncGatewayConfigOps:
"""High-level async manager for creating and managing gateway configurations.

Accessed via ``runloop.gateway_config`` from :class:`AsyncRunloopSDK`, provides
coroutines to create, retrieve, update, delete, and list gateway configs. Gateway configs
define how to proxy API requests through the credential gateway, enabling secure API
proxying without exposing API keys.

Example:
>>> runloop = AsyncRunloopSDK()
>>> gateway_config = await runloop.gateway_config.create(
... name="my-api-gateway",
... endpoint="https://api.example.com",
... auth_mechanism={"type": "bearer"},
... )
>>> # Use with a devbox
>>> devbox = await runloop.devbox.create(
... name="my-devbox",
... gateways={
... "MY_API": {
... "gateway": gateway_config.id,
... "secret": "my-api-key-secret",
... },
... },
... )
"""

def __init__(self, client: AsyncRunloop) -> None:
"""Initialize AsyncGatewayConfigOps.

:param client: AsyncRunloop client instance
:type client: AsyncRunloop
"""
self._client = client

async def create(self, **params: Unpack[SDKGatewayConfigCreateParams]) -> AsyncGatewayConfig:
"""Create a new gateway config.

Example:
>>> gateway_config = await runloop.gateway_config.create(
... name="my-gateway",
... endpoint="https://api.example.com",
... auth_mechanism={"type": "header", "key": "x-api-key"},
... description="Gateway for My API",
... )

:param params: See :typeddict:`~runloop_api_client.sdk._types.SDKGatewayConfigCreateParams` for available parameters
:return: The newly created gateway config
:rtype: AsyncGatewayConfig
"""
response = await self._client.gateway_configs.create(**params)
return AsyncGatewayConfig(self._client, response.id)

def from_id(self, gateway_config_id: str) -> AsyncGatewayConfig:
"""Get an AsyncGatewayConfig instance for an existing gateway config ID.

Example:
>>> gateway_config = runloop.gateway_config.from_id("gwc_1234567890")
>>> info = await gateway_config.get_info()
>>> print(f"Gateway Config name: {info.name}")

:param gateway_config_id: ID of the gateway config
:type gateway_config_id: str
:return: AsyncGatewayConfig instance for the given ID
:rtype: AsyncGatewayConfig
"""
return AsyncGatewayConfig(self._client, gateway_config_id)

async def list(self, **params: Unpack[SDKGatewayConfigListParams]) -> list[AsyncGatewayConfig]:
"""List all gateway configs, optionally filtered by parameters.

Example:
>>> configs = await runloop.gateway_config.list(limit=10)
>>> for config in configs:
... print(config.id)

:param params: See :typeddict:`~runloop_api_client.sdk._types.SDKGatewayConfigListParams` for available parameters
:return: List of gateway configs
:rtype: list[AsyncGatewayConfig]
"""
page = await self._client.gateway_configs.list(**params)
return [AsyncGatewayConfig(self._client, item.id) for item in page.gateway_configs]


class AsyncRunloopSDK:
"""High-level asynchronous entry point for the Runloop SDK.

Expand Down Expand Up @@ -951,6 +1038,8 @@ class AsyncRunloopSDK:
:vartype storage_object: AsyncStorageObjectOps
:ivar network_policy: High-level async interface for network policy management
:vartype network_policy: AsyncNetworkPolicyOps
:ivar gateway_config: High-level async interface for gateway config management
:vartype gateway_config: AsyncGatewayConfigOps

Example:
>>> runloop = AsyncRunloopSDK() # Uses RUNLOOP_API_KEY env var
Expand All @@ -965,6 +1054,7 @@ class AsyncRunloopSDK:
benchmark: AsyncBenchmarkOps
devbox: AsyncDevboxOps
blueprint: AsyncBlueprintOps
gateway_config: AsyncGatewayConfigOps
network_policy: AsyncNetworkPolicyOps
scenario: AsyncScenarioOps
scorer: AsyncScorerOps
Expand Down Expand Up @@ -1013,6 +1103,7 @@ def __init__(
self.benchmark = AsyncBenchmarkOps(self.api)
self.devbox = AsyncDevboxOps(self.api)
self.blueprint = AsyncBlueprintOps(self.api)
self.gateway_config = AsyncGatewayConfigOps(self.api)
self.network_policy = AsyncNetworkPolicyOps(self.api)
self.scenario = AsyncScenarioOps(self.api)
self.scorer = AsyncScorerOps(self.api)
Expand Down
108 changes: 108 additions & 0 deletions src/runloop_api_client/sdk/async_gateway_config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
"""GatewayConfig resource class for asynchronous operations."""

from __future__ import annotations

from typing_extensions import Unpack, override

from ._types import BaseRequestOptions, LongRequestOptions, SDKGatewayConfigUpdateParams
from .._client import AsyncRunloop
from ..types.gateway_config_view import GatewayConfigView


class AsyncGatewayConfig:
"""Asynchronous wrapper around a gateway config resource.

Gateway configs define how to proxy API requests through the credential gateway.
They specify the target endpoint and how credentials should be applied. Use with
devboxes to securely proxy requests to external APIs without exposing API keys.

Example:
>>> runloop = AsyncRunloopSDK()
>>> gateway_config = await runloop.gateway_config.create(
... name="my-api-gateway",
... endpoint="https://api.example.com",
... auth_mechanism={"type": "bearer"},
... )
>>> info = await gateway_config.get_info()
>>> print(f"Gateway Config: {info.name}")
"""

def __init__(
self,
client: AsyncRunloop,
gateway_config_id: str,
) -> None:
"""Initialize the wrapper.

:param client: Generated AsyncRunloop client
:type client: AsyncRunloop
:param gateway_config_id: GatewayConfig ID returned by the API
:type gateway_config_id: str
"""
self._client = client
self._id = gateway_config_id

@override
def __repr__(self) -> str:
return f"<AsyncGatewayConfig id={self._id!r}>"

@property
def id(self) -> str:
"""Return the gateway config ID.

:return: Unique gateway config ID
:rtype: str
"""
return self._id

async def get_info(
self,
**options: Unpack[BaseRequestOptions],
) -> GatewayConfigView:
"""Retrieve the latest gateway config details.

Example:
>>> info = await gateway_config.get_info()
>>> print(f"Gateway Config: {info.name}, endpoint: {info.endpoint}")

:param options: Optional request configuration
:return: API response describing the gateway config
:rtype: GatewayConfigView
"""
return await self._client.gateway_configs.retrieve(
self._id,
**options,
)

async def update(self, **params: Unpack[SDKGatewayConfigUpdateParams]) -> GatewayConfigView:
"""Update the gateway config.

Example:
>>> updated = await gateway_config.update(
... name="updated-gateway-name",
... description="Updated description",
... )

:param params: See :typeddict:`~runloop_api_client.sdk._types.SDKGatewayConfigUpdateParams` for available parameters
:return: Updated gateway config view
:rtype: GatewayConfigView
"""
return await self._client.gateway_configs.update(self._id, **params)

async def delete(
self,
**options: Unpack[LongRequestOptions],
) -> GatewayConfigView:
"""Delete the gateway config. This action is irreversible.

Example:
>>> await gateway_config.delete()

:param options: Optional long-running request configuration
:return: API response acknowledging deletion
:rtype: GatewayConfigView
"""
return await self._client.gateway_configs.delete(
self._id,
**options,
)
Loading