diff --git a/.release-please-manifest.json b/.release-please-manifest.json index caf5ca3..59acac4 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.26.0" + ".": "0.27.0" } \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index 2857ba8..50043a4 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 91 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-fc2c80b398a8dd511010ae7cda5e21c353e388ee130aa288974b47af4208b5b8.yml -openapi_spec_hash: 5e06586dbbb9fce12b907f4e32497006 -config_hash: cc7fdd701d995d4b3456d77041c604cf +configured_endpoints: 97 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-7427d4bcaba5cad07910da7a222bdd2650b5280e6b889132ed38d230adafb8a5.yml +openapi_spec_hash: e8e3dc1ae54666d544d1fc848b25e7cf +config_hash: b470456b217bb9502f5212311d395a6f diff --git a/CHANGELOG.md b/CHANGELOG.md index 09a63d3..950e91e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,20 @@ # Changelog +## 0.27.0 (2026-01-21) + +Full Changelog: [v0.26.0...v0.27.0](https://github.com/kernel/kernel-python-sdk/compare/v0.26.0...v0.27.0) + +### Features + +* **agent-auth:** add 1Password integration for credential providers ([b26d1a3](https://github.com/kernel/kernel-python-sdk/commit/b26d1a35dce7e8b76d916d7bbd869edb0c44c195)) +* **dashboard:** add browser replays support for past browsers ([9d81781](https://github.com/kernel/kernel-python-sdk/commit/9d81781970ed6230844d479bc27893453b34a05e)) +* Update browser pool org limits ([7fa6d9b](https://github.com/kernel/kernel-python-sdk/commit/7fa6d9b152e051ed7cbadb9b5760a525fdf1f3b2)) + + +### Refactors + +* **agentauth:** enhance discover and submit modules with improve… ([570df3a](https://github.com/kernel/kernel-python-sdk/commit/570df3a0cc4b4e48737729442885959e9bf205ba)) + ## 0.26.0 (2026-01-17) Full Changelog: [v0.25.0...v0.26.0](https://github.com/kernel/kernel-python-sdk/compare/v0.25.0...v0.26.0) diff --git a/api.md b/api.md index 51f8cdb..e951a78 100644 --- a/api.md +++ b/api.md @@ -89,7 +89,7 @@ from kernel.types import ( Methods: - client.browsers.create(\*\*params) -> BrowserCreateResponse -- client.browsers.retrieve(id) -> BrowserRetrieveResponse +- client.browsers.retrieve(id, \*\*params) -> BrowserRetrieveResponse - client.browsers.update(id, \*\*params) -> BrowserUpdateResponse - client.browsers.list(\*\*params) -> SyncOffsetPagination[BrowserListResponse] - client.browsers.delete(\*\*params) -> None @@ -344,3 +344,26 @@ Methods: - client.credentials.list(\*\*params) -> SyncOffsetPagination[Credential] - client.credentials.delete(id_or_name) -> None - client.credentials.totp_code(id_or_name) -> CredentialTotpCodeResponse + +# CredentialProviders + +Types: + +```python +from kernel.types import ( + CreateCredentialProviderRequest, + CredentialProvider, + CredentialProviderTestResult, + UpdateCredentialProviderRequest, + CredentialProviderListResponse, +) +``` + +Methods: + +- client.credential_providers.create(\*\*params) -> CredentialProvider +- client.credential_providers.retrieve(id) -> CredentialProvider +- client.credential_providers.update(id, \*\*params) -> CredentialProvider +- client.credential_providers.list() -> CredentialProviderListResponse +- client.credential_providers.delete(id) -> None +- client.credential_providers.test(id) -> CredentialProviderTestResult diff --git a/pyproject.toml b/pyproject.toml index cad7dd2..7ac03dc 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "kernel" -version = "0.26.0" +version = "0.27.0" description = "The official Python library for the kernel API" dynamic = ["readme"] license = "Apache-2.0" diff --git a/src/kernel/_client.py b/src/kernel/_client.py index 166ecdb..daf5799 100644 --- a/src/kernel/_client.py +++ b/src/kernel/_client.py @@ -42,6 +42,7 @@ deployments, invocations, browser_pools, + credential_providers, ) from .resources.apps import AppsResource, AsyncAppsResource from .resources.proxies import ProxiesResource, AsyncProxiesResource @@ -53,6 +54,7 @@ from .resources.agents.agents import AgentsResource, AsyncAgentsResource from .resources.browser_pools import BrowserPoolsResource, AsyncBrowserPoolsResource from .resources.browsers.browsers import BrowsersResource, AsyncBrowsersResource + from .resources.credential_providers import CredentialProvidersResource, AsyncCredentialProvidersResource __all__ = [ "ENVIRONMENTS", @@ -211,6 +213,12 @@ def credentials(self) -> CredentialsResource: return CredentialsResource(self) + @cached_property + def credential_providers(self) -> CredentialProvidersResource: + from .resources.credential_providers import CredentialProvidersResource + + return CredentialProvidersResource(self) + @cached_property def with_raw_response(self) -> KernelWithRawResponse: return KernelWithRawResponse(self) @@ -465,6 +473,12 @@ def credentials(self) -> AsyncCredentialsResource: return AsyncCredentialsResource(self) + @cached_property + def credential_providers(self) -> AsyncCredentialProvidersResource: + from .resources.credential_providers import AsyncCredentialProvidersResource + + return AsyncCredentialProvidersResource(self) + @cached_property def with_raw_response(self) -> AsyncKernelWithRawResponse: return AsyncKernelWithRawResponse(self) @@ -646,6 +660,12 @@ def credentials(self) -> credentials.CredentialsResourceWithRawResponse: return CredentialsResourceWithRawResponse(self._client.credentials) + @cached_property + def credential_providers(self) -> credential_providers.CredentialProvidersResourceWithRawResponse: + from .resources.credential_providers import CredentialProvidersResourceWithRawResponse + + return CredentialProvidersResourceWithRawResponse(self._client.credential_providers) + class AsyncKernelWithRawResponse: _client: AsyncKernel @@ -713,6 +733,12 @@ def credentials(self) -> credentials.AsyncCredentialsResourceWithRawResponse: return AsyncCredentialsResourceWithRawResponse(self._client.credentials) + @cached_property + def credential_providers(self) -> credential_providers.AsyncCredentialProvidersResourceWithRawResponse: + from .resources.credential_providers import AsyncCredentialProvidersResourceWithRawResponse + + return AsyncCredentialProvidersResourceWithRawResponse(self._client.credential_providers) + class KernelWithStreamedResponse: _client: Kernel @@ -780,6 +806,12 @@ def credentials(self) -> credentials.CredentialsResourceWithStreamingResponse: return CredentialsResourceWithStreamingResponse(self._client.credentials) + @cached_property + def credential_providers(self) -> credential_providers.CredentialProvidersResourceWithStreamingResponse: + from .resources.credential_providers import CredentialProvidersResourceWithStreamingResponse + + return CredentialProvidersResourceWithStreamingResponse(self._client.credential_providers) + class AsyncKernelWithStreamedResponse: _client: AsyncKernel @@ -847,6 +879,12 @@ def credentials(self) -> credentials.AsyncCredentialsResourceWithStreamingRespon return AsyncCredentialsResourceWithStreamingResponse(self._client.credentials) + @cached_property + def credential_providers(self) -> credential_providers.AsyncCredentialProvidersResourceWithStreamingResponse: + from .resources.credential_providers import AsyncCredentialProvidersResourceWithStreamingResponse + + return AsyncCredentialProvidersResourceWithStreamingResponse(self._client.credential_providers) + Client = Kernel diff --git a/src/kernel/_version.py b/src/kernel/_version.py index 0c46e78..b962ca5 100644 --- a/src/kernel/_version.py +++ b/src/kernel/_version.py @@ -1,4 +1,4 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. __title__ = "kernel" -__version__ = "0.26.0" # x-release-please-version +__version__ = "0.27.0" # x-release-please-version diff --git a/src/kernel/resources/__init__.py b/src/kernel/resources/__init__.py index e6e8103..50db63b 100644 --- a/src/kernel/resources/__init__.py +++ b/src/kernel/resources/__init__.py @@ -80,6 +80,14 @@ BrowserPoolsResourceWithStreamingResponse, AsyncBrowserPoolsResourceWithStreamingResponse, ) +from .credential_providers import ( + CredentialProvidersResource, + AsyncCredentialProvidersResource, + CredentialProvidersResourceWithRawResponse, + AsyncCredentialProvidersResourceWithRawResponse, + CredentialProvidersResourceWithStreamingResponse, + AsyncCredentialProvidersResourceWithStreamingResponse, +) __all__ = [ "DeploymentsResource", @@ -142,4 +150,10 @@ "AsyncCredentialsResourceWithRawResponse", "CredentialsResourceWithStreamingResponse", "AsyncCredentialsResourceWithStreamingResponse", + "CredentialProvidersResource", + "AsyncCredentialProvidersResource", + "CredentialProvidersResourceWithRawResponse", + "AsyncCredentialProvidersResourceWithRawResponse", + "CredentialProvidersResourceWithStreamingResponse", + "AsyncCredentialProvidersResourceWithStreamingResponse", ] diff --git a/src/kernel/resources/browser_pools.py b/src/kernel/resources/browser_pools.py index 5a4bf61..884b0e1 100644 --- a/src/kernel/resources/browser_pools.py +++ b/src/kernel/resources/browser_pools.py @@ -79,7 +79,9 @@ def create( Create a new browser pool with the specified configuration and size. Args: - size: Number of browsers to create in the pool + size: Number of browsers to maintain in the pool. The maximum size is determined by + your organization's pooled sessions limit (the sum of all pool sizes cannot + exceed your limit). extensions: List of browser extensions to load into the session. Provide each by id or name. @@ -206,7 +208,9 @@ def update( Updates the configuration used to create browsers in the pool. Args: - size: Number of browsers to create in the pool + size: Number of browsers to maintain in the pool. The maximum size is determined by + your organization's pooled sessions limit (the sum of all pool sizes cannot + exceed your limit). discard_all_idle: Whether to discard all idle browsers and rebuild the pool immediately. Defaults to false. @@ -513,7 +517,9 @@ async def create( Create a new browser pool with the specified configuration and size. Args: - size: Number of browsers to create in the pool + size: Number of browsers to maintain in the pool. The maximum size is determined by + your organization's pooled sessions limit (the sum of all pool sizes cannot + exceed your limit). extensions: List of browser extensions to load into the session. Provide each by id or name. @@ -640,7 +646,9 @@ async def update( Updates the configuration used to create browsers in the pool. Args: - size: Number of browsers to create in the pool + size: Number of browsers to maintain in the pool. The maximum size is determined by + your organization's pooled sessions limit (the sum of all pool sizes cannot + exceed your limit). discard_all_idle: Whether to discard all idle browsers and rebuild the pool immediately. Defaults to false. diff --git a/src/kernel/resources/browsers/browsers.py b/src/kernel/resources/browsers/browsers.py index ab57854..d835f7a 100644 --- a/src/kernel/resources/browsers/browsers.py +++ b/src/kernel/resources/browsers/browsers.py @@ -4,6 +4,7 @@ import typing_extensions from typing import Mapping, Iterable, Optional, cast +from typing_extensions import Literal import httpx @@ -28,6 +29,7 @@ browser_create_params, browser_delete_params, browser_update_params, + browser_retrieve_params, browser_load_extensions_params, ) from .process import ( @@ -226,6 +228,7 @@ def retrieve( self, id: str, *, + include_deleted: bool | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -237,6 +240,8 @@ def retrieve( Get information about a browser session. Args: + include_deleted: When true, includes soft-deleted browser sessions in the lookup. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -250,7 +255,13 @@ def retrieve( return self._get( f"/browsers/{id}", options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + {"include_deleted": include_deleted}, browser_retrieve_params.BrowserRetrieveParams + ), ), cast_to=BrowserRetrieveResponse, ) @@ -300,6 +311,7 @@ def list( include_deleted: bool | Omit = omit, limit: int | Omit = omit, offset: int | Omit = omit, + status: Literal["active", "deleted", "all"] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -309,17 +321,20 @@ def list( ) -> SyncOffsetPagination[BrowserListResponse]: """List all browser sessions with pagination support. - Use include_deleted=true to - include soft-deleted sessions in the results. + Use status parameter to + filter by session state. Args: - include_deleted: When true, includes soft-deleted browser sessions in the results alongside - active sessions. + include_deleted: Deprecated: Use status=all instead. When true, includes soft-deleted browser + sessions in the results alongside active sessions. limit: Maximum number of results to return. Defaults to 20, maximum 100. offset: Number of results to skip. Defaults to 0. + status: Filter sessions by status. "active" returns only active sessions (default), + "deleted" returns only soft-deleted sessions, "all" returns both. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -341,6 +356,7 @@ def list( "include_deleted": include_deleted, "limit": limit, "offset": offset, + "status": status, }, browser_list_params.BrowserListParams, ), @@ -610,6 +626,7 @@ async def retrieve( self, id: str, *, + include_deleted: bool | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -621,6 +638,8 @@ async def retrieve( Get information about a browser session. Args: + include_deleted: When true, includes soft-deleted browser sessions in the lookup. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -634,7 +653,13 @@ async def retrieve( return await self._get( f"/browsers/{id}", options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=await async_maybe_transform( + {"include_deleted": include_deleted}, browser_retrieve_params.BrowserRetrieveParams + ), ), cast_to=BrowserRetrieveResponse, ) @@ -684,6 +709,7 @@ def list( include_deleted: bool | Omit = omit, limit: int | Omit = omit, offset: int | Omit = omit, + status: Literal["active", "deleted", "all"] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -693,17 +719,20 @@ def list( ) -> AsyncPaginator[BrowserListResponse, AsyncOffsetPagination[BrowserListResponse]]: """List all browser sessions with pagination support. - Use include_deleted=true to - include soft-deleted sessions in the results. + Use status parameter to + filter by session state. Args: - include_deleted: When true, includes soft-deleted browser sessions in the results alongside - active sessions. + include_deleted: Deprecated: Use status=all instead. When true, includes soft-deleted browser + sessions in the results alongside active sessions. limit: Maximum number of results to return. Defaults to 20, maximum 100. offset: Number of results to skip. Defaults to 0. + status: Filter sessions by status. "active" returns only active sessions (default), + "deleted" returns only soft-deleted sessions, "all" returns both. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -725,6 +754,7 @@ def list( "include_deleted": include_deleted, "limit": limit, "offset": offset, + "status": status, }, browser_list_params.BrowserListParams, ), diff --git a/src/kernel/resources/credential_providers.py b/src/kernel/resources/credential_providers.py new file mode 100644 index 0000000..b1b1248 --- /dev/null +++ b/src/kernel/resources/credential_providers.py @@ -0,0 +1,605 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Literal + +import httpx + +from ..types import credential_provider_create_params, credential_provider_update_params +from .._types import Body, Omit, Query, Headers, NoneType, NotGiven, omit, not_given +from .._utils import maybe_transform, async_maybe_transform +from .._compat import cached_property +from .._resource import SyncAPIResource, AsyncAPIResource +from .._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from .._base_client import make_request_options +from ..types.credential_provider import CredentialProvider +from ..types.credential_provider_test_result import CredentialProviderTestResult +from ..types.credential_provider_list_response import CredentialProviderListResponse + +__all__ = ["CredentialProvidersResource", "AsyncCredentialProvidersResource"] + + +class CredentialProvidersResource(SyncAPIResource): + @cached_property + def with_raw_response(self) -> CredentialProvidersResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/kernel/kernel-python-sdk#accessing-raw-response-data-eg-headers + """ + return CredentialProvidersResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> CredentialProvidersResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/kernel/kernel-python-sdk#with_streaming_response + """ + return CredentialProvidersResourceWithStreamingResponse(self) + + def create( + self, + *, + token: str, + provider_type: Literal["onepassword"], + cache_ttl_seconds: int | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> CredentialProvider: + """ + Configure an external credential provider (e.g., 1Password) for automatic + credential lookup. + + Args: + token: Service account token for the provider (e.g., 1Password service account token) + + provider_type: Type of credential provider + + cache_ttl_seconds: How long to cache credential lists (default 300 seconds) + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._post( + "/org/credential-providers", + body=maybe_transform( + { + "token": token, + "provider_type": provider_type, + "cache_ttl_seconds": cache_ttl_seconds, + }, + credential_provider_create_params.CredentialProviderCreateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=CredentialProvider, + ) + + def retrieve( + self, + id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> CredentialProvider: + """ + Retrieve a credential provider by its ID. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return self._get( + f"/org/credential-providers/{id}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=CredentialProvider, + ) + + def update( + self, + id: str, + *, + token: str | Omit = omit, + cache_ttl_seconds: int | Omit = omit, + enabled: bool | Omit = omit, + priority: int | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> CredentialProvider: + """ + Update a credential provider's configuration. + + Args: + token: New service account token (to rotate credentials) + + cache_ttl_seconds: How long to cache credential lists + + enabled: Whether the provider is enabled for credential lookups + + priority: Priority order for credential lookups (lower numbers are checked first) + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return self._patch( + f"/org/credential-providers/{id}", + body=maybe_transform( + { + "token": token, + "cache_ttl_seconds": cache_ttl_seconds, + "enabled": enabled, + "priority": priority, + }, + credential_provider_update_params.CredentialProviderUpdateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=CredentialProvider, + ) + + def list( + self, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> CredentialProviderListResponse: + """List external credential providers configured for the organization.""" + return self._get( + "/org/credential-providers", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=CredentialProviderListResponse, + ) + + def delete( + self, + id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> None: + """ + Delete a credential provider by its ID. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + return self._delete( + f"/org/credential-providers/{id}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) + + def test( + self, + id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> CredentialProviderTestResult: + """ + Validate the credential provider's token and list accessible vaults. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return self._post( + f"/org/credential-providers/{id}/test", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=CredentialProviderTestResult, + ) + + +class AsyncCredentialProvidersResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncCredentialProvidersResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/kernel/kernel-python-sdk#accessing-raw-response-data-eg-headers + """ + return AsyncCredentialProvidersResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncCredentialProvidersResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/kernel/kernel-python-sdk#with_streaming_response + """ + return AsyncCredentialProvidersResourceWithStreamingResponse(self) + + async def create( + self, + *, + token: str, + provider_type: Literal["onepassword"], + cache_ttl_seconds: int | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> CredentialProvider: + """ + Configure an external credential provider (e.g., 1Password) for automatic + credential lookup. + + Args: + token: Service account token for the provider (e.g., 1Password service account token) + + provider_type: Type of credential provider + + cache_ttl_seconds: How long to cache credential lists (default 300 seconds) + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return await self._post( + "/org/credential-providers", + body=await async_maybe_transform( + { + "token": token, + "provider_type": provider_type, + "cache_ttl_seconds": cache_ttl_seconds, + }, + credential_provider_create_params.CredentialProviderCreateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=CredentialProvider, + ) + + async def retrieve( + self, + id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> CredentialProvider: + """ + Retrieve a credential provider by its ID. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return await self._get( + f"/org/credential-providers/{id}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=CredentialProvider, + ) + + async def update( + self, + id: str, + *, + token: str | Omit = omit, + cache_ttl_seconds: int | Omit = omit, + enabled: bool | Omit = omit, + priority: int | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> CredentialProvider: + """ + Update a credential provider's configuration. + + Args: + token: New service account token (to rotate credentials) + + cache_ttl_seconds: How long to cache credential lists + + enabled: Whether the provider is enabled for credential lookups + + priority: Priority order for credential lookups (lower numbers are checked first) + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return await self._patch( + f"/org/credential-providers/{id}", + body=await async_maybe_transform( + { + "token": token, + "cache_ttl_seconds": cache_ttl_seconds, + "enabled": enabled, + "priority": priority, + }, + credential_provider_update_params.CredentialProviderUpdateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=CredentialProvider, + ) + + async def list( + self, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> CredentialProviderListResponse: + """List external credential providers configured for the organization.""" + return await self._get( + "/org/credential-providers", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=CredentialProviderListResponse, + ) + + async def delete( + self, + id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> None: + """ + Delete a credential provider by its ID. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + return await self._delete( + f"/org/credential-providers/{id}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) + + async def test( + self, + id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> CredentialProviderTestResult: + """ + Validate the credential provider's token and list accessible vaults. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return await self._post( + f"/org/credential-providers/{id}/test", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=CredentialProviderTestResult, + ) + + +class CredentialProvidersResourceWithRawResponse: + def __init__(self, credential_providers: CredentialProvidersResource) -> None: + self._credential_providers = credential_providers + + self.create = to_raw_response_wrapper( + credential_providers.create, + ) + self.retrieve = to_raw_response_wrapper( + credential_providers.retrieve, + ) + self.update = to_raw_response_wrapper( + credential_providers.update, + ) + self.list = to_raw_response_wrapper( + credential_providers.list, + ) + self.delete = to_raw_response_wrapper( + credential_providers.delete, + ) + self.test = to_raw_response_wrapper( + credential_providers.test, + ) + + +class AsyncCredentialProvidersResourceWithRawResponse: + def __init__(self, credential_providers: AsyncCredentialProvidersResource) -> None: + self._credential_providers = credential_providers + + self.create = async_to_raw_response_wrapper( + credential_providers.create, + ) + self.retrieve = async_to_raw_response_wrapper( + credential_providers.retrieve, + ) + self.update = async_to_raw_response_wrapper( + credential_providers.update, + ) + self.list = async_to_raw_response_wrapper( + credential_providers.list, + ) + self.delete = async_to_raw_response_wrapper( + credential_providers.delete, + ) + self.test = async_to_raw_response_wrapper( + credential_providers.test, + ) + + +class CredentialProvidersResourceWithStreamingResponse: + def __init__(self, credential_providers: CredentialProvidersResource) -> None: + self._credential_providers = credential_providers + + self.create = to_streamed_response_wrapper( + credential_providers.create, + ) + self.retrieve = to_streamed_response_wrapper( + credential_providers.retrieve, + ) + self.update = to_streamed_response_wrapper( + credential_providers.update, + ) + self.list = to_streamed_response_wrapper( + credential_providers.list, + ) + self.delete = to_streamed_response_wrapper( + credential_providers.delete, + ) + self.test = to_streamed_response_wrapper( + credential_providers.test, + ) + + +class AsyncCredentialProvidersResourceWithStreamingResponse: + def __init__(self, credential_providers: AsyncCredentialProvidersResource) -> None: + self._credential_providers = credential_providers + + self.create = async_to_streamed_response_wrapper( + credential_providers.create, + ) + self.retrieve = async_to_streamed_response_wrapper( + credential_providers.retrieve, + ) + self.update = async_to_streamed_response_wrapper( + credential_providers.update, + ) + self.list = async_to_streamed_response_wrapper( + credential_providers.list, + ) + self.delete = async_to_streamed_response_wrapper( + credential_providers.delete, + ) + self.test = async_to_streamed_response_wrapper( + credential_providers.test, + ) diff --git a/src/kernel/types/__init__.py b/src/kernel/types/__init__.py index d037578..ef16ae2 100644 --- a/src/kernel/types/__init__.py +++ b/src/kernel/types/__init__.py @@ -20,6 +20,7 @@ from .app_list_response import AppListResponse as AppListResponse from .browser_list_params import BrowserListParams as BrowserListParams from .browser_persistence import BrowserPersistence as BrowserPersistence +from .credential_provider import CredentialProvider as CredentialProvider from .proxy_create_params import ProxyCreateParams as ProxyCreateParams from .proxy_list_response import ProxyListResponse as ProxyListResponse from .proxy_check_response import ProxyCheckResponse as ProxyCheckResponse @@ -36,6 +37,7 @@ from .invocation_list_params import InvocationListParams as InvocationListParams from .invocation_state_event import InvocationStateEvent as InvocationStateEvent from .browser_create_response import BrowserCreateResponse as BrowserCreateResponse +from .browser_retrieve_params import BrowserRetrieveParams as BrowserRetrieveParams from .browser_update_response import BrowserUpdateResponse as BrowserUpdateResponse from .extension_list_response import ExtensionListResponse as ExtensionListResponse from .extension_upload_params import ExtensionUploadParams as ExtensionUploadParams @@ -68,6 +70,10 @@ from .browser_pool_acquire_response import BrowserPoolAcquireResponse as BrowserPoolAcquireResponse from .credential_totp_code_response import CredentialTotpCodeResponse as CredentialTotpCodeResponse from .browser_load_extensions_params import BrowserLoadExtensionsParams as BrowserLoadExtensionsParams +from .credential_provider_test_result import CredentialProviderTestResult as CredentialProviderTestResult +from .credential_provider_create_params import CredentialProviderCreateParams as CredentialProviderCreateParams +from .credential_provider_list_response import CredentialProviderListResponse as CredentialProviderListResponse +from .credential_provider_update_params import CredentialProviderUpdateParams as CredentialProviderUpdateParams from .extension_download_from_chrome_store_params import ( ExtensionDownloadFromChromeStoreParams as ExtensionDownloadFromChromeStoreParams, ) diff --git a/src/kernel/types/agents/agent_auth_invocation_response.py b/src/kernel/types/agents/agent_auth_invocation_response.py index 2731290..9823582 100644 --- a/src/kernel/types/agents/agent_auth_invocation_response.py +++ b/src/kernel/types/agents/agent_auth_invocation_response.py @@ -91,6 +91,9 @@ class AgentAuthInvocationResponse(BaseModel): pending_sso_buttons: Optional[List[PendingSSOButton]] = None """SSO buttons available on the page (present when step=awaiting_input)""" + sso_provider: Optional[str] = None + """SSO provider being used for authentication (e.g., google, github, microsoft)""" + submitted_fields: Optional[List[str]] = None """ Names of fields that have been submitted (present when step=submitting or later) diff --git a/src/kernel/types/browser_list_params.py b/src/kernel/types/browser_list_params.py index 20837be..02aa97a 100644 --- a/src/kernel/types/browser_list_params.py +++ b/src/kernel/types/browser_list_params.py @@ -2,14 +2,15 @@ from __future__ import annotations -from typing_extensions import TypedDict +from typing_extensions import Literal, TypedDict __all__ = ["BrowserListParams"] class BrowserListParams(TypedDict, total=False): include_deleted: bool - """ + """Deprecated: Use status=all instead. + When true, includes soft-deleted browser sessions in the results alongside active sessions. """ @@ -19,3 +20,10 @@ class BrowserListParams(TypedDict, total=False): offset: int """Number of results to skip. Defaults to 0.""" + + status: Literal["active", "deleted", "all"] + """Filter sessions by status. + + "active" returns only active sessions (default), "deleted" returns only + soft-deleted sessions, "all" returns both. + """ diff --git a/src/kernel/types/browser_pool.py b/src/kernel/types/browser_pool.py index 1694313..b9142f7 100644 --- a/src/kernel/types/browser_pool.py +++ b/src/kernel/types/browser_pool.py @@ -15,7 +15,11 @@ class BrowserPoolConfig(BaseModel): """Configuration used to create all browsers in this pool""" size: int - """Number of browsers to create in the pool""" + """Number of browsers to maintain in the pool. + + The maximum size is determined by your organization's pooled sessions limit (the + sum of all pool sizes cannot exceed your limit). + """ extensions: Optional[List[BrowserExtension]] = None """List of browser extensions to load into the session. diff --git a/src/kernel/types/browser_pool_create_params.py b/src/kernel/types/browser_pool_create_params.py index 6c8e815..afa9e6e 100644 --- a/src/kernel/types/browser_pool_create_params.py +++ b/src/kernel/types/browser_pool_create_params.py @@ -14,7 +14,11 @@ class BrowserPoolCreateParams(TypedDict, total=False): size: Required[int] - """Number of browsers to create in the pool""" + """Number of browsers to maintain in the pool. + + The maximum size is determined by your organization's pooled sessions limit (the + sum of all pool sizes cannot exceed your limit). + """ extensions: Iterable[BrowserExtension] """List of browser extensions to load into the session. diff --git a/src/kernel/types/browser_pool_update_params.py b/src/kernel/types/browser_pool_update_params.py index 2cd3be7..ac23916 100644 --- a/src/kernel/types/browser_pool_update_params.py +++ b/src/kernel/types/browser_pool_update_params.py @@ -14,7 +14,11 @@ class BrowserPoolUpdateParams(TypedDict, total=False): size: Required[int] - """Number of browsers to create in the pool""" + """Number of browsers to maintain in the pool. + + The maximum size is determined by your organization's pooled sessions limit (the + sum of all pool sizes cannot exceed your limit). + """ discard_all_idle: bool """Whether to discard all idle browsers and rebuild the pool immediately. diff --git a/src/kernel/types/browser_retrieve_params.py b/src/kernel/types/browser_retrieve_params.py new file mode 100644 index 0000000..ec5e8aa --- /dev/null +++ b/src/kernel/types/browser_retrieve_params.py @@ -0,0 +1,12 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import TypedDict + +__all__ = ["BrowserRetrieveParams"] + + +class BrowserRetrieveParams(TypedDict, total=False): + include_deleted: bool + """When true, includes soft-deleted browser sessions in the lookup.""" diff --git a/src/kernel/types/credential_provider.py b/src/kernel/types/credential_provider.py new file mode 100644 index 0000000..83a205a --- /dev/null +++ b/src/kernel/types/credential_provider.py @@ -0,0 +1,32 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from datetime import datetime +from typing_extensions import Literal + +from .._models import BaseModel + +__all__ = ["CredentialProvider"] + + +class CredentialProvider(BaseModel): + """ + An external credential provider (e.g., 1Password) for automatic credential lookup + """ + + id: str + """Unique identifier for the credential provider""" + + created_at: datetime + """When the credential provider was created""" + + enabled: bool + """Whether the provider is enabled for credential lookups""" + + priority: int + """Priority order for credential lookups (lower numbers are checked first)""" + + provider_type: Literal["onepassword"] + """Type of credential provider""" + + updated_at: datetime + """When the credential provider was last updated""" diff --git a/src/kernel/types/credential_provider_create_params.py b/src/kernel/types/credential_provider_create_params.py new file mode 100644 index 0000000..ed631b3 --- /dev/null +++ b/src/kernel/types/credential_provider_create_params.py @@ -0,0 +1,18 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Literal, Required, TypedDict + +__all__ = ["CredentialProviderCreateParams"] + + +class CredentialProviderCreateParams(TypedDict, total=False): + token: Required[str] + """Service account token for the provider (e.g., 1Password service account token)""" + + provider_type: Required[Literal["onepassword"]] + """Type of credential provider""" + + cache_ttl_seconds: int + """How long to cache credential lists (default 300 seconds)""" diff --git a/src/kernel/types/credential_provider_list_response.py b/src/kernel/types/credential_provider_list_response.py new file mode 100644 index 0000000..59814e0 --- /dev/null +++ b/src/kernel/types/credential_provider_list_response.py @@ -0,0 +1,10 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List +from typing_extensions import TypeAlias + +from .credential_provider import CredentialProvider + +__all__ = ["CredentialProviderListResponse"] + +CredentialProviderListResponse: TypeAlias = List[CredentialProvider] diff --git a/src/kernel/types/credential_provider_test_result.py b/src/kernel/types/credential_provider_test_result.py new file mode 100644 index 0000000..8cc4b01 --- /dev/null +++ b/src/kernel/types/credential_provider_test_result.py @@ -0,0 +1,28 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional + +from .._models import BaseModel + +__all__ = ["CredentialProviderTestResult", "Vault"] + + +class Vault(BaseModel): + id: str + """Vault ID""" + + name: str + """Vault name""" + + +class CredentialProviderTestResult(BaseModel): + """Result of testing a credential provider connection""" + + success: bool + """Whether the connection test was successful""" + + vaults: List[Vault] + """List of vaults accessible by the service account""" + + error: Optional[str] = None + """Error message if the test failed""" diff --git a/src/kernel/types/credential_provider_update_params.py b/src/kernel/types/credential_provider_update_params.py new file mode 100644 index 0000000..ecebeab --- /dev/null +++ b/src/kernel/types/credential_provider_update_params.py @@ -0,0 +1,21 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import TypedDict + +__all__ = ["CredentialProviderUpdateParams"] + + +class CredentialProviderUpdateParams(TypedDict, total=False): + token: str + """New service account token (to rotate credentials)""" + + cache_ttl_seconds: int + """How long to cache credential lists""" + + enabled: bool + """Whether the provider is enabled for credential lookups""" + + priority: int + """Priority order for credential lookups (lower numbers are checked first)""" diff --git a/tests/api_resources/test_browsers.py b/tests/api_resources/test_browsers.py index 5eec9de..139cf14 100644 --- a/tests/api_resources/test_browsers.py +++ b/tests/api_resources/test_browsers.py @@ -87,7 +87,16 @@ def test_streaming_response_create(self, client: Kernel) -> None: @parametrize def test_method_retrieve(self, client: Kernel) -> None: browser = client.browsers.retrieve( - "htzv5orfit78e1m2biiifpbv", + id="htzv5orfit78e1m2biiifpbv", + ) + assert_matches_type(BrowserRetrieveResponse, browser, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_retrieve_with_all_params(self, client: Kernel) -> None: + browser = client.browsers.retrieve( + id="htzv5orfit78e1m2biiifpbv", + include_deleted=True, ) assert_matches_type(BrowserRetrieveResponse, browser, path=["response"]) @@ -95,7 +104,7 @@ def test_method_retrieve(self, client: Kernel) -> None: @parametrize def test_raw_response_retrieve(self, client: Kernel) -> None: response = client.browsers.with_raw_response.retrieve( - "htzv5orfit78e1m2biiifpbv", + id="htzv5orfit78e1m2biiifpbv", ) assert response.is_closed is True @@ -107,7 +116,7 @@ def test_raw_response_retrieve(self, client: Kernel) -> None: @parametrize def test_streaming_response_retrieve(self, client: Kernel) -> None: with client.browsers.with_streaming_response.retrieve( - "htzv5orfit78e1m2biiifpbv", + id="htzv5orfit78e1m2biiifpbv", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -122,7 +131,7 @@ def test_streaming_response_retrieve(self, client: Kernel) -> None: def test_path_params_retrieve(self, client: Kernel) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): client.browsers.with_raw_response.retrieve( - "", + id="", ) @pytest.mark.skip(reason="Prism tests are disabled") @@ -189,6 +198,7 @@ def test_method_list_with_all_params(self, client: Kernel) -> None: include_deleted=True, limit=1, offset=0, + status="active", ) assert_matches_type(SyncOffsetPagination[BrowserListResponse], browser, path=["response"]) @@ -428,7 +438,16 @@ async def test_streaming_response_create(self, async_client: AsyncKernel) -> Non @parametrize async def test_method_retrieve(self, async_client: AsyncKernel) -> None: browser = await async_client.browsers.retrieve( - "htzv5orfit78e1m2biiifpbv", + id="htzv5orfit78e1m2biiifpbv", + ) + assert_matches_type(BrowserRetrieveResponse, browser, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_retrieve_with_all_params(self, async_client: AsyncKernel) -> None: + browser = await async_client.browsers.retrieve( + id="htzv5orfit78e1m2biiifpbv", + include_deleted=True, ) assert_matches_type(BrowserRetrieveResponse, browser, path=["response"]) @@ -436,7 +455,7 @@ async def test_method_retrieve(self, async_client: AsyncKernel) -> None: @parametrize async def test_raw_response_retrieve(self, async_client: AsyncKernel) -> None: response = await async_client.browsers.with_raw_response.retrieve( - "htzv5orfit78e1m2biiifpbv", + id="htzv5orfit78e1m2biiifpbv", ) assert response.is_closed is True @@ -448,7 +467,7 @@ async def test_raw_response_retrieve(self, async_client: AsyncKernel) -> None: @parametrize async def test_streaming_response_retrieve(self, async_client: AsyncKernel) -> None: async with async_client.browsers.with_streaming_response.retrieve( - "htzv5orfit78e1m2biiifpbv", + id="htzv5orfit78e1m2biiifpbv", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -463,7 +482,7 @@ async def test_streaming_response_retrieve(self, async_client: AsyncKernel) -> N async def test_path_params_retrieve(self, async_client: AsyncKernel) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): await async_client.browsers.with_raw_response.retrieve( - "", + id="", ) @pytest.mark.skip(reason="Prism tests are disabled") @@ -530,6 +549,7 @@ async def test_method_list_with_all_params(self, async_client: AsyncKernel) -> N include_deleted=True, limit=1, offset=0, + status="active", ) assert_matches_type(AsyncOffsetPagination[BrowserListResponse], browser, path=["response"]) diff --git a/tests/api_resources/test_credential_providers.py b/tests/api_resources/test_credential_providers.py new file mode 100644 index 0000000..136446c --- /dev/null +++ b/tests/api_resources/test_credential_providers.py @@ -0,0 +1,538 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +from typing import Any, cast + +import pytest + +from kernel import Kernel, AsyncKernel +from tests.utils import assert_matches_type +from kernel.types import ( + CredentialProvider, + CredentialProviderTestResult, + CredentialProviderListResponse, +) + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestCredentialProviders: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_create(self, client: Kernel) -> None: + credential_provider = client.credential_providers.create( + token="ops_eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...", + provider_type="onepassword", + ) + assert_matches_type(CredentialProvider, credential_provider, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_create_with_all_params(self, client: Kernel) -> None: + credential_provider = client.credential_providers.create( + token="ops_eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...", + provider_type="onepassword", + cache_ttl_seconds=300, + ) + assert_matches_type(CredentialProvider, credential_provider, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_create(self, client: Kernel) -> None: + response = client.credential_providers.with_raw_response.create( + token="ops_eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...", + provider_type="onepassword", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + credential_provider = response.parse() + assert_matches_type(CredentialProvider, credential_provider, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_create(self, client: Kernel) -> None: + with client.credential_providers.with_streaming_response.create( + token="ops_eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...", + provider_type="onepassword", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + credential_provider = response.parse() + assert_matches_type(CredentialProvider, credential_provider, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_retrieve(self, client: Kernel) -> None: + credential_provider = client.credential_providers.retrieve( + "id", + ) + assert_matches_type(CredentialProvider, credential_provider, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_retrieve(self, client: Kernel) -> None: + response = client.credential_providers.with_raw_response.retrieve( + "id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + credential_provider = response.parse() + assert_matches_type(CredentialProvider, credential_provider, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_retrieve(self, client: Kernel) -> None: + with client.credential_providers.with_streaming_response.retrieve( + "id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + credential_provider = response.parse() + assert_matches_type(CredentialProvider, credential_provider, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_path_params_retrieve(self, client: Kernel) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.credential_providers.with_raw_response.retrieve( + "", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_update(self, client: Kernel) -> None: + credential_provider = client.credential_providers.update( + id="id", + ) + assert_matches_type(CredentialProvider, credential_provider, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_update_with_all_params(self, client: Kernel) -> None: + credential_provider = client.credential_providers.update( + id="id", + token="ops_eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...", + cache_ttl_seconds=300, + enabled=True, + priority=0, + ) + assert_matches_type(CredentialProvider, credential_provider, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_update(self, client: Kernel) -> None: + response = client.credential_providers.with_raw_response.update( + id="id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + credential_provider = response.parse() + assert_matches_type(CredentialProvider, credential_provider, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_update(self, client: Kernel) -> None: + with client.credential_providers.with_streaming_response.update( + id="id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + credential_provider = response.parse() + assert_matches_type(CredentialProvider, credential_provider, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_path_params_update(self, client: Kernel) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.credential_providers.with_raw_response.update( + id="", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_list(self, client: Kernel) -> None: + credential_provider = client.credential_providers.list() + assert_matches_type(CredentialProviderListResponse, credential_provider, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_list(self, client: Kernel) -> None: + response = client.credential_providers.with_raw_response.list() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + credential_provider = response.parse() + assert_matches_type(CredentialProviderListResponse, credential_provider, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_list(self, client: Kernel) -> None: + with client.credential_providers.with_streaming_response.list() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + credential_provider = response.parse() + assert_matches_type(CredentialProviderListResponse, credential_provider, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_delete(self, client: Kernel) -> None: + credential_provider = client.credential_providers.delete( + "id", + ) + assert credential_provider is None + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_delete(self, client: Kernel) -> None: + response = client.credential_providers.with_raw_response.delete( + "id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + credential_provider = response.parse() + assert credential_provider is None + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_delete(self, client: Kernel) -> None: + with client.credential_providers.with_streaming_response.delete( + "id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + credential_provider = response.parse() + assert credential_provider is None + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_path_params_delete(self, client: Kernel) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.credential_providers.with_raw_response.delete( + "", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_test(self, client: Kernel) -> None: + credential_provider = client.credential_providers.test( + "id", + ) + assert_matches_type(CredentialProviderTestResult, credential_provider, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_test(self, client: Kernel) -> None: + response = client.credential_providers.with_raw_response.test( + "id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + credential_provider = response.parse() + assert_matches_type(CredentialProviderTestResult, credential_provider, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_test(self, client: Kernel) -> None: + with client.credential_providers.with_streaming_response.test( + "id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + credential_provider = response.parse() + assert_matches_type(CredentialProviderTestResult, credential_provider, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_path_params_test(self, client: Kernel) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.credential_providers.with_raw_response.test( + "", + ) + + +class TestAsyncCredentialProviders: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_create(self, async_client: AsyncKernel) -> None: + credential_provider = await async_client.credential_providers.create( + token="ops_eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...", + provider_type="onepassword", + ) + assert_matches_type(CredentialProvider, credential_provider, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_create_with_all_params(self, async_client: AsyncKernel) -> None: + credential_provider = await async_client.credential_providers.create( + token="ops_eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...", + provider_type="onepassword", + cache_ttl_seconds=300, + ) + assert_matches_type(CredentialProvider, credential_provider, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_create(self, async_client: AsyncKernel) -> None: + response = await async_client.credential_providers.with_raw_response.create( + token="ops_eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...", + provider_type="onepassword", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + credential_provider = await response.parse() + assert_matches_type(CredentialProvider, credential_provider, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_create(self, async_client: AsyncKernel) -> None: + async with async_client.credential_providers.with_streaming_response.create( + token="ops_eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...", + provider_type="onepassword", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + credential_provider = await response.parse() + assert_matches_type(CredentialProvider, credential_provider, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_retrieve(self, async_client: AsyncKernel) -> None: + credential_provider = await async_client.credential_providers.retrieve( + "id", + ) + assert_matches_type(CredentialProvider, credential_provider, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_retrieve(self, async_client: AsyncKernel) -> None: + response = await async_client.credential_providers.with_raw_response.retrieve( + "id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + credential_provider = await response.parse() + assert_matches_type(CredentialProvider, credential_provider, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_retrieve(self, async_client: AsyncKernel) -> None: + async with async_client.credential_providers.with_streaming_response.retrieve( + "id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + credential_provider = await response.parse() + assert_matches_type(CredentialProvider, credential_provider, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_path_params_retrieve(self, async_client: AsyncKernel) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.credential_providers.with_raw_response.retrieve( + "", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_update(self, async_client: AsyncKernel) -> None: + credential_provider = await async_client.credential_providers.update( + id="id", + ) + assert_matches_type(CredentialProvider, credential_provider, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_update_with_all_params(self, async_client: AsyncKernel) -> None: + credential_provider = await async_client.credential_providers.update( + id="id", + token="ops_eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...", + cache_ttl_seconds=300, + enabled=True, + priority=0, + ) + assert_matches_type(CredentialProvider, credential_provider, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_update(self, async_client: AsyncKernel) -> None: + response = await async_client.credential_providers.with_raw_response.update( + id="id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + credential_provider = await response.parse() + assert_matches_type(CredentialProvider, credential_provider, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_update(self, async_client: AsyncKernel) -> None: + async with async_client.credential_providers.with_streaming_response.update( + id="id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + credential_provider = await response.parse() + assert_matches_type(CredentialProvider, credential_provider, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_path_params_update(self, async_client: AsyncKernel) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.credential_providers.with_raw_response.update( + id="", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_list(self, async_client: AsyncKernel) -> None: + credential_provider = await async_client.credential_providers.list() + assert_matches_type(CredentialProviderListResponse, credential_provider, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_list(self, async_client: AsyncKernel) -> None: + response = await async_client.credential_providers.with_raw_response.list() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + credential_provider = await response.parse() + assert_matches_type(CredentialProviderListResponse, credential_provider, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_list(self, async_client: AsyncKernel) -> None: + async with async_client.credential_providers.with_streaming_response.list() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + credential_provider = await response.parse() + assert_matches_type(CredentialProviderListResponse, credential_provider, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_delete(self, async_client: AsyncKernel) -> None: + credential_provider = await async_client.credential_providers.delete( + "id", + ) + assert credential_provider is None + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_delete(self, async_client: AsyncKernel) -> None: + response = await async_client.credential_providers.with_raw_response.delete( + "id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + credential_provider = await response.parse() + assert credential_provider is None + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_delete(self, async_client: AsyncKernel) -> None: + async with async_client.credential_providers.with_streaming_response.delete( + "id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + credential_provider = await response.parse() + assert credential_provider is None + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_path_params_delete(self, async_client: AsyncKernel) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.credential_providers.with_raw_response.delete( + "", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_test(self, async_client: AsyncKernel) -> None: + credential_provider = await async_client.credential_providers.test( + "id", + ) + assert_matches_type(CredentialProviderTestResult, credential_provider, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_test(self, async_client: AsyncKernel) -> None: + response = await async_client.credential_providers.with_raw_response.test( + "id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + credential_provider = await response.parse() + assert_matches_type(CredentialProviderTestResult, credential_provider, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_test(self, async_client: AsyncKernel) -> None: + async with async_client.credential_providers.with_streaming_response.test( + "id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + credential_provider = await response.parse() + assert_matches_type(CredentialProviderTestResult, credential_provider, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_path_params_test(self, async_client: AsyncKernel) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.credential_providers.with_raw_response.test( + "", + )