diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index a8124647..a579a434 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "0.98.0"
+ ".": "0.99.0"
}
\ No newline at end of file
diff --git a/.stats.yml b/.stats.yml
index a867372d..5fe5772a 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1 +1 @@
-configured_endpoints: 147
+configured_endpoints: 158
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 992c5f68..2c0c8bf7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,13 @@
# Changelog
+## [0.99.0](https://github.com/kernel/kernel-python-sdk/compare/v0.98.0...v0.99.0) (2026-09-04)
+
+
+### Features
+
+* Expose OTLP destination delivery health ([9ab1d58](https://github.com/kernel/kernel-python-sdk/commit/9ab1d583d7bb4dabba5a640883dda9f2ac248f18))
+* Repair Vault SDK custom-code seals ([645ce00](https://github.com/kernel/kernel-python-sdk/commit/645ce00d68172a323d11b7e4dd4f3997cc287fe0))
+
## [0.98.0](https://github.com/kernel/kernel-python-sdk/compare/v0.97.0...v0.98.0) (2026-09-02)
diff --git a/api.md b/api.md
index 4a09a5d9..797c5d9c 100644
--- a/api.md
+++ b/api.md
@@ -126,6 +126,7 @@ from kernel.types import (
BrowserUsage,
Profile,
Tags,
+ VaultReference,
BrowserCreateResponse,
BrowserRetrieveResponse,
BrowserUpdateResponse,
@@ -486,6 +487,52 @@ Methods:
- client.browser_pools.flush(id_or_name) -> None
- client.browser_pools.release(id_or_name, \*\*params) -> None
+# Vaults
+
+Types:
+
+```python
+from kernel.types import Vault
+```
+
+Methods:
+
+- client.vaults.retrieve(id_or_name) -> Vault
+- client.vaults.list(\*\*params) -> SyncOffsetPagination[Vault]
+- client.vaults.delete(id_or_name) -> None
+- client.vaults.upsert(\*\*params) -> Vault
+
+## Items
+
+Types:
+
+```python
+from kernel.types.vaults import (
+ AgentcardCheckoutAuthorization,
+ CardVaultItemSpec,
+ CardVaultItemState,
+ VaultCardAliases,
+ VaultItem,
+ VaultItemAction,
+ VaultItemEvent,
+ VaultPaymentMethod,
+ WalletVaultItemSpec,
+ WalletVaultItemState,
+ ItemListResponse,
+ ItemEventsResponse,
+)
+```
+
+Methods:
+
+- client.vaults.items.retrieve(key, \*, id_or_name, \*\*params) -> VaultItem
+- client.vaults.items.update(key, \*, id_or_name, \*\*params) -> VaultItem
+- client.vaults.items.list(id_or_name) -> ItemListResponse
+- client.vaults.items.delete(key, \*, id_or_name) -> None
+- client.vaults.items.events(key, \*, id_or_name, \*\*params) -> ItemEventsResponse
+- client.vaults.items.perform_operation(key, \*, id_or_name, \*\*params) -> VaultItem
+- client.vaults.items.upsert(key, \*, id_or_name, \*\*params) -> VaultItem
+
# Credentials
Types:
diff --git a/pyproject.toml b/pyproject.toml
index fbe3ab05..dc940a7b 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "kernel"
-version = "0.98.0"
+version = "0.99.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 2c06cb04..acdb7357 100644
--- a/src/kernel/_client.py
+++ b/src/kernel/_client.py
@@ -50,6 +50,7 @@
from .resources import (
apps,
auth,
+ vaults,
proxies,
api_keys,
browsers,
@@ -76,6 +77,7 @@
from .resources.deployments import DeploymentsResource, AsyncDeploymentsResource
from .resources.invocations import InvocationsResource, AsyncInvocationsResource
from .resources.browser_pools import BrowserPoolsResource, AsyncBrowserPoolsResource
+ from .resources.vaults.vaults import VaultsResource, AsyncVaultsResource
from .resources.browsers.browsers import BrowsersResource, AsyncBrowsersResource
from .resources.projects.projects import ProjectsResource, AsyncProjectsResource
from .resources.telemetry.telemetry import TelemetryResource, AsyncTelemetryResource
@@ -279,6 +281,12 @@ def browser_pools(self) -> BrowserPoolsResource:
return BrowserPoolsResource(self)
+ @cached_property
+ def vaults(self) -> VaultsResource:
+ from .resources.vaults import VaultsResource
+
+ return VaultsResource(self)
+
@cached_property
def credentials(self) -> CredentialsResource:
"""Create and manage credentials for authentication."""
@@ -662,6 +670,12 @@ def browser_pools(self) -> AsyncBrowserPoolsResource:
return AsyncBrowserPoolsResource(self)
+ @cached_property
+ def vaults(self) -> AsyncVaultsResource:
+ from .resources.vaults import AsyncVaultsResource
+
+ return AsyncVaultsResource(self)
+
@cached_property
def credentials(self) -> AsyncCredentialsResource:
"""Create and manage credentials for authentication."""
@@ -949,6 +963,12 @@ def browser_pools(self) -> browser_pools.BrowserPoolsResourceWithRawResponse:
return BrowserPoolsResourceWithRawResponse(self._client.browser_pools)
+ @cached_property
+ def vaults(self) -> vaults.VaultsResourceWithRawResponse:
+ from .resources.vaults import VaultsResourceWithRawResponse
+
+ return VaultsResourceWithRawResponse(self._client.vaults)
+
@cached_property
def credentials(self) -> credentials.CredentialsResourceWithRawResponse:
"""Create and manage credentials for authentication."""
@@ -1076,6 +1096,12 @@ def browser_pools(self) -> browser_pools.AsyncBrowserPoolsResourceWithRawRespons
return AsyncBrowserPoolsResourceWithRawResponse(self._client.browser_pools)
+ @cached_property
+ def vaults(self) -> vaults.AsyncVaultsResourceWithRawResponse:
+ from .resources.vaults import AsyncVaultsResourceWithRawResponse
+
+ return AsyncVaultsResourceWithRawResponse(self._client.vaults)
+
@cached_property
def credentials(self) -> credentials.AsyncCredentialsResourceWithRawResponse:
"""Create and manage credentials for authentication."""
@@ -1203,6 +1229,12 @@ def browser_pools(self) -> browser_pools.BrowserPoolsResourceWithStreamingRespon
return BrowserPoolsResourceWithStreamingResponse(self._client.browser_pools)
+ @cached_property
+ def vaults(self) -> vaults.VaultsResourceWithStreamingResponse:
+ from .resources.vaults import VaultsResourceWithStreamingResponse
+
+ return VaultsResourceWithStreamingResponse(self._client.vaults)
+
@cached_property
def credentials(self) -> credentials.CredentialsResourceWithStreamingResponse:
"""Create and manage credentials for authentication."""
@@ -1330,6 +1362,12 @@ def browser_pools(self) -> browser_pools.AsyncBrowserPoolsResourceWithStreamingR
return AsyncBrowserPoolsResourceWithStreamingResponse(self._client.browser_pools)
+ @cached_property
+ def vaults(self) -> vaults.AsyncVaultsResourceWithStreamingResponse:
+ from .resources.vaults import AsyncVaultsResourceWithStreamingResponse
+
+ return AsyncVaultsResourceWithStreamingResponse(self._client.vaults)
+
@cached_property
def credentials(self) -> credentials.AsyncCredentialsResourceWithStreamingResponse:
"""Create and manage credentials for authentication."""
diff --git a/src/kernel/_version.py b/src/kernel/_version.py
index 4adaa91f..18073be8 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.98.0" # x-release-please-version
+__version__ = "0.99.0" # x-release-please-version
diff --git a/src/kernel/resources/__init__.py b/src/kernel/resources/__init__.py
index c6496534..5bc0849c 100644
--- a/src/kernel/resources/__init__.py
+++ b/src/kernel/resources/__init__.py
@@ -16,6 +16,14 @@
AuthResourceWithStreamingResponse,
AsyncAuthResourceWithStreamingResponse,
)
+from .vaults import (
+ VaultsResource,
+ AsyncVaultsResource,
+ VaultsResourceWithRawResponse,
+ AsyncVaultsResourceWithRawResponse,
+ VaultsResourceWithStreamingResponse,
+ AsyncVaultsResourceWithStreamingResponse,
+)
from .proxies import (
ProxiesResource,
AsyncProxiesResource,
@@ -204,6 +212,12 @@
"AsyncBrowserPoolsResourceWithRawResponse",
"BrowserPoolsResourceWithStreamingResponse",
"AsyncBrowserPoolsResourceWithStreamingResponse",
+ "VaultsResource",
+ "AsyncVaultsResource",
+ "VaultsResourceWithRawResponse",
+ "AsyncVaultsResourceWithRawResponse",
+ "VaultsResourceWithStreamingResponse",
+ "AsyncVaultsResourceWithStreamingResponse",
"CredentialsResource",
"AsyncCredentialsResource",
"CredentialsResourceWithRawResponse",
diff --git a/src/kernel/resources/browsers/browsers.py b/src/kernel/resources/browsers/browsers.py
index d703df24..219dd462 100644
--- a/src/kernel/resources/browsers/browsers.py
+++ b/src/kernel/resources/browsers/browsers.py
@@ -97,6 +97,7 @@
from ...types.tags_param import TagsParam
from ...types.browser_curl_response import BrowserCurlResponse
from ...types.browser_list_response import BrowserListResponse
+from ...types.vault_reference_param import VaultReferenceParam
from ...lib.browser_routing.raw_http import (
stream_via_browser_route,
request_via_browser_route,
@@ -201,6 +202,7 @@ def create(
tags: TagsParam | Omit = omit,
telemetry: Optional[browser_create_params.Telemetry] | Omit = omit,
timeout_seconds: int | Omit = omit,
+ vaults: Iterable[VaultReferenceParam] | Omit = omit,
viewport: BrowserViewport | 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.
@@ -284,6 +286,9 @@ def create(
check for inactivity every 5 seconds, so the actual timeout behavior you will
see is +/- 5 seconds around the specified value.
+ vaults: Project-scoped vaults to link to the browser session. Links are immutable after
+ creation.
+
viewport: Initial browser window size in pixels with optional refresh rate. If omitted,
image defaults apply (1920x1080@25). For GPU images, the default is
1920x1080@60. Arbitrary viewport dimensions and refresh rates are accepted.
@@ -327,6 +332,7 @@ def create(
"tags": tags,
"telemetry": telemetry,
"timeout_seconds": timeout_seconds,
+ "vaults": vaults,
"viewport": viewport,
},
browser_create_params.BrowserCreateParams,
@@ -826,6 +832,7 @@ async def create(
tags: TagsParam | Omit = omit,
telemetry: Optional[browser_create_params.Telemetry] | Omit = omit,
timeout_seconds: int | Omit = omit,
+ vaults: Iterable[VaultReferenceParam] | Omit = omit,
viewport: BrowserViewport | 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.
@@ -909,6 +916,9 @@ async def create(
check for inactivity every 5 seconds, so the actual timeout behavior you will
see is +/- 5 seconds around the specified value.
+ vaults: Project-scoped vaults to link to the browser session. Links are immutable after
+ creation.
+
viewport: Initial browser window size in pixels with optional refresh rate. If omitted,
image defaults apply (1920x1080@25). For GPU images, the default is
1920x1080@60. Arbitrary viewport dimensions and refresh rates are accepted.
@@ -952,6 +962,7 @@ async def create(
"tags": tags,
"telemetry": telemetry,
"timeout_seconds": timeout_seconds,
+ "vaults": vaults,
"viewport": viewport,
},
browser_create_params.BrowserCreateParams,
diff --git a/src/kernel/resources/config_registry/config_registry.py b/src/kernel/resources/config_registry/config_registry.py
index e5aa40d6..0b9d1824 100644
--- a/src/kernel/resources/config_registry/config_registry.py
+++ b/src/kernel/resources/config_registry/config_registry.py
@@ -78,12 +78,12 @@ def list(
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> SyncOffsetPagination[RecommendationSummary]:
"""
- Lists unique domains previously analyzed by the selected project with their
- current domain-level recommendations.
+ Lists unique exact targets previously analyzed by the selected project with the
+ recommendation produced by each target's latest analysis.
Args:
- search: Case-insensitive domain search. Full URLs are reduced to their registrable
- domain.
+ search: Case-insensitive substring search over normalized targets, including domain,
+ subdomain, and path.
extra_headers: Send extra headers
@@ -252,12 +252,12 @@ def list(
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> AsyncPaginator[RecommendationSummary, AsyncOffsetPagination[RecommendationSummary]]:
"""
- Lists unique domains previously analyzed by the selected project with their
- current domain-level recommendations.
+ Lists unique exact targets previously analyzed by the selected project with the
+ recommendation produced by each target's latest analysis.
Args:
- search: Case-insensitive domain search. Full URLs are reduced to their registrable
- domain.
+ search: Case-insensitive substring search over normalized targets, including domain,
+ subdomain, and path.
extra_headers: Send extra headers
diff --git a/src/kernel/resources/vaults/__init__.py b/src/kernel/resources/vaults/__init__.py
new file mode 100644
index 00000000..a019b7ee
--- /dev/null
+++ b/src/kernel/resources/vaults/__init__.py
@@ -0,0 +1,33 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from .items import (
+ ItemsResource,
+ AsyncItemsResource,
+ ItemsResourceWithRawResponse,
+ AsyncItemsResourceWithRawResponse,
+ ItemsResourceWithStreamingResponse,
+ AsyncItemsResourceWithStreamingResponse,
+)
+from .vaults import (
+ VaultsResource,
+ AsyncVaultsResource,
+ VaultsResourceWithRawResponse,
+ AsyncVaultsResourceWithRawResponse,
+ VaultsResourceWithStreamingResponse,
+ AsyncVaultsResourceWithStreamingResponse,
+)
+
+__all__ = [
+ "ItemsResource",
+ "AsyncItemsResource",
+ "ItemsResourceWithRawResponse",
+ "AsyncItemsResourceWithRawResponse",
+ "ItemsResourceWithStreamingResponse",
+ "AsyncItemsResourceWithStreamingResponse",
+ "VaultsResource",
+ "AsyncVaultsResource",
+ "VaultsResourceWithRawResponse",
+ "AsyncVaultsResourceWithRawResponse",
+ "VaultsResourceWithStreamingResponse",
+ "AsyncVaultsResourceWithStreamingResponse",
+]
diff --git a/src/kernel/resources/vaults/items.py b/src/kernel/resources/vaults/items.py
new file mode 100644
index 00000000..17bef3c6
--- /dev/null
+++ b/src/kernel/resources/vaults/items.py
@@ -0,0 +1,928 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Any, List, cast
+from typing_extensions import Literal, overload
+
+import httpx
+
+from ..._types import Body, Omit, Query, Headers, NoneType, NotGiven, omit, not_given
+from ..._utils import path_template, required_args, 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.vaults import (
+ item_events_params,
+ item_update_params,
+ item_upsert_params,
+ item_retrieve_params,
+ item_perform_operation_params,
+)
+from ...types.vaults.vault_item import VaultItem
+from ...types.vaults.item_list_response import ItemListResponse
+from ...types.vaults.item_events_response import ItemEventsResponse
+from ...types.vaults.card_vault_item_spec_param import CardVaultItemSpecParam
+from ...types.vaults.wallet_vault_item_spec_param import WalletVaultItemSpecParam
+
+__all__ = ["ItemsResource", "AsyncItemsResource"]
+
+
+class ItemsResource(SyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> ItemsResourceWithRawResponse:
+ """
+ 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 ItemsResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> ItemsResourceWithStreamingResponse:
+ """
+ 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 ItemsResourceWithStreamingResponse(self)
+
+ def retrieve(
+ self,
+ key: str,
+ *,
+ id_or_name: str,
+ expand: List[Literal["payment_methods"]] | Omit = omit,
+ wait: 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,
+ ) -> VaultItem:
+ """
+ The response advertises operations that are valid in the item's current state
+ and live data that can be requested through `expand`. Read each operation's
+ description before using it. Expanded data is fetched from the provider and is
+ not persisted in the vault item. Requesting an unavailable expansion returns 409
+ instead of a partial item.
+
+ Args:
+ expand: Live fields advertised by `available_expansions` to include in `expanded`.
+
+ wait: Hold for up to this many seconds while the item is pending authorization or
+ approval.
+
+ 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_or_name:
+ raise ValueError(f"Expected a non-empty value for `id_or_name` but received {id_or_name!r}")
+ if not key:
+ raise ValueError(f"Expected a non-empty value for `key` but received {key!r}")
+ return cast(
+ VaultItem,
+ self._get(
+ path_template("/vaults/{id_or_name}/items/{key}", id_or_name=id_or_name, key=key),
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=maybe_transform(
+ {
+ "expand": expand,
+ "wait": wait,
+ },
+ item_retrieve_params.ItemRetrieveParams,
+ ),
+ ),
+ cast_to=cast(Any, VaultItem), # Union types cannot be passed in as arguments in the type system
+ ),
+ )
+
+ def update(
+ self,
+ key: str,
+ *,
+ id_or_name: str,
+ spec: CardVaultItemSpecParam,
+ # 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,
+ ) -> VaultItem:
+ """
+ Update a card specification before or between authorizations
+
+ Args:
+ spec: AgentCard reusable card. Each checkout creates an approval-gated authorization
+ for spec.merchant / spec.amount. The card stays ready after each authorization.
+
+ 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_or_name:
+ raise ValueError(f"Expected a non-empty value for `id_or_name` but received {id_or_name!r}")
+ if not key:
+ raise ValueError(f"Expected a non-empty value for `key` but received {key!r}")
+ return cast(
+ VaultItem,
+ self._patch(
+ path_template("/vaults/{id_or_name}/items/{key}", id_or_name=id_or_name, key=key),
+ body=maybe_transform({"spec": spec}, item_update_params.ItemUpdateParams),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=cast(Any, VaultItem), # Union types cannot be passed in as arguments in the type system
+ ),
+ )
+
+ def list(
+ self,
+ id_or_name: 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,
+ ) -> ItemListResponse:
+ """
+ List vault items without secret values
+
+ 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_or_name:
+ raise ValueError(f"Expected a non-empty value for `id_or_name` but received {id_or_name!r}")
+ return self._get(
+ path_template("/vaults/{id_or_name}/items", id_or_name=id_or_name),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ItemListResponse,
+ )
+
+ def delete(
+ self,
+ key: str,
+ *,
+ id_or_name: 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 vault item and invalidate its secret value
+
+ 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_or_name:
+ raise ValueError(f"Expected a non-empty value for `id_or_name` but received {id_or_name!r}")
+ if not key:
+ raise ValueError(f"Expected a non-empty value for `key` but received {key!r}")
+ extra_headers = {"Accept": "*/*", **(extra_headers or {})}
+ return self._delete(
+ path_template("/vaults/{id_or_name}/items/{key}", id_or_name=id_or_name, key=key),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=NoneType,
+ )
+
+ def events(
+ self,
+ key: str,
+ *,
+ id_or_name: str,
+ after: str | Omit = omit,
+ wait: 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,
+ ) -> ItemEventsResponse:
+ """
+ List immutable audit events for a vault item
+
+ Args:
+ after: Return events after this event ID.
+
+ wait: Long-poll for new events for up to this many 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
+ """
+ if not id_or_name:
+ raise ValueError(f"Expected a non-empty value for `id_or_name` but received {id_or_name!r}")
+ if not key:
+ raise ValueError(f"Expected a non-empty value for `key` but received {key!r}")
+ return self._get(
+ path_template("/vaults/{id_or_name}/items/{key}/events", id_or_name=id_or_name, key=key),
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=maybe_transform(
+ {
+ "after": after,
+ "wait": wait,
+ },
+ item_events_params.ItemEventsParams,
+ ),
+ ),
+ cast_to=ItemEventsResponse,
+ )
+
+ def perform_operation(
+ self,
+ key: str,
+ *,
+ id_or_name: str,
+ type: Literal["authorize"],
+ # 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,
+ ) -> VaultItem:
+ """
+ Retrieve the item first and invoke only an operation listed in
+ `available_operations`, following its natural-language description. Operations
+ may call an external provider and can return the item's updated state.
+
+ 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_or_name:
+ raise ValueError(f"Expected a non-empty value for `id_or_name` but received {id_or_name!r}")
+ if not key:
+ raise ValueError(f"Expected a non-empty value for `key` but received {key!r}")
+ return cast(
+ VaultItem,
+ self._post(
+ path_template("/vaults/{id_or_name}/items/{key}/operations", id_or_name=id_or_name, key=key),
+ body=maybe_transform({"type": type}, item_perform_operation_params.ItemPerformOperationParams),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=cast(Any, VaultItem), # Union types cannot be passed in as arguments in the type system
+ ),
+ )
+
+ @overload
+ def upsert(
+ self,
+ key: str,
+ *,
+ id_or_name: str,
+ spec: WalletVaultItemSpecParam,
+ type: Literal["wallet"],
+ # 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,
+ ) -> VaultItem:
+ """
+ Create or retrieve an identical vault item by immutable key
+
+ Args:
+ spec: AgentCard wallet. Mode (sandbox vs live) is fixed by the deployment's AgentCard
+ credential; there is no per-item test flag. user_id may only reference a user
+ already enrolled by a wallet in this organization.
+
+ 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
+ """
+ ...
+
+ @overload
+ def upsert(
+ self,
+ key: str,
+ *,
+ id_or_name: str,
+ spec: CardVaultItemSpecParam,
+ type: Literal["card"],
+ # 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,
+ ) -> VaultItem:
+ """
+ Create or retrieve an identical vault item by immutable key
+
+ Args:
+ spec: AgentCard reusable card. Each checkout creates an approval-gated authorization
+ for spec.merchant / spec.amount. The card stays ready after each authorization.
+
+ 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
+ """
+ ...
+
+ @required_args(["id_or_name", "spec", "type"])
+ def upsert(
+ self,
+ key: str,
+ *,
+ id_or_name: str,
+ spec: WalletVaultItemSpecParam | CardVaultItemSpecParam,
+ type: Literal["wallet"] | Literal["card"],
+ # 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,
+ ) -> VaultItem:
+ if not id_or_name:
+ raise ValueError(f"Expected a non-empty value for `id_or_name` but received {id_or_name!r}")
+ if not key:
+ raise ValueError(f"Expected a non-empty value for `key` but received {key!r}")
+ return cast(
+ VaultItem,
+ self._put(
+ path_template("/vaults/{id_or_name}/items/{key}", id_or_name=id_or_name, key=key),
+ body=maybe_transform(
+ {
+ "spec": spec,
+ "type": type,
+ },
+ item_upsert_params.ItemUpsertParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=cast(Any, VaultItem), # Union types cannot be passed in as arguments in the type system
+ ),
+ )
+
+
+class AsyncItemsResource(AsyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> AsyncItemsResourceWithRawResponse:
+ """
+ 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 AsyncItemsResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncItemsResourceWithStreamingResponse:
+ """
+ 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 AsyncItemsResourceWithStreamingResponse(self)
+
+ async def retrieve(
+ self,
+ key: str,
+ *,
+ id_or_name: str,
+ expand: List[Literal["payment_methods"]] | Omit = omit,
+ wait: 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,
+ ) -> VaultItem:
+ """
+ The response advertises operations that are valid in the item's current state
+ and live data that can be requested through `expand`. Read each operation's
+ description before using it. Expanded data is fetched from the provider and is
+ not persisted in the vault item. Requesting an unavailable expansion returns 409
+ instead of a partial item.
+
+ Args:
+ expand: Live fields advertised by `available_expansions` to include in `expanded`.
+
+ wait: Hold for up to this many seconds while the item is pending authorization or
+ approval.
+
+ 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_or_name:
+ raise ValueError(f"Expected a non-empty value for `id_or_name` but received {id_or_name!r}")
+ if not key:
+ raise ValueError(f"Expected a non-empty value for `key` but received {key!r}")
+ return cast(
+ VaultItem,
+ await self._get(
+ path_template("/vaults/{id_or_name}/items/{key}", id_or_name=id_or_name, key=key),
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=await async_maybe_transform(
+ {
+ "expand": expand,
+ "wait": wait,
+ },
+ item_retrieve_params.ItemRetrieveParams,
+ ),
+ ),
+ cast_to=cast(Any, VaultItem), # Union types cannot be passed in as arguments in the type system
+ ),
+ )
+
+ async def update(
+ self,
+ key: str,
+ *,
+ id_or_name: str,
+ spec: CardVaultItemSpecParam,
+ # 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,
+ ) -> VaultItem:
+ """
+ Update a card specification before or between authorizations
+
+ Args:
+ spec: AgentCard reusable card. Each checkout creates an approval-gated authorization
+ for spec.merchant / spec.amount. The card stays ready after each authorization.
+
+ 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_or_name:
+ raise ValueError(f"Expected a non-empty value for `id_or_name` but received {id_or_name!r}")
+ if not key:
+ raise ValueError(f"Expected a non-empty value for `key` but received {key!r}")
+ return cast(
+ VaultItem,
+ await self._patch(
+ path_template("/vaults/{id_or_name}/items/{key}", id_or_name=id_or_name, key=key),
+ body=await async_maybe_transform({"spec": spec}, item_update_params.ItemUpdateParams),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=cast(Any, VaultItem), # Union types cannot be passed in as arguments in the type system
+ ),
+ )
+
+ async def list(
+ self,
+ id_or_name: 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,
+ ) -> ItemListResponse:
+ """
+ List vault items without secret values
+
+ 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_or_name:
+ raise ValueError(f"Expected a non-empty value for `id_or_name` but received {id_or_name!r}")
+ return await self._get(
+ path_template("/vaults/{id_or_name}/items", id_or_name=id_or_name),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ItemListResponse,
+ )
+
+ async def delete(
+ self,
+ key: str,
+ *,
+ id_or_name: 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 vault item and invalidate its secret value
+
+ 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_or_name:
+ raise ValueError(f"Expected a non-empty value for `id_or_name` but received {id_or_name!r}")
+ if not key:
+ raise ValueError(f"Expected a non-empty value for `key` but received {key!r}")
+ extra_headers = {"Accept": "*/*", **(extra_headers or {})}
+ return await self._delete(
+ path_template("/vaults/{id_or_name}/items/{key}", id_or_name=id_or_name, key=key),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=NoneType,
+ )
+
+ async def events(
+ self,
+ key: str,
+ *,
+ id_or_name: str,
+ after: str | Omit = omit,
+ wait: 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,
+ ) -> ItemEventsResponse:
+ """
+ List immutable audit events for a vault item
+
+ Args:
+ after: Return events after this event ID.
+
+ wait: Long-poll for new events for up to this many 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
+ """
+ if not id_or_name:
+ raise ValueError(f"Expected a non-empty value for `id_or_name` but received {id_or_name!r}")
+ if not key:
+ raise ValueError(f"Expected a non-empty value for `key` but received {key!r}")
+ return await self._get(
+ path_template("/vaults/{id_or_name}/items/{key}/events", id_or_name=id_or_name, key=key),
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=await async_maybe_transform(
+ {
+ "after": after,
+ "wait": wait,
+ },
+ item_events_params.ItemEventsParams,
+ ),
+ ),
+ cast_to=ItemEventsResponse,
+ )
+
+ async def perform_operation(
+ self,
+ key: str,
+ *,
+ id_or_name: str,
+ type: Literal["authorize"],
+ # 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,
+ ) -> VaultItem:
+ """
+ Retrieve the item first and invoke only an operation listed in
+ `available_operations`, following its natural-language description. Operations
+ may call an external provider and can return the item's updated state.
+
+ 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_or_name:
+ raise ValueError(f"Expected a non-empty value for `id_or_name` but received {id_or_name!r}")
+ if not key:
+ raise ValueError(f"Expected a non-empty value for `key` but received {key!r}")
+ return cast(
+ VaultItem,
+ await self._post(
+ path_template("/vaults/{id_or_name}/items/{key}/operations", id_or_name=id_or_name, key=key),
+ body=await async_maybe_transform(
+ {"type": type}, item_perform_operation_params.ItemPerformOperationParams
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=cast(Any, VaultItem), # Union types cannot be passed in as arguments in the type system
+ ),
+ )
+
+ @overload
+ async def upsert(
+ self,
+ key: str,
+ *,
+ id_or_name: str,
+ spec: WalletVaultItemSpecParam,
+ type: Literal["wallet"],
+ # 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,
+ ) -> VaultItem:
+ """
+ Create or retrieve an identical vault item by immutable key
+
+ Args:
+ spec: AgentCard wallet. Mode (sandbox vs live) is fixed by the deployment's AgentCard
+ credential; there is no per-item test flag. user_id may only reference a user
+ already enrolled by a wallet in this organization.
+
+ 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
+ """
+ ...
+
+ @overload
+ async def upsert(
+ self,
+ key: str,
+ *,
+ id_or_name: str,
+ spec: CardVaultItemSpecParam,
+ type: Literal["card"],
+ # 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,
+ ) -> VaultItem:
+ """
+ Create or retrieve an identical vault item by immutable key
+
+ Args:
+ spec: AgentCard reusable card. Each checkout creates an approval-gated authorization
+ for spec.merchant / spec.amount. The card stays ready after each authorization.
+
+ 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
+ """
+ ...
+
+ @required_args(["id_or_name", "spec", "type"])
+ async def upsert(
+ self,
+ key: str,
+ *,
+ id_or_name: str,
+ spec: WalletVaultItemSpecParam | CardVaultItemSpecParam,
+ type: Literal["wallet"] | Literal["card"],
+ # 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,
+ ) -> VaultItem:
+ if not id_or_name:
+ raise ValueError(f"Expected a non-empty value for `id_or_name` but received {id_or_name!r}")
+ if not key:
+ raise ValueError(f"Expected a non-empty value for `key` but received {key!r}")
+ return cast(
+ VaultItem,
+ await self._put(
+ path_template("/vaults/{id_or_name}/items/{key}", id_or_name=id_or_name, key=key),
+ body=await async_maybe_transform(
+ {
+ "spec": spec,
+ "type": type,
+ },
+ item_upsert_params.ItemUpsertParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=cast(Any, VaultItem), # Union types cannot be passed in as arguments in the type system
+ ),
+ )
+
+
+class ItemsResourceWithRawResponse:
+ def __init__(self, items: ItemsResource) -> None:
+ self._items = items
+
+ self.retrieve = to_raw_response_wrapper(
+ items.retrieve,
+ )
+ self.update = to_raw_response_wrapper(
+ items.update,
+ )
+ self.list = to_raw_response_wrapper(
+ items.list,
+ )
+ self.delete = to_raw_response_wrapper(
+ items.delete,
+ )
+ self.events = to_raw_response_wrapper(
+ items.events,
+ )
+ self.perform_operation = to_raw_response_wrapper(
+ items.perform_operation,
+ )
+ self.upsert = to_raw_response_wrapper(
+ items.upsert,
+ )
+
+
+class AsyncItemsResourceWithRawResponse:
+ def __init__(self, items: AsyncItemsResource) -> None:
+ self._items = items
+
+ self.retrieve = async_to_raw_response_wrapper(
+ items.retrieve,
+ )
+ self.update = async_to_raw_response_wrapper(
+ items.update,
+ )
+ self.list = async_to_raw_response_wrapper(
+ items.list,
+ )
+ self.delete = async_to_raw_response_wrapper(
+ items.delete,
+ )
+ self.events = async_to_raw_response_wrapper(
+ items.events,
+ )
+ self.perform_operation = async_to_raw_response_wrapper(
+ items.perform_operation,
+ )
+ self.upsert = async_to_raw_response_wrapper(
+ items.upsert,
+ )
+
+
+class ItemsResourceWithStreamingResponse:
+ def __init__(self, items: ItemsResource) -> None:
+ self._items = items
+
+ self.retrieve = to_streamed_response_wrapper(
+ items.retrieve,
+ )
+ self.update = to_streamed_response_wrapper(
+ items.update,
+ )
+ self.list = to_streamed_response_wrapper(
+ items.list,
+ )
+ self.delete = to_streamed_response_wrapper(
+ items.delete,
+ )
+ self.events = to_streamed_response_wrapper(
+ items.events,
+ )
+ self.perform_operation = to_streamed_response_wrapper(
+ items.perform_operation,
+ )
+ self.upsert = to_streamed_response_wrapper(
+ items.upsert,
+ )
+
+
+class AsyncItemsResourceWithStreamingResponse:
+ def __init__(self, items: AsyncItemsResource) -> None:
+ self._items = items
+
+ self.retrieve = async_to_streamed_response_wrapper(
+ items.retrieve,
+ )
+ self.update = async_to_streamed_response_wrapper(
+ items.update,
+ )
+ self.list = async_to_streamed_response_wrapper(
+ items.list,
+ )
+ self.delete = async_to_streamed_response_wrapper(
+ items.delete,
+ )
+ self.events = async_to_streamed_response_wrapper(
+ items.events,
+ )
+ self.perform_operation = async_to_streamed_response_wrapper(
+ items.perform_operation,
+ )
+ self.upsert = async_to_streamed_response_wrapper(
+ items.upsert,
+ )
diff --git a/src/kernel/resources/vaults/vaults.py b/src/kernel/resources/vaults/vaults.py
new file mode 100644
index 00000000..ec33277c
--- /dev/null
+++ b/src/kernel/resources/vaults/vaults.py
@@ -0,0 +1,456 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+import httpx
+
+from .items import (
+ ItemsResource,
+ AsyncItemsResource,
+ ItemsResourceWithRawResponse,
+ AsyncItemsResourceWithRawResponse,
+ ItemsResourceWithStreamingResponse,
+ AsyncItemsResourceWithStreamingResponse,
+)
+from ...types import vault_list_params, vault_upsert_params
+from ..._types import Body, Omit, Query, Headers, NoneType, NotGiven, omit, not_given
+from ..._utils import path_template, 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 ...pagination import SyncOffsetPagination, AsyncOffsetPagination
+from ...types.vault import Vault
+from ..._base_client import AsyncPaginator, make_request_options
+
+__all__ = ["VaultsResource", "AsyncVaultsResource"]
+
+
+class VaultsResource(SyncAPIResource):
+ @cached_property
+ def items(self) -> ItemsResource:
+ return ItemsResource(self._client)
+
+ @cached_property
+ def with_raw_response(self) -> VaultsResourceWithRawResponse:
+ """
+ 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 VaultsResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> VaultsResourceWithStreamingResponse:
+ """
+ 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 VaultsResourceWithStreamingResponse(self)
+
+ def retrieve(
+ self,
+ id_or_name: 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,
+ ) -> Vault:
+ """
+ Get a vault
+
+ 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_or_name:
+ raise ValueError(f"Expected a non-empty value for `id_or_name` but received {id_or_name!r}")
+ return self._get(
+ path_template("/vaults/{id_or_name}", id_or_name=id_or_name),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=Vault,
+ )
+
+ def list(
+ self,
+ *,
+ limit: int | Omit = omit,
+ offset: 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,
+ ) -> SyncOffsetPagination[Vault]:
+ """
+ List vaults in the current project
+
+ 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
+ """
+ return self._get_api_list(
+ "/vaults",
+ page=SyncOffsetPagination[Vault],
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=maybe_transform(
+ {
+ "limit": limit,
+ "offset": offset,
+ },
+ vault_list_params.VaultListParams,
+ ),
+ ),
+ model=Vault,
+ )
+
+ def delete(
+ self,
+ id_or_name: 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 vault and invalidate its items
+
+ 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_or_name:
+ raise ValueError(f"Expected a non-empty value for `id_or_name` but received {id_or_name!r}")
+ extra_headers = {"Accept": "*/*", **(extra_headers or {})}
+ return self._delete(
+ path_template("/vaults/{id_or_name}", id_or_name=id_or_name),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=NoneType,
+ )
+
+ def upsert(
+ self,
+ *,
+ name: 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,
+ ) -> Vault:
+ """
+ Create or retrieve a vault by immutable name
+
+ Args:
+ name: Immutable name used to create or retrieve the vault.
+
+ 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(
+ "/vaults",
+ body=maybe_transform({"name": name}, vault_upsert_params.VaultUpsertParams),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=Vault,
+ )
+
+
+class AsyncVaultsResource(AsyncAPIResource):
+ @cached_property
+ def items(self) -> AsyncItemsResource:
+ return AsyncItemsResource(self._client)
+
+ @cached_property
+ def with_raw_response(self) -> AsyncVaultsResourceWithRawResponse:
+ """
+ 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 AsyncVaultsResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncVaultsResourceWithStreamingResponse:
+ """
+ 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 AsyncVaultsResourceWithStreamingResponse(self)
+
+ async def retrieve(
+ self,
+ id_or_name: 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,
+ ) -> Vault:
+ """
+ Get a vault
+
+ 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_or_name:
+ raise ValueError(f"Expected a non-empty value for `id_or_name` but received {id_or_name!r}")
+ return await self._get(
+ path_template("/vaults/{id_or_name}", id_or_name=id_or_name),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=Vault,
+ )
+
+ def list(
+ self,
+ *,
+ limit: int | Omit = omit,
+ offset: 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,
+ ) -> AsyncPaginator[Vault, AsyncOffsetPagination[Vault]]:
+ """
+ List vaults in the current project
+
+ 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
+ """
+ return self._get_api_list(
+ "/vaults",
+ page=AsyncOffsetPagination[Vault],
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=maybe_transform(
+ {
+ "limit": limit,
+ "offset": offset,
+ },
+ vault_list_params.VaultListParams,
+ ),
+ ),
+ model=Vault,
+ )
+
+ async def delete(
+ self,
+ id_or_name: 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 vault and invalidate its items
+
+ 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_or_name:
+ raise ValueError(f"Expected a non-empty value for `id_or_name` but received {id_or_name!r}")
+ extra_headers = {"Accept": "*/*", **(extra_headers or {})}
+ return await self._delete(
+ path_template("/vaults/{id_or_name}", id_or_name=id_or_name),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=NoneType,
+ )
+
+ async def upsert(
+ self,
+ *,
+ name: 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,
+ ) -> Vault:
+ """
+ Create or retrieve a vault by immutable name
+
+ Args:
+ name: Immutable name used to create or retrieve the vault.
+
+ 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(
+ "/vaults",
+ body=await async_maybe_transform({"name": name}, vault_upsert_params.VaultUpsertParams),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=Vault,
+ )
+
+
+class VaultsResourceWithRawResponse:
+ def __init__(self, vaults: VaultsResource) -> None:
+ self._vaults = vaults
+
+ self.retrieve = to_raw_response_wrapper(
+ vaults.retrieve,
+ )
+ self.list = to_raw_response_wrapper(
+ vaults.list,
+ )
+ self.delete = to_raw_response_wrapper(
+ vaults.delete,
+ )
+ self.upsert = to_raw_response_wrapper(
+ vaults.upsert,
+ )
+
+ @cached_property
+ def items(self) -> ItemsResourceWithRawResponse:
+ return ItemsResourceWithRawResponse(self._vaults.items)
+
+
+class AsyncVaultsResourceWithRawResponse:
+ def __init__(self, vaults: AsyncVaultsResource) -> None:
+ self._vaults = vaults
+
+ self.retrieve = async_to_raw_response_wrapper(
+ vaults.retrieve,
+ )
+ self.list = async_to_raw_response_wrapper(
+ vaults.list,
+ )
+ self.delete = async_to_raw_response_wrapper(
+ vaults.delete,
+ )
+ self.upsert = async_to_raw_response_wrapper(
+ vaults.upsert,
+ )
+
+ @cached_property
+ def items(self) -> AsyncItemsResourceWithRawResponse:
+ return AsyncItemsResourceWithRawResponse(self._vaults.items)
+
+
+class VaultsResourceWithStreamingResponse:
+ def __init__(self, vaults: VaultsResource) -> None:
+ self._vaults = vaults
+
+ self.retrieve = to_streamed_response_wrapper(
+ vaults.retrieve,
+ )
+ self.list = to_streamed_response_wrapper(
+ vaults.list,
+ )
+ self.delete = to_streamed_response_wrapper(
+ vaults.delete,
+ )
+ self.upsert = to_streamed_response_wrapper(
+ vaults.upsert,
+ )
+
+ @cached_property
+ def items(self) -> ItemsResourceWithStreamingResponse:
+ return ItemsResourceWithStreamingResponse(self._vaults.items)
+
+
+class AsyncVaultsResourceWithStreamingResponse:
+ def __init__(self, vaults: AsyncVaultsResource) -> None:
+ self._vaults = vaults
+
+ self.retrieve = async_to_streamed_response_wrapper(
+ vaults.retrieve,
+ )
+ self.list = async_to_streamed_response_wrapper(
+ vaults.list,
+ )
+ self.delete = async_to_streamed_response_wrapper(
+ vaults.delete,
+ )
+ self.upsert = async_to_streamed_response_wrapper(
+ vaults.upsert,
+ )
+
+ @cached_property
+ def items(self) -> AsyncItemsResourceWithStreamingResponse:
+ return AsyncItemsResourceWithStreamingResponse(self._vaults.items)
diff --git a/src/kernel/types/__init__.py b/src/kernel/types/__init__.py
index fffffd45..0310cfbe 100644
--- a/src/kernel/types/__init__.py
+++ b/src/kernel/types/__init__.py
@@ -6,6 +6,7 @@
from .. import _compat
from .tags import Tags as Tags
from .proxy import Proxy as Proxy
+from .vault import Vault as Vault
from .shared import (
LogEvent as LogEvent,
AppAction as AppAction,
@@ -35,11 +36,13 @@
from .audit_log_entry import AuditLogEntry as AuditLogEntry
from .created_api_key import CreatedAPIKey as CreatedAPIKey
from .lookup_response import LookupResponse as LookupResponse
+from .vault_reference import VaultReference as VaultReference
from .analysis_summary import AnalysisSummary as AnalysisSummary
from .browser_pool_ref import BrowserPoolRef as BrowserPoolRef
from .app_list_response import AppListResponse as AppListResponse
from .no_recommendation import NoRecommendation as NoRecommendation
from .proxy_list_params import ProxyListParams as ProxyListParams
+from .vault_list_params import VaultListParams as VaultListParams
from .browser_proxy_mode import BrowserProxyMode as BrowserProxyMode
from .proxy_check_params import ProxyCheckParams as ProxyCheckParams
from .api_key_list_params import APIKeyListParams as APIKeyListParams
@@ -51,6 +54,7 @@
from .proxy_create_params import ProxyCreateParams as ProxyCreateParams
from .proxy_list_response import ProxyListResponse as ProxyListResponse
from .proxy_update_params import ProxyUpdateParams as ProxyUpdateParams
+from .vault_upsert_params import VaultUpsertParams as VaultUpsertParams
from .browser_proxy_config import BrowserProxyConfig as BrowserProxyConfig
from .proxy_check_response import ProxyCheckResponse as ProxyCheckResponse
from .api_key_create_params import APIKeyCreateParams as APIKeyCreateParams
@@ -69,6 +73,7 @@
from .proxy_create_response import ProxyCreateResponse as ProxyCreateResponse
from .proxy_update_response import ProxyUpdateResponse as ProxyUpdateResponse
from .recommendation_result import RecommendationResult as RecommendationResult
+from .vault_reference_param import VaultReferenceParam as VaultReferenceParam
from .browser_memory_request import BrowserMemoryRequest as BrowserMemoryRequest
from .browser_network_config import BrowserNetworkConfig as BrowserNetworkConfig
from .credential_list_params import CredentialListParams as CredentialListParams
diff --git a/src/kernel/types/browser_create_params.py b/src/kernel/types/browser_create_params.py
index da890722..ab486672 100644
--- a/src/kernel/types/browser_create_params.py
+++ b/src/kernel/types/browser_create_params.py
@@ -6,6 +6,7 @@
from typing_extensions import Literal, TypedDict
from .tags_param import TagsParam
+from .vault_reference_param import VaultReferenceParam
from .browser_memory_request import BrowserMemoryRequest
from .browser_proxy_config_param import BrowserProxyConfigParam
from .browser_network_config_param import BrowserNetworkConfigParam
@@ -149,6 +150,12 @@ class BrowserCreateParams(TypedDict, total=False):
see is +/- 5 seconds around the specified value.
"""
+ vaults: Iterable[VaultReferenceParam]
+ """Project-scoped vaults to link to the browser session.
+
+ Links are immutable after creation.
+ """
+
viewport: BrowserViewport
"""
Initial browser window size in pixels with optional refresh rate. If omitted,
diff --git a/src/kernel/types/browser_create_response.py b/src/kernel/types/browser_create_response.py
index e5f63b6c..678bcbcb 100644
--- a/src/kernel/types/browser_create_response.py
+++ b/src/kernel/types/browser_create_response.py
@@ -1,6 +1,6 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-from typing import Dict, Optional
+from typing import Dict, List, Optional
from datetime import datetime
from typing_extensions import Literal
@@ -10,6 +10,7 @@
from .browser_proxy import BrowserProxy
from .browser_usage import BrowserUsage
from .browser_memory import BrowserMemory
+from .vault_reference import VaultReference
from .browser_pool_ref import BrowserPoolRef
from .browser_network_config import BrowserNetworkConfig
from .shared.browser_viewport import BrowserViewport
@@ -125,6 +126,15 @@ class BrowserCreateResponse(BaseModel):
usage: Optional[BrowserUsage] = None
"""Session usage metrics."""
+ usage_status: Optional[Literal["pending", "ready"]] = None
+ """Whether final usage billing is still pending or complete.
+
+ Only present for deleted sessions.
+ """
+
+ vaults: Optional[List[VaultReference]] = None
+ """Vaults linked when the browser session was created."""
+
viewport: Optional[BrowserViewport] = None
"""
Initial browser window size in pixels with optional refresh rate. If omitted,
diff --git a/src/kernel/types/browser_list_response.py b/src/kernel/types/browser_list_response.py
index da294a61..aa281a39 100644
--- a/src/kernel/types/browser_list_response.py
+++ b/src/kernel/types/browser_list_response.py
@@ -1,6 +1,6 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-from typing import Dict, Optional
+from typing import Dict, List, Optional
from datetime import datetime
from typing_extensions import Literal
@@ -10,6 +10,7 @@
from .browser_proxy import BrowserProxy
from .browser_usage import BrowserUsage
from .browser_memory import BrowserMemory
+from .vault_reference import VaultReference
from .browser_pool_ref import BrowserPoolRef
from .browser_network_config import BrowserNetworkConfig
from .shared.browser_viewport import BrowserViewport
@@ -125,6 +126,15 @@ class BrowserListResponse(BaseModel):
usage: Optional[BrowserUsage] = None
"""Session usage metrics."""
+ usage_status: Optional[Literal["pending", "ready"]] = None
+ """Whether final usage billing is still pending or complete.
+
+ Only present for deleted sessions.
+ """
+
+ vaults: Optional[List[VaultReference]] = None
+ """Vaults linked when the browser session was created."""
+
viewport: Optional[BrowserViewport] = None
"""
Initial browser window size in pixels with optional refresh rate. If omitted,
diff --git a/src/kernel/types/browser_pool_acquire_response.py b/src/kernel/types/browser_pool_acquire_response.py
index 755f5838..d472b5e0 100644
--- a/src/kernel/types/browser_pool_acquire_response.py
+++ b/src/kernel/types/browser_pool_acquire_response.py
@@ -1,6 +1,6 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-from typing import Dict, Optional
+from typing import Dict, List, Optional
from datetime import datetime
from typing_extensions import Literal
@@ -10,6 +10,7 @@
from .browser_proxy import BrowserProxy
from .browser_usage import BrowserUsage
from .browser_memory import BrowserMemory
+from .vault_reference import VaultReference
from .browser_pool_ref import BrowserPoolRef
from .browser_network_config import BrowserNetworkConfig
from .shared.browser_viewport import BrowserViewport
@@ -125,6 +126,15 @@ class BrowserPoolAcquireResponse(BaseModel):
usage: Optional[BrowserUsage] = None
"""Session usage metrics."""
+ usage_status: Optional[Literal["pending", "ready"]] = None
+ """Whether final usage billing is still pending or complete.
+
+ Only present for deleted sessions.
+ """
+
+ vaults: Optional[List[VaultReference]] = None
+ """Vaults linked when the browser session was created."""
+
viewport: Optional[BrowserViewport] = None
"""
Initial browser window size in pixels with optional refresh rate. If omitted,
diff --git a/src/kernel/types/browser_retrieve_response.py b/src/kernel/types/browser_retrieve_response.py
index 332585ca..e6881ab1 100644
--- a/src/kernel/types/browser_retrieve_response.py
+++ b/src/kernel/types/browser_retrieve_response.py
@@ -1,6 +1,6 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-from typing import Dict, Optional
+from typing import Dict, List, Optional
from datetime import datetime
from typing_extensions import Literal
@@ -10,6 +10,7 @@
from .browser_proxy import BrowserProxy
from .browser_usage import BrowserUsage
from .browser_memory import BrowserMemory
+from .vault_reference import VaultReference
from .browser_pool_ref import BrowserPoolRef
from .browser_network_config import BrowserNetworkConfig
from .shared.browser_viewport import BrowserViewport
@@ -125,6 +126,15 @@ class BrowserRetrieveResponse(BaseModel):
usage: Optional[BrowserUsage] = None
"""Session usage metrics."""
+ usage_status: Optional[Literal["pending", "ready"]] = None
+ """Whether final usage billing is still pending or complete.
+
+ Only present for deleted sessions.
+ """
+
+ vaults: Optional[List[VaultReference]] = None
+ """Vaults linked when the browser session was created."""
+
viewport: Optional[BrowserViewport] = None
"""
Initial browser window size in pixels with optional refresh rate. If omitted,
diff --git a/src/kernel/types/browser_update_response.py b/src/kernel/types/browser_update_response.py
index 7af24aee..65be1ba3 100644
--- a/src/kernel/types/browser_update_response.py
+++ b/src/kernel/types/browser_update_response.py
@@ -1,6 +1,6 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-from typing import Dict, Optional
+from typing import Dict, List, Optional
from datetime import datetime
from typing_extensions import Literal
@@ -10,6 +10,7 @@
from .browser_proxy import BrowserProxy
from .browser_usage import BrowserUsage
from .browser_memory import BrowserMemory
+from .vault_reference import VaultReference
from .browser_pool_ref import BrowserPoolRef
from .browser_network_config import BrowserNetworkConfig
from .shared.browser_viewport import BrowserViewport
@@ -125,6 +126,15 @@ class BrowserUpdateResponse(BaseModel):
usage: Optional[BrowserUsage] = None
"""Session usage metrics."""
+ usage_status: Optional[Literal["pending", "ready"]] = None
+ """Whether final usage billing is still pending or complete.
+
+ Only present for deleted sessions.
+ """
+
+ vaults: Optional[List[VaultReference]] = None
+ """Vaults linked when the browser session was created."""
+
viewport: Optional[BrowserViewport] = None
"""
Initial browser window size in pixels with optional refresh rate. If omitted,
diff --git a/src/kernel/types/config_registry_list_params.py b/src/kernel/types/config_registry_list_params.py
index 5259e4b7..7277ef4b 100644
--- a/src/kernel/types/config_registry_list_params.py
+++ b/src/kernel/types/config_registry_list_params.py
@@ -13,9 +13,9 @@ class ConfigRegistryListParams(TypedDict, total=False):
offset: int
search: str
- """Case-insensitive domain search.
-
- Full URLs are reduced to their registrable domain.
+ """
+ Case-insensitive substring search over normalized targets, including domain,
+ subdomain, and path.
"""
sort_by: Literal["target", "analysis_status", "recommended_config", "last_requested_at", "success_rate"]
diff --git a/src/kernel/types/invocation_list_browsers_response.py b/src/kernel/types/invocation_list_browsers_response.py
index e31194b8..bb9d423d 100644
--- a/src/kernel/types/invocation_list_browsers_response.py
+++ b/src/kernel/types/invocation_list_browsers_response.py
@@ -10,6 +10,7 @@
from .browser_proxy import BrowserProxy
from .browser_usage import BrowserUsage
from .browser_memory import BrowserMemory
+from .vault_reference import VaultReference
from .browser_pool_ref import BrowserPoolRef
from .browser_network_config import BrowserNetworkConfig
from .shared.browser_viewport import BrowserViewport
@@ -125,6 +126,15 @@ class Browser(BaseModel):
usage: Optional[BrowserUsage] = None
"""Session usage metrics."""
+ usage_status: Optional[Literal["pending", "ready"]] = None
+ """Whether final usage billing is still pending or complete.
+
+ Only present for deleted sessions.
+ """
+
+ vaults: Optional[List[VaultReference]] = None
+ """Vaults linked when the browser session was created."""
+
viewport: Optional[BrowserViewport] = None
"""
Initial browser window size in pixels with optional refresh rate. If omitted,
diff --git a/src/kernel/types/recommendation_summary.py b/src/kernel/types/recommendation_summary.py
index df83ae35..278ba9ef 100644
--- a/src/kernel/types/recommendation_summary.py
+++ b/src/kernel/types/recommendation_summary.py
@@ -12,16 +12,22 @@
class RecommendationSummary(BaseModel):
analysis_id: str
- """ID of the most recently requested analysis for this domain."""
+ """ID of the most recently requested analysis for this exact target."""
analysis_status: Literal["running", "completed", "failed", "canceled"]
- """Lifecycle status of the most recently requested analysis for this domain."""
+ """Lifecycle status of the most recently requested analysis for this exact target."""
last_requested_at: datetime
- """Most recent time the selected project requested an analysis for this domain."""
+ """
+ Most recent time the selected project requested an analysis for this exact
+ target.
+ """
recommendation: Optional[Recommendation] = None
- """Current domain-level recommendation. Null when no eligible knowledge exists."""
+ """Recommendation produced by the latest analysis.
+
+ Null when that analysis did not produce one.
+ """
recommended_config_label: Optional[str] = None
"""Display label for the recommended browser configuration."""
@@ -29,8 +35,11 @@ class RecommendationSummary(BaseModel):
success_rate: Optional[float] = None
"""Success rate for the recommended configuration.
- Null when no eligible knowledge exists.
+ Null when the latest analysis did not produce one.
"""
target: str
- """Registrable domain previously analyzed by the selected project."""
+ """
+ Normalized exact target previously analyzed by the selected project, including
+ scheme, host, port, and path.
+ """
diff --git a/src/kernel/types/telemetry/otlp_destination.py b/src/kernel/types/telemetry/otlp_destination.py
index 0afe6ae8..293c2497 100644
--- a/src/kernel/types/telemetry/otlp_destination.py
+++ b/src/kernel/types/telemetry/otlp_destination.py
@@ -16,6 +16,13 @@ class OtlpDestination(BaseModel):
id: str
+ consecutive_failures: int
+ """
+ Failed deliveries since the last success, as observed by the relay process that
+ wrote the latest outcome. Zero means the most recently recorded outcome
+ succeeded.
+ """
+
created_at: datetime
endpoint: str
@@ -39,3 +46,21 @@ class OtlpDestination(BaseModel):
updated_at: datetime
description: Optional[str] = None
+
+ last_error: Optional[str] = None
+ """Sanitized class of the delivery failure recorded at `last_error_at`.
+
+ It is retained after a later success, so its presence does not mean the
+ destination is currently failing. Response bodies, endpoint URLs, credentials,
+ and raw transport errors are never returned.
+ """
+
+ last_error_at: Optional[datetime] = None
+ """Timestamp of the most recent failed delivery.
+
+ It is retained after a later success, so it can predate `last_export_at`. Read
+ `consecutive_failures` to tell whether the destination is currently failing.
+ """
+
+ last_export_at: Optional[datetime] = None
+ """Timestamp of the most recent successful delivery. Moves only on success."""
diff --git a/src/kernel/types/vault.py b/src/kernel/types/vault.py
new file mode 100644
index 00000000..210edfbe
--- /dev/null
+++ b/src/kernel/types/vault.py
@@ -0,0 +1,18 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from datetime import datetime
+
+from .._models import BaseModel
+
+__all__ = ["Vault"]
+
+
+class Vault(BaseModel):
+ id: str
+
+ created_at: datetime
+
+ name: str
+ """Immutable name assigned when the vault is created."""
+
+ updated_at: datetime
diff --git a/src/kernel/types/vault_list_params.py b/src/kernel/types/vault_list_params.py
new file mode 100644
index 00000000..7530bc28
--- /dev/null
+++ b/src/kernel/types/vault_list_params.py
@@ -0,0 +1,13 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import TypedDict
+
+__all__ = ["VaultListParams"]
+
+
+class VaultListParams(TypedDict, total=False):
+ limit: int
+
+ offset: int
diff --git a/src/kernel/types/vault_reference.py b/src/kernel/types/vault_reference.py
new file mode 100644
index 00000000..f22e7de8
--- /dev/null
+++ b/src/kernel/types/vault_reference.py
@@ -0,0 +1,15 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Optional
+
+from .._models import BaseModel
+
+__all__ = ["VaultReference"]
+
+
+class VaultReference(BaseModel):
+ """Reference to a project-scoped vault. Provide exactly one of id or name."""
+
+ id: Optional[str] = None
+
+ name: Optional[str] = None
diff --git a/src/kernel/types/vault_reference_param.py b/src/kernel/types/vault_reference_param.py
new file mode 100644
index 00000000..3e8fe9ac
--- /dev/null
+++ b/src/kernel/types/vault_reference_param.py
@@ -0,0 +1,15 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import TypedDict
+
+__all__ = ["VaultReferenceParam"]
+
+
+class VaultReferenceParam(TypedDict, total=False):
+ """Reference to a project-scoped vault. Provide exactly one of id or name."""
+
+ id: str
+
+ name: str
diff --git a/src/kernel/types/vault_upsert_params.py b/src/kernel/types/vault_upsert_params.py
new file mode 100644
index 00000000..84be182b
--- /dev/null
+++ b/src/kernel/types/vault_upsert_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 Required, TypedDict
+
+__all__ = ["VaultUpsertParams"]
+
+
+class VaultUpsertParams(TypedDict, total=False):
+ name: Required[str]
+ """Immutable name used to create or retrieve the vault."""
diff --git a/src/kernel/types/vaults/__init__.py b/src/kernel/types/vaults/__init__.py
new file mode 100644
index 00000000..7ee998eb
--- /dev/null
+++ b/src/kernel/types/vaults/__init__.py
@@ -0,0 +1,23 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from .vault_item import VaultItem as VaultItem
+from .vault_item_event import VaultItemEvent as VaultItemEvent
+from .vault_item_action import VaultItemAction as VaultItemAction
+from .item_events_params import ItemEventsParams as ItemEventsParams
+from .item_list_response import ItemListResponse as ItemListResponse
+from .item_update_params import ItemUpdateParams as ItemUpdateParams
+from .item_upsert_params import ItemUpsertParams as ItemUpsertParams
+from .vault_card_aliases import VaultCardAliases as VaultCardAliases
+from .card_vault_item_spec import CardVaultItemSpec as CardVaultItemSpec
+from .item_events_response import ItemEventsResponse as ItemEventsResponse
+from .item_retrieve_params import ItemRetrieveParams as ItemRetrieveParams
+from .vault_payment_method import VaultPaymentMethod as VaultPaymentMethod
+from .card_vault_item_state import CardVaultItemState as CardVaultItemState
+from .wallet_vault_item_spec import WalletVaultItemSpec as WalletVaultItemSpec
+from .wallet_vault_item_state import WalletVaultItemState as WalletVaultItemState
+from .card_vault_item_spec_param import CardVaultItemSpecParam as CardVaultItemSpecParam
+from .wallet_vault_item_spec_param import WalletVaultItemSpecParam as WalletVaultItemSpecParam
+from .item_perform_operation_params import ItemPerformOperationParams as ItemPerformOperationParams
+from .agentcard_checkout_authorization import AgentcardCheckoutAuthorization as AgentcardCheckoutAuthorization
diff --git a/src/kernel/types/vaults/agentcard_checkout_authorization.py b/src/kernel/types/vaults/agentcard_checkout_authorization.py
new file mode 100644
index 00000000..2a0dc815
--- /dev/null
+++ b/src/kernel/types/vaults/agentcard_checkout_authorization.py
@@ -0,0 +1,66 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Optional
+from datetime import datetime
+from typing_extensions import Literal
+
+from ..._models import BaseModel
+
+__all__ = ["AgentcardCheckoutAuthorization"]
+
+
+class AgentcardCheckoutAuthorization(BaseModel):
+ """The in-flight or most recent checkout authorization.
+
+ Present while a checkout is pending approval and after it settles.
+ """
+
+ id: str
+
+ amount_cents: int
+
+ created_at: datetime
+
+ currency: str
+
+ merchant: str
+
+ psp: str
+
+ status: Literal["awaiting_approval", "approved", "declined", "expired"]
+
+ actual_cents: Optional[int] = None
+
+ amount: Optional[str] = None
+ """Display amount shown on the approval screen."""
+
+ amount_authority: Optional[Literal["display_only", "stripe_payment_intent"]] = None
+
+ amount_verified: Optional[bool] = None
+
+ approval_url: Optional[str] = None
+
+ browser_id: Optional[str] = None
+ """Browser session that submitted the checkout."""
+
+ charged_amount_cents: Optional[int] = None
+
+ charged_currency: Optional[str] = None
+
+ charged_kind: Optional[Literal["captured", "authorized", "none"]] = None
+
+ expected_cents: Optional[int] = None
+
+ expires_at: Optional[datetime] = None
+
+ psp_error_code: Optional[str] = None
+
+ reason: Optional[str] = None
+
+ replay_attempted: Optional[bool] = None
+
+ replay_delivered: Optional[bool] = None
+ """Whether the processor response was delivered to the browser."""
+
+ replay_status: Optional[int] = None
+ """HTTP status of the replayed processor response."""
diff --git a/src/kernel/types/vaults/card_vault_item_spec.py b/src/kernel/types/vaults/card_vault_item_spec.py
new file mode 100644
index 00000000..65eebebd
--- /dev/null
+++ b/src/kernel/types/vaults/card_vault_item_spec.py
@@ -0,0 +1,125 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Dict, List, Union, Optional
+from typing_extensions import Literal, Annotated, TypeAlias
+
+from ..._utils import PropertyInfo
+from ..._models import BaseModel
+
+__all__ = [
+ "CardVaultItemSpec",
+ "LinkCardVaultItemSpec",
+ "LinkCardVaultItemSpecLineItem",
+ "LinkCardVaultItemSpecLineItemTotal",
+ "LinkCardVaultItemSpecTotal",
+ "AgentCardCardVaultItemSpec",
+]
+
+
+class LinkCardVaultItemSpecLineItemTotal(BaseModel):
+ amount: int
+ """Total amount in minor currency units."""
+
+ display_text: str
+
+ type: str
+
+
+class LinkCardVaultItemSpecLineItem(BaseModel):
+ name: str
+
+ description: Optional[str] = None
+
+ image_url: Optional[str] = None
+
+ product_url: Optional[str] = None
+
+ quantity: Optional[int] = None
+
+ sku: Optional[str] = None
+
+ totals: Optional[List[LinkCardVaultItemSpecLineItemTotal]] = None
+
+ unit_amount: Optional[int] = None
+ """Unit amount in minor currency units."""
+
+ url: Optional[str] = None
+
+
+class LinkCardVaultItemSpecTotal(BaseModel):
+ amount: int
+ """Total amount in minor currency units."""
+
+ display_text: str
+
+ type: str
+
+
+class LinkCardVaultItemSpec(BaseModel):
+ amount: int
+ """Integer amount in minor currency units."""
+
+ context: str
+
+ currency: str
+
+ merchant_name: str
+
+ merchant_url: str
+
+ payment_method_id: str
+ """Payment-method ID returned by the referenced wallet's payment-method listing.
+
+ The provider decides whether the selected funding method can satisfy the card
+ request.
+ """
+
+ provider: Literal["link"]
+
+ test: bool
+ """
+ Whether Link should return test credentials instead of a live payment
+ credential.
+ """
+
+ wallet: str
+ """Wallet item key used to mint this card."""
+
+ expires_at: Optional[int] = None
+
+ line_items: Optional[List[LinkCardVaultItemSpecLineItem]] = None
+
+ metadata: Optional[Dict[str, str]] = None
+
+ totals: Optional[List[LinkCardVaultItemSpecTotal]] = None
+
+
+class AgentCardCardVaultItemSpec(BaseModel):
+ """AgentCard reusable card.
+
+ Each checkout creates an approval-gated authorization for spec.merchant / spec.amount. The card stays ready after each authorization.
+ """
+
+ amount: int
+ """Integer amount in minor currency units."""
+
+ currency: str
+
+ merchant: str
+ """Merchant name shown on the cardholder's approval screen."""
+
+ provider: Literal["agentcard"]
+
+ wallet: str
+ """Wallet item key used to authorize checkouts."""
+
+ card_id: Optional[str] = None
+ """AgentCard vaulted card to pay with.
+
+ Omitted, the cardholder picks on the approval screen.
+ """
+
+
+CardVaultItemSpec: TypeAlias = Annotated[
+ Union[LinkCardVaultItemSpec, AgentCardCardVaultItemSpec], PropertyInfo(discriminator="provider")
+]
diff --git a/src/kernel/types/vaults/card_vault_item_spec_param.py b/src/kernel/types/vaults/card_vault_item_spec_param.py
new file mode 100644
index 00000000..22b81433
--- /dev/null
+++ b/src/kernel/types/vaults/card_vault_item_spec_param.py
@@ -0,0 +1,122 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Dict, Union, Iterable
+from typing_extensions import Literal, Required, TypeAlias, TypedDict
+
+__all__ = [
+ "CardVaultItemSpecParam",
+ "LinkCardVaultItemSpec",
+ "LinkCardVaultItemSpecLineItem",
+ "LinkCardVaultItemSpecLineItemTotal",
+ "LinkCardVaultItemSpecTotal",
+ "AgentCardCardVaultItemSpec",
+]
+
+
+class LinkCardVaultItemSpecLineItemTotal(TypedDict, total=False):
+ amount: Required[int]
+ """Total amount in minor currency units."""
+
+ display_text: Required[str]
+
+ type: Required[str]
+
+
+class LinkCardVaultItemSpecLineItem(TypedDict, total=False):
+ name: Required[str]
+
+ description: str
+
+ image_url: str
+
+ product_url: str
+
+ quantity: int
+
+ sku: str
+
+ totals: Iterable[LinkCardVaultItemSpecLineItemTotal]
+
+ unit_amount: int
+ """Unit amount in minor currency units."""
+
+ url: str
+
+
+class LinkCardVaultItemSpecTotal(TypedDict, total=False):
+ amount: Required[int]
+ """Total amount in minor currency units."""
+
+ display_text: Required[str]
+
+ type: Required[str]
+
+
+class LinkCardVaultItemSpec(TypedDict, total=False):
+ amount: Required[int]
+ """Integer amount in minor currency units."""
+
+ context: Required[str]
+
+ currency: Required[str]
+
+ merchant_name: Required[str]
+
+ merchant_url: Required[str]
+
+ payment_method_id: Required[str]
+ """Payment-method ID returned by the referenced wallet's payment-method listing.
+
+ The provider decides whether the selected funding method can satisfy the card
+ request.
+ """
+
+ provider: Required[Literal["link"]]
+
+ test: Required[bool]
+ """
+ Whether Link should return test credentials instead of a live payment
+ credential.
+ """
+
+ wallet: Required[str]
+ """Wallet item key used to mint this card."""
+
+ expires_at: int
+
+ line_items: Iterable[LinkCardVaultItemSpecLineItem]
+
+ metadata: Dict[str, str]
+
+ totals: Iterable[LinkCardVaultItemSpecTotal]
+
+
+class AgentCardCardVaultItemSpec(TypedDict, total=False):
+ """AgentCard reusable card.
+
+ Each checkout creates an approval-gated authorization for spec.merchant / spec.amount. The card stays ready after each authorization.
+ """
+
+ amount: Required[int]
+ """Integer amount in minor currency units."""
+
+ currency: Required[str]
+
+ merchant: Required[str]
+ """Merchant name shown on the cardholder's approval screen."""
+
+ provider: Required[Literal["agentcard"]]
+
+ wallet: Required[str]
+ """Wallet item key used to authorize checkouts."""
+
+ card_id: str
+ """AgentCard vaulted card to pay with.
+
+ Omitted, the cardholder picks on the approval screen.
+ """
+
+
+CardVaultItemSpecParam: TypeAlias = Union[LinkCardVaultItemSpec, AgentCardCardVaultItemSpec]
diff --git a/src/kernel/types/vaults/card_vault_item_state.py b/src/kernel/types/vaults/card_vault_item_state.py
new file mode 100644
index 00000000..4808d1ff
--- /dev/null
+++ b/src/kernel/types/vaults/card_vault_item_state.py
@@ -0,0 +1,86 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import TYPE_CHECKING, Dict, List, Union, Optional
+from typing_extensions import Literal, Annotated, TypeAlias
+
+from pydantic import Field as FieldInfo
+
+from ..._utils import PropertyInfo
+from ..._models import BaseModel
+from .vault_card_aliases import VaultCardAliases
+from .agentcard_checkout_authorization import AgentcardCheckoutAuthorization
+
+__all__ = ["CardVaultItemState", "LinkCardState", "LinkCardStateMasks", "AgentCardCardState", "AgentCardCardStateMasks"]
+
+
+class LinkCardStateMasks(BaseModel):
+ brand: Optional[str] = None
+
+ last4: Optional[str] = None
+
+ if TYPE_CHECKING:
+ # Some versions of Pydantic <2.8.0 have a bug and don’t allow assigning a
+ # value to this field, so for compatibility we avoid doing it at runtime.
+ __pydantic_extra__: Dict[str, str] = FieldInfo(init=False) # pyright: ignore[reportIncompatibleVariableOverride]
+
+ # Stub to indicate that arbitrary properties are accepted.
+ # To access properties that are not valid identifiers you can use `getattr`, e.g.
+ # `getattr(obj, '$type')`
+ def __getattr__(self, attr: str) -> str: ...
+ else:
+ __pydantic_extra__: Dict[str, str]
+
+
+class LinkCardState(BaseModel):
+ provider: Literal["link"]
+
+ status: Literal["requested", "pending_authorization", "ready", "consumed", "expired", "declined"]
+
+ aliases: Optional[VaultCardAliases] = None
+
+ domains: Optional[List[str]] = None
+
+ masks: Optional[LinkCardStateMasks] = None
+
+ status_reason: Optional[str] = None
+
+
+class AgentCardCardStateMasks(BaseModel):
+ brand: Optional[str] = None
+
+ last4: Optional[str] = None
+
+ if TYPE_CHECKING:
+ # Some versions of Pydantic <2.8.0 have a bug and don’t allow assigning a
+ # value to this field, so for compatibility we avoid doing it at runtime.
+ __pydantic_extra__: Dict[str, str] = FieldInfo(init=False) # pyright: ignore[reportIncompatibleVariableOverride]
+
+ # Stub to indicate that arbitrary properties are accepted.
+ # To access properties that are not valid identifiers you can use `getattr`, e.g.
+ # `getattr(obj, '$type')`
+ def __getattr__(self, attr: str) -> str: ...
+ else:
+ __pydantic_extra__: Dict[str, str]
+
+
+class AgentCardCardState(BaseModel):
+ provider: Literal["agentcard"]
+
+ status: Literal["requested", "ready", "pending_approval", "degraded"]
+
+ aliases: Optional[VaultCardAliases] = None
+
+ authorization: Optional[AgentcardCheckoutAuthorization] = None
+ """The in-flight or most recent checkout authorization.
+
+ Present while a checkout is pending approval and after it settles.
+ """
+
+ masks: Optional[AgentCardCardStateMasks] = None
+
+ status_reason: Optional[str] = None
+
+
+CardVaultItemState: TypeAlias = Annotated[
+ Union[LinkCardState, AgentCardCardState], PropertyInfo(discriminator="provider")
+]
diff --git a/src/kernel/types/vaults/item_events_params.py b/src/kernel/types/vaults/item_events_params.py
new file mode 100644
index 00000000..cee33414
--- /dev/null
+++ b/src/kernel/types/vaults/item_events_params.py
@@ -0,0 +1,17 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Required, TypedDict
+
+__all__ = ["ItemEventsParams"]
+
+
+class ItemEventsParams(TypedDict, total=False):
+ id_or_name: Required[str]
+
+ after: str
+ """Return events after this event ID."""
+
+ wait: int
+ """Long-poll for new events for up to this many seconds."""
diff --git a/src/kernel/types/vaults/item_events_response.py b/src/kernel/types/vaults/item_events_response.py
new file mode 100644
index 00000000..fa1959fe
--- /dev/null
+++ b/src/kernel/types/vaults/item_events_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 .vault_item_event import VaultItemEvent
+
+__all__ = ["ItemEventsResponse"]
+
+ItemEventsResponse: TypeAlias = List[VaultItemEvent]
diff --git a/src/kernel/types/vaults/item_list_response.py b/src/kernel/types/vaults/item_list_response.py
new file mode 100644
index 00000000..9bc1fb58
--- /dev/null
+++ b/src/kernel/types/vaults/item_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 .vault_item import VaultItem
+
+__all__ = ["ItemListResponse"]
+
+ItemListResponse: TypeAlias = List[VaultItem]
diff --git a/src/kernel/types/vaults/item_perform_operation_params.py b/src/kernel/types/vaults/item_perform_operation_params.py
new file mode 100644
index 00000000..9d62f380
--- /dev/null
+++ b/src/kernel/types/vaults/item_perform_operation_params.py
@@ -0,0 +1,13 @@
+# 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__ = ["ItemPerformOperationParams"]
+
+
+class ItemPerformOperationParams(TypedDict, total=False):
+ id_or_name: Required[str]
+
+ type: Required[Literal["authorize"]]
diff --git a/src/kernel/types/vaults/item_retrieve_params.py b/src/kernel/types/vaults/item_retrieve_params.py
new file mode 100644
index 00000000..976881b2
--- /dev/null
+++ b/src/kernel/types/vaults/item_retrieve_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 import List
+from typing_extensions import Literal, Required, TypedDict
+
+__all__ = ["ItemRetrieveParams"]
+
+
+class ItemRetrieveParams(TypedDict, total=False):
+ id_or_name: Required[str]
+
+ expand: List[Literal["payment_methods"]]
+ """Live fields advertised by `available_expansions` to include in `expanded`."""
+
+ wait: int
+ """
+ Hold for up to this many seconds while the item is pending authorization or
+ approval.
+ """
diff --git a/src/kernel/types/vaults/item_update_params.py b/src/kernel/types/vaults/item_update_params.py
new file mode 100644
index 00000000..38604305
--- /dev/null
+++ b/src/kernel/types/vaults/item_update_params.py
@@ -0,0 +1,20 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Required, TypedDict
+
+from .card_vault_item_spec_param import CardVaultItemSpecParam
+
+__all__ = ["ItemUpdateParams"]
+
+
+class ItemUpdateParams(TypedDict, total=False):
+ id_or_name: Required[str]
+
+ spec: Required[CardVaultItemSpecParam]
+ """AgentCard reusable card.
+
+ Each checkout creates an approval-gated authorization for spec.merchant /
+ spec.amount. The card stays ready after each authorization.
+ """
diff --git a/src/kernel/types/vaults/item_upsert_params.py b/src/kernel/types/vaults/item_upsert_params.py
new file mode 100644
index 00000000..5f1a4b0e
--- /dev/null
+++ b/src/kernel/types/vaults/item_upsert_params.py
@@ -0,0 +1,41 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Union
+from typing_extensions import Literal, Required, TypeAlias, TypedDict
+
+from .card_vault_item_spec_param import CardVaultItemSpecParam
+from .wallet_vault_item_spec_param import WalletVaultItemSpecParam
+
+__all__ = ["ItemUpsertParams", "WalletVaultItemRequest", "CardVaultItemRequest"]
+
+
+class WalletVaultItemRequest(TypedDict, total=False):
+ id_or_name: Required[str]
+
+ spec: Required[WalletVaultItemSpecParam]
+ """AgentCard wallet.
+
+ Mode (sandbox vs live) is fixed by the deployment's AgentCard credential; there
+ is no per-item test flag. user_id may only reference a user already enrolled by
+ a wallet in this organization.
+ """
+
+ type: Required[Literal["wallet"]]
+
+
+class CardVaultItemRequest(TypedDict, total=False):
+ id_or_name: Required[str]
+
+ spec: Required[CardVaultItemSpecParam]
+ """AgentCard reusable card.
+
+ Each checkout creates an approval-gated authorization for spec.merchant /
+ spec.amount. The card stays ready after each authorization.
+ """
+
+ type: Required[Literal["card"]]
+
+
+ItemUpsertParams: TypeAlias = Union[WalletVaultItemRequest, CardVaultItemRequest]
diff --git a/src/kernel/types/vaults/vault_card_aliases.py b/src/kernel/types/vaults/vault_card_aliases.py
new file mode 100644
index 00000000..149de39f
--- /dev/null
+++ b/src/kernel/types/vaults/vault_card_aliases.py
@@ -0,0 +1,15 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from ..._models import BaseModel
+
+__all__ = ["VaultCardAliases"]
+
+
+class VaultCardAliases(BaseModel):
+ cvc: str
+
+ exp_month: str
+
+ exp_year: str
+
+ number: str
diff --git a/src/kernel/types/vaults/vault_item.py b/src/kernel/types/vaults/vault_item.py
new file mode 100644
index 00000000..8418f0bc
--- /dev/null
+++ b/src/kernel/types/vaults/vault_item.py
@@ -0,0 +1,140 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List, Union, Optional
+from datetime import datetime
+from typing_extensions import Literal, Annotated, TypeAlias
+
+from ..._utils import PropertyInfo
+from ..._models import BaseModel
+from .vault_item_action import VaultItemAction
+from .card_vault_item_spec import CardVaultItemSpec
+from .vault_payment_method import VaultPaymentMethod
+from .card_vault_item_state import CardVaultItemState
+from .wallet_vault_item_spec import WalletVaultItemSpec
+from .wallet_vault_item_state import WalletVaultItemState
+
+__all__ = [
+ "VaultItem",
+ "WalletVaultItem",
+ "WalletVaultItemAvailableExpansion",
+ "WalletVaultItemAvailableOperation",
+ "WalletVaultItemExpanded",
+ "CardVaultItem",
+ "CardVaultItemAvailableExpansion",
+ "CardVaultItemAvailableOperation",
+]
+
+
+class WalletVaultItemAvailableExpansion(BaseModel):
+ """
+ Live data that can currently be requested by passing its type to the item GET expand parameter.
+ """
+
+ description: str
+
+ type: Literal["payment_methods"]
+
+
+class WalletVaultItemAvailableOperation(BaseModel):
+ """An operation that is currently valid for this item.
+
+ Read the description before invoking it through the item operations endpoint.
+ """
+
+ description: str
+
+ type: Literal["authorize"]
+
+
+class WalletVaultItemExpanded(BaseModel):
+ """Live, non-persisted data requested through the item GET expand parameter."""
+
+ payment_methods: Optional[List[VaultPaymentMethod]] = None
+
+
+class WalletVaultItem(BaseModel):
+ id: str
+
+ available_expansions: List[WalletVaultItemAvailableExpansion]
+
+ available_operations: List[WalletVaultItemAvailableOperation]
+
+ created_at: datetime
+
+ key: str
+ """Immutable item key assigned when the item is created."""
+
+ spec: WalletVaultItemSpec
+ """AgentCard wallet.
+
+ Mode (sandbox vs live) is fixed by the deployment's AgentCard credential; there
+ is no per-item test flag. user_id may only reference a user already enrolled by
+ a wallet in this organization.
+ """
+
+ state: WalletVaultItemState
+
+ type: Literal["wallet"]
+
+ updated_at: datetime
+
+ action: Optional[VaultItemAction] = None
+
+ expanded: Optional[WalletVaultItemExpanded] = None
+ """Live, non-persisted data requested through the item GET expand parameter."""
+
+ expires_at: Optional[datetime] = None
+
+
+class CardVaultItemAvailableExpansion(BaseModel):
+ """
+ Live data that can currently be requested by passing its type to the item GET expand parameter.
+ """
+
+ description: str
+
+ type: Literal["payment_methods"]
+
+
+class CardVaultItemAvailableOperation(BaseModel):
+ """An operation that is currently valid for this item.
+
+ Read the description before invoking it through the item operations endpoint.
+ """
+
+ description: str
+
+ type: Literal["authorize"]
+
+
+class CardVaultItem(BaseModel):
+ id: str
+
+ available_expansions: List[CardVaultItemAvailableExpansion]
+
+ available_operations: List[CardVaultItemAvailableOperation]
+
+ created_at: datetime
+
+ key: str
+ """Immutable item key assigned when the item is created."""
+
+ spec: CardVaultItemSpec
+ """AgentCard reusable card.
+
+ Each checkout creates an approval-gated authorization for spec.merchant /
+ spec.amount. The card stays ready after each authorization.
+ """
+
+ state: CardVaultItemState
+
+ type: Literal["card"]
+
+ updated_at: datetime
+
+ action: Optional[VaultItemAction] = None
+
+ expires_at: Optional[datetime] = None
+
+
+VaultItem: TypeAlias = Annotated[Union[WalletVaultItem, CardVaultItem], PropertyInfo(discriminator="type")]
diff --git a/src/kernel/types/vaults/vault_item_action.py b/src/kernel/types/vaults/vault_item_action.py
new file mode 100644
index 00000000..9054447e
--- /dev/null
+++ b/src/kernel/types/vaults/vault_item_action.py
@@ -0,0 +1,66 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Union
+from typing_extensions import Literal, Annotated, TypeAlias
+
+from ..._utils import PropertyInfo
+from ..._models import BaseModel
+
+__all__ = [
+ "VaultItemAction",
+ "LinkOAuthAction",
+ "SpendApprovalAction",
+ "PushApprovalAction",
+ "CollectAction",
+ "MfaAction",
+ "EmbeddedCeremonyAction",
+ "CardEnrollmentAction",
+]
+
+
+class LinkOAuthAction(BaseModel):
+ name: Literal["link_oauth"]
+
+ url: str
+
+
+class SpendApprovalAction(BaseModel):
+ name: Literal["spend_approval"]
+
+ url: str
+
+
+class PushApprovalAction(BaseModel):
+ name: Literal["push_approval"]
+
+
+class CollectAction(BaseModel):
+ name: Literal["collect"]
+
+
+class MfaAction(BaseModel):
+ name: Literal["mfa"]
+
+
+class EmbeddedCeremonyAction(BaseModel):
+ name: Literal["embedded_ceremony"]
+
+
+class CardEnrollmentAction(BaseModel):
+ name: Literal["card_enrollment"]
+
+ url: str
+
+
+VaultItemAction: TypeAlias = Annotated[
+ Union[
+ LinkOAuthAction,
+ SpendApprovalAction,
+ PushApprovalAction,
+ CollectAction,
+ MfaAction,
+ EmbeddedCeremonyAction,
+ CardEnrollmentAction,
+ ],
+ PropertyInfo(discriminator="name"),
+]
diff --git a/src/kernel/types/vaults/vault_item_event.py b/src/kernel/types/vaults/vault_item_event.py
new file mode 100644
index 00000000..2d4098be
--- /dev/null
+++ b/src/kernel/types/vaults/vault_item_event.py
@@ -0,0 +1,21 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Dict, Optional
+from datetime import datetime
+
+from ..._models import BaseModel
+
+__all__ = ["VaultItemEvent"]
+
+
+class VaultItemEvent(BaseModel):
+ id: str
+
+ created_at: datetime
+
+ name: str
+
+ browser_id: Optional[str] = None
+ """Browser session associated with the event, when applicable."""
+
+ data: Optional[Dict[str, object]] = None
diff --git a/src/kernel/types/vaults/vault_payment_method.py b/src/kernel/types/vaults/vault_payment_method.py
new file mode 100644
index 00000000..27f87ad1
--- /dev/null
+++ b/src/kernel/types/vaults/vault_payment_method.py
@@ -0,0 +1,51 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List, Optional
+
+from ..._models import BaseModel
+
+__all__ = ["VaultPaymentMethod", "Capabilities", "CapabilitiesSingleUseCard", "Display"]
+
+
+class CapabilitiesSingleUseCard(BaseModel):
+ eligible: bool
+
+ reasons: List[str]
+
+
+class Capabilities(BaseModel):
+ """Provider-reported advisory capabilities.
+
+ A missing capability is unknown, not ineligible; only eligible=false is an explicit negative signal.
+ """
+
+ single_use_card: Optional[CapabilitiesSingleUseCard] = None
+
+
+class Display(BaseModel):
+ brand: Optional[str] = None
+
+ label: Optional[str] = None
+
+ last4: Optional[str] = None
+
+
+class VaultPaymentMethod(BaseModel):
+ id: str
+
+ capabilities: Capabilities
+ """Provider-reported advisory capabilities.
+
+ A missing capability is unknown, not ineligible; only eligible=false is an
+ explicit negative signal.
+ """
+
+ display: Display
+
+ is_default: bool
+
+ provider: str
+ """Provider that issued this payment-method ID."""
+
+ type: str
+ """Provider-neutral payment-method type normalized to lowercase."""
diff --git a/src/kernel/types/vaults/wallet_vault_item_spec.py b/src/kernel/types/vaults/wallet_vault_item_spec.py
new file mode 100644
index 00000000..03176670
--- /dev/null
+++ b/src/kernel/types/vaults/wallet_vault_item_spec.py
@@ -0,0 +1,47 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Union, Optional
+from typing_extensions import Literal, Annotated, TypeAlias
+
+from ..._utils import PropertyInfo
+from ..._models import BaseModel
+
+__all__ = [
+ "WalletVaultItemSpec",
+ "LinkWalletVaultItemSpec",
+ "LinkWalletVaultItemSpecAuthorization",
+ "LinkWalletVaultItemSpecAuthorizationClient",
+ "AgentCardWalletVaultItemSpec",
+]
+
+
+class LinkWalletVaultItemSpecAuthorizationClient(BaseModel):
+ type: Literal["kernel_managed"]
+
+
+class LinkWalletVaultItemSpecAuthorization(BaseModel):
+ client: LinkWalletVaultItemSpecAuthorizationClient
+
+ method: Literal["oauth"]
+
+
+class LinkWalletVaultItemSpec(BaseModel):
+ authorization: LinkWalletVaultItemSpecAuthorization
+
+ provider: Literal["link"]
+
+
+class AgentCardWalletVaultItemSpec(BaseModel):
+ """AgentCard wallet.
+
+ Mode (sandbox vs live) is fixed by the deployment's AgentCard credential; there is no per-item test flag. user_id may only reference a user already enrolled by a wallet in this organization.
+ """
+
+ provider: Literal["agentcard"]
+
+ user_id: Optional[str] = None
+
+
+WalletVaultItemSpec: TypeAlias = Annotated[
+ Union[LinkWalletVaultItemSpec, AgentCardWalletVaultItemSpec], PropertyInfo(discriminator="provider")
+]
diff --git a/src/kernel/types/vaults/wallet_vault_item_spec_param.py b/src/kernel/types/vaults/wallet_vault_item_spec_param.py
new file mode 100644
index 00000000..dc30e054
--- /dev/null
+++ b/src/kernel/types/vaults/wallet_vault_item_spec_param.py
@@ -0,0 +1,44 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Union
+from typing_extensions import Literal, Required, TypeAlias, TypedDict
+
+__all__ = [
+ "WalletVaultItemSpecParam",
+ "LinkWalletVaultItemSpec",
+ "LinkWalletVaultItemSpecAuthorization",
+ "LinkWalletVaultItemSpecAuthorizationClient",
+ "AgentCardWalletVaultItemSpec",
+]
+
+
+class LinkWalletVaultItemSpecAuthorizationClient(TypedDict, total=False):
+ type: Required[Literal["kernel_managed"]]
+
+
+class LinkWalletVaultItemSpecAuthorization(TypedDict, total=False):
+ client: Required[LinkWalletVaultItemSpecAuthorizationClient]
+
+ method: Required[Literal["oauth"]]
+
+
+class LinkWalletVaultItemSpec(TypedDict, total=False):
+ authorization: Required[LinkWalletVaultItemSpecAuthorization]
+
+ provider: Required[Literal["link"]]
+
+
+class AgentCardWalletVaultItemSpec(TypedDict, total=False):
+ """AgentCard wallet.
+
+ Mode (sandbox vs live) is fixed by the deployment's AgentCard credential; there is no per-item test flag. user_id may only reference a user already enrolled by a wallet in this organization.
+ """
+
+ provider: Required[Literal["agentcard"]]
+
+ user_id: str
+
+
+WalletVaultItemSpecParam: TypeAlias = Union[LinkWalletVaultItemSpec, AgentCardWalletVaultItemSpec]
diff --git a/src/kernel/types/vaults/wallet_vault_item_state.py b/src/kernel/types/vaults/wallet_vault_item_state.py
new file mode 100644
index 00000000..9b76f419
--- /dev/null
+++ b/src/kernel/types/vaults/wallet_vault_item_state.py
@@ -0,0 +1,33 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Union, Optional
+from typing_extensions import Literal, Annotated, TypeAlias
+
+from ..._utils import PropertyInfo
+from ..._models import BaseModel
+
+__all__ = ["WalletVaultItemState", "LinkWalletState", "AgentCardWalletState"]
+
+
+class LinkWalletState(BaseModel):
+ provider: Literal["link"]
+
+ status: Literal["pending_authorization", "connected", "declined", "reconnect_required", "degraded"]
+
+ status_reason: Optional[str] = None
+
+
+class AgentCardWalletState(BaseModel):
+ provider: Literal["agentcard"]
+
+ status: Literal["pending_authorization", "connected", "degraded"]
+
+ status_reason: Optional[str] = None
+
+ user_id: Optional[str] = None
+ """AgentCard user id linked to this wallet. Present once connected."""
+
+
+WalletVaultItemState: TypeAlias = Annotated[
+ Union[LinkWalletState, AgentCardWalletState], PropertyInfo(discriminator="provider")
+]
diff --git a/tests/api_resources/test_browsers.py b/tests/api_resources/test_browsers.py
index 3d0a3eb6..406b0ce8 100644
--- a/tests/api_resources/test_browsers.py
+++ b/tests/api_resources/test_browsers.py
@@ -94,6 +94,12 @@ def test_method_create_with_all_params(self, client: Kernel) -> None:
},
},
timeout_seconds=10,
+ vaults=[
+ {
+ "id": "id",
+ "name": "x",
+ }
+ ],
viewport={
"height": 800,
"width": 1280,
@@ -561,6 +567,12 @@ async def test_method_create_with_all_params(self, async_client: AsyncKernel) ->
},
},
timeout_seconds=10,
+ vaults=[
+ {
+ "id": "id",
+ "name": "x",
+ }
+ ],
viewport={
"height": 800,
"width": 1280,
diff --git a/tests/api_resources/test_vaults.py b/tests/api_resources/test_vaults.py
new file mode 100644
index 00000000..0836a7f8
--- /dev/null
+++ b/tests/api_resources/test_vaults.py
@@ -0,0 +1,335 @@
+# 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 Vault
+from kernel.pagination import SyncOffsetPagination, AsyncOffsetPagination
+
+base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
+
+
+class TestVaults:
+ parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_retrieve(self, client: Kernel) -> None:
+ vault = client.vaults.retrieve(
+ "id_or_name",
+ )
+ assert_matches_type(Vault, vault, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_retrieve(self, client: Kernel) -> None:
+ response = client.vaults.with_raw_response.retrieve(
+ "id_or_name",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ vault = response.parse()
+ assert_matches_type(Vault, vault, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_retrieve(self, client: Kernel) -> None:
+ with client.vaults.with_streaming_response.retrieve(
+ "id_or_name",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ vault = response.parse()
+ assert_matches_type(Vault, vault, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server 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_or_name` but received ''"):
+ client.vaults.with_raw_response.retrieve(
+ "",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_list(self, client: Kernel) -> None:
+ vault = client.vaults.list()
+ assert_matches_type(SyncOffsetPagination[Vault], vault, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_list_with_all_params(self, client: Kernel) -> None:
+ vault = client.vaults.list(
+ limit=1,
+ offset=0,
+ )
+ assert_matches_type(SyncOffsetPagination[Vault], vault, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_list(self, client: Kernel) -> None:
+ response = client.vaults.with_raw_response.list()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ vault = response.parse()
+ assert_matches_type(SyncOffsetPagination[Vault], vault, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_list(self, client: Kernel) -> None:
+ with client.vaults.with_streaming_response.list() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ vault = response.parse()
+ assert_matches_type(SyncOffsetPagination[Vault], vault, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_delete(self, client: Kernel) -> None:
+ vault = client.vaults.delete(
+ "id_or_name",
+ )
+ assert vault is None
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_delete(self, client: Kernel) -> None:
+ response = client.vaults.with_raw_response.delete(
+ "id_or_name",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ vault = response.parse()
+ assert vault is None
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_delete(self, client: Kernel) -> None:
+ with client.vaults.with_streaming_response.delete(
+ "id_or_name",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ vault = response.parse()
+ assert vault is None
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server 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_or_name` but received ''"):
+ client.vaults.with_raw_response.delete(
+ "",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_upsert(self, client: Kernel) -> None:
+ vault = client.vaults.upsert(
+ name="name",
+ )
+ assert_matches_type(Vault, vault, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_upsert(self, client: Kernel) -> None:
+ response = client.vaults.with_raw_response.upsert(
+ name="name",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ vault = response.parse()
+ assert_matches_type(Vault, vault, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_upsert(self, client: Kernel) -> None:
+ with client.vaults.with_streaming_response.upsert(
+ name="name",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ vault = response.parse()
+ assert_matches_type(Vault, vault, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+
+class TestAsyncVaults:
+ parametrize = pytest.mark.parametrize(
+ "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_retrieve(self, async_client: AsyncKernel) -> None:
+ vault = await async_client.vaults.retrieve(
+ "id_or_name",
+ )
+ assert_matches_type(Vault, vault, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_raw_response_retrieve(self, async_client: AsyncKernel) -> None:
+ response = await async_client.vaults.with_raw_response.retrieve(
+ "id_or_name",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ vault = await response.parse()
+ assert_matches_type(Vault, vault, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_streaming_response_retrieve(self, async_client: AsyncKernel) -> None:
+ async with async_client.vaults.with_streaming_response.retrieve(
+ "id_or_name",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ vault = await response.parse()
+ assert_matches_type(Vault, vault, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server 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_or_name` but received ''"):
+ await async_client.vaults.with_raw_response.retrieve(
+ "",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_list(self, async_client: AsyncKernel) -> None:
+ vault = await async_client.vaults.list()
+ assert_matches_type(AsyncOffsetPagination[Vault], vault, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_list_with_all_params(self, async_client: AsyncKernel) -> None:
+ vault = await async_client.vaults.list(
+ limit=1,
+ offset=0,
+ )
+ assert_matches_type(AsyncOffsetPagination[Vault], vault, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_raw_response_list(self, async_client: AsyncKernel) -> None:
+ response = await async_client.vaults.with_raw_response.list()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ vault = await response.parse()
+ assert_matches_type(AsyncOffsetPagination[Vault], vault, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_streaming_response_list(self, async_client: AsyncKernel) -> None:
+ async with async_client.vaults.with_streaming_response.list() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ vault = await response.parse()
+ assert_matches_type(AsyncOffsetPagination[Vault], vault, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_delete(self, async_client: AsyncKernel) -> None:
+ vault = await async_client.vaults.delete(
+ "id_or_name",
+ )
+ assert vault is None
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_raw_response_delete(self, async_client: AsyncKernel) -> None:
+ response = await async_client.vaults.with_raw_response.delete(
+ "id_or_name",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ vault = await response.parse()
+ assert vault is None
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_streaming_response_delete(self, async_client: AsyncKernel) -> None:
+ async with async_client.vaults.with_streaming_response.delete(
+ "id_or_name",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ vault = await response.parse()
+ assert vault is None
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server 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_or_name` but received ''"):
+ await async_client.vaults.with_raw_response.delete(
+ "",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_upsert(self, async_client: AsyncKernel) -> None:
+ vault = await async_client.vaults.upsert(
+ name="name",
+ )
+ assert_matches_type(Vault, vault, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_raw_response_upsert(self, async_client: AsyncKernel) -> None:
+ response = await async_client.vaults.with_raw_response.upsert(
+ name="name",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ vault = await response.parse()
+ assert_matches_type(Vault, vault, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_streaming_response_upsert(self, async_client: AsyncKernel) -> None:
+ async with async_client.vaults.with_streaming_response.upsert(
+ name="name",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ vault = await response.parse()
+ assert_matches_type(Vault, vault, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
diff --git a/tests/api_resources/vaults/__init__.py b/tests/api_resources/vaults/__init__.py
new file mode 100644
index 00000000..fd8019a9
--- /dev/null
+++ b/tests/api_resources/vaults/__init__.py
@@ -0,0 +1 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
diff --git a/tests/api_resources/vaults/test_items.py b/tests/api_resources/vaults/test_items.py
new file mode 100644
index 00000000..9d0f9ec6
--- /dev/null
+++ b/tests/api_resources/vaults/test_items.py
@@ -0,0 +1,1432 @@
+# 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.vaults import (
+ VaultItem,
+ ItemListResponse,
+ ItemEventsResponse,
+)
+
+base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
+
+
+class TestItems:
+ parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_retrieve(self, client: Kernel) -> None:
+ item = client.vaults.items.retrieve(
+ key="x",
+ id_or_name="id_or_name",
+ )
+ assert_matches_type(VaultItem, item, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_retrieve_with_all_params(self, client: Kernel) -> None:
+ item = client.vaults.items.retrieve(
+ key="x",
+ id_or_name="id_or_name",
+ expand=["payment_methods"],
+ wait=0,
+ )
+ assert_matches_type(VaultItem, item, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_retrieve(self, client: Kernel) -> None:
+ response = client.vaults.items.with_raw_response.retrieve(
+ key="x",
+ id_or_name="id_or_name",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ item = response.parse()
+ assert_matches_type(VaultItem, item, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_retrieve(self, client: Kernel) -> None:
+ with client.vaults.items.with_streaming_response.retrieve(
+ key="x",
+ id_or_name="id_or_name",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ item = response.parse()
+ assert_matches_type(VaultItem, item, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server 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_or_name` but received ''"):
+ client.vaults.items.with_raw_response.retrieve(
+ key="x",
+ id_or_name="",
+ )
+
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `key` but received ''"):
+ client.vaults.items.with_raw_response.retrieve(
+ key="",
+ id_or_name="id_or_name",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_update(self, client: Kernel) -> None:
+ item = client.vaults.items.update(
+ key="x",
+ id_or_name="id_or_name",
+ spec={
+ "amount": 1,
+ "context": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
+ "currency": "bFx",
+ "merchant_name": "x",
+ "merchant_url": "https://example.com",
+ "payment_method_id": "x",
+ "provider": "link",
+ "test": True,
+ "wallet": "wallet",
+ },
+ )
+ assert_matches_type(VaultItem, item, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_update_with_all_params(self, client: Kernel) -> None:
+ item = client.vaults.items.update(
+ key="x",
+ id_or_name="id_or_name",
+ spec={
+ "amount": 1,
+ "context": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
+ "currency": "bFx",
+ "merchant_name": "x",
+ "merchant_url": "https://example.com",
+ "payment_method_id": "x",
+ "provider": "link",
+ "test": True,
+ "wallet": "wallet",
+ "expires_at": 0,
+ "line_items": [
+ {
+ "name": "name",
+ "description": "description",
+ "image_url": "image_url",
+ "product_url": "product_url",
+ "quantity": 1,
+ "sku": "sku",
+ "totals": [
+ {
+ "amount": 0,
+ "display_text": "display_text",
+ "type": "type",
+ }
+ ],
+ "unit_amount": 0,
+ "url": "url",
+ }
+ ],
+ "metadata": {"foo": "string"},
+ "totals": [
+ {
+ "amount": 0,
+ "display_text": "display_text",
+ "type": "type",
+ }
+ ],
+ },
+ )
+ assert_matches_type(VaultItem, item, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_update(self, client: Kernel) -> None:
+ response = client.vaults.items.with_raw_response.update(
+ key="x",
+ id_or_name="id_or_name",
+ spec={
+ "amount": 1,
+ "context": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
+ "currency": "bFx",
+ "merchant_name": "x",
+ "merchant_url": "https://example.com",
+ "payment_method_id": "x",
+ "provider": "link",
+ "test": True,
+ "wallet": "wallet",
+ },
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ item = response.parse()
+ assert_matches_type(VaultItem, item, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_update(self, client: Kernel) -> None:
+ with client.vaults.items.with_streaming_response.update(
+ key="x",
+ id_or_name="id_or_name",
+ spec={
+ "amount": 1,
+ "context": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
+ "currency": "bFx",
+ "merchant_name": "x",
+ "merchant_url": "https://example.com",
+ "payment_method_id": "x",
+ "provider": "link",
+ "test": True,
+ "wallet": "wallet",
+ },
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ item = response.parse()
+ assert_matches_type(VaultItem, item, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server 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_or_name` but received ''"):
+ client.vaults.items.with_raw_response.update(
+ key="x",
+ id_or_name="",
+ spec={
+ "amount": 1,
+ "context": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
+ "currency": "bFx",
+ "merchant_name": "x",
+ "merchant_url": "https://example.com",
+ "payment_method_id": "x",
+ "provider": "link",
+ "test": True,
+ "wallet": "wallet",
+ },
+ )
+
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `key` but received ''"):
+ client.vaults.items.with_raw_response.update(
+ key="",
+ id_or_name="id_or_name",
+ spec={
+ "amount": 1,
+ "context": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
+ "currency": "bFx",
+ "merchant_name": "x",
+ "merchant_url": "https://example.com",
+ "payment_method_id": "x",
+ "provider": "link",
+ "test": True,
+ "wallet": "wallet",
+ },
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_list(self, client: Kernel) -> None:
+ item = client.vaults.items.list(
+ "id_or_name",
+ )
+ assert_matches_type(ItemListResponse, item, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_list(self, client: Kernel) -> None:
+ response = client.vaults.items.with_raw_response.list(
+ "id_or_name",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ item = response.parse()
+ assert_matches_type(ItemListResponse, item, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_list(self, client: Kernel) -> None:
+ with client.vaults.items.with_streaming_response.list(
+ "id_or_name",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ item = response.parse()
+ assert_matches_type(ItemListResponse, item, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_path_params_list(self, client: Kernel) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id_or_name` but received ''"):
+ client.vaults.items.with_raw_response.list(
+ "",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_delete(self, client: Kernel) -> None:
+ item = client.vaults.items.delete(
+ key="x",
+ id_or_name="id_or_name",
+ )
+ assert item is None
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_delete(self, client: Kernel) -> None:
+ response = client.vaults.items.with_raw_response.delete(
+ key="x",
+ id_or_name="id_or_name",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ item = response.parse()
+ assert item is None
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_delete(self, client: Kernel) -> None:
+ with client.vaults.items.with_streaming_response.delete(
+ key="x",
+ id_or_name="id_or_name",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ item = response.parse()
+ assert item is None
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server 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_or_name` but received ''"):
+ client.vaults.items.with_raw_response.delete(
+ key="x",
+ id_or_name="",
+ )
+
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `key` but received ''"):
+ client.vaults.items.with_raw_response.delete(
+ key="",
+ id_or_name="id_or_name",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_events(self, client: Kernel) -> None:
+ item = client.vaults.items.events(
+ key="key",
+ id_or_name="id_or_name",
+ )
+ assert_matches_type(ItemEventsResponse, item, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_events_with_all_params(self, client: Kernel) -> None:
+ item = client.vaults.items.events(
+ key="key",
+ id_or_name="id_or_name",
+ after="after",
+ wait=0,
+ )
+ assert_matches_type(ItemEventsResponse, item, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_events(self, client: Kernel) -> None:
+ response = client.vaults.items.with_raw_response.events(
+ key="key",
+ id_or_name="id_or_name",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ item = response.parse()
+ assert_matches_type(ItemEventsResponse, item, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_events(self, client: Kernel) -> None:
+ with client.vaults.items.with_streaming_response.events(
+ key="key",
+ id_or_name="id_or_name",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ item = response.parse()
+ assert_matches_type(ItemEventsResponse, item, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_path_params_events(self, client: Kernel) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id_or_name` but received ''"):
+ client.vaults.items.with_raw_response.events(
+ key="key",
+ id_or_name="",
+ )
+
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `key` but received ''"):
+ client.vaults.items.with_raw_response.events(
+ key="",
+ id_or_name="id_or_name",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_perform_operation(self, client: Kernel) -> None:
+ item = client.vaults.items.perform_operation(
+ key="key",
+ id_or_name="id_or_name",
+ type="authorize",
+ )
+ assert_matches_type(VaultItem, item, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_perform_operation(self, client: Kernel) -> None:
+ response = client.vaults.items.with_raw_response.perform_operation(
+ key="key",
+ id_or_name="id_or_name",
+ type="authorize",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ item = response.parse()
+ assert_matches_type(VaultItem, item, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_perform_operation(self, client: Kernel) -> None:
+ with client.vaults.items.with_streaming_response.perform_operation(
+ key="key",
+ id_or_name="id_or_name",
+ type="authorize",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ item = response.parse()
+ assert_matches_type(VaultItem, item, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_path_params_perform_operation(self, client: Kernel) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id_or_name` but received ''"):
+ client.vaults.items.with_raw_response.perform_operation(
+ key="key",
+ id_or_name="",
+ type="authorize",
+ )
+
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `key` but received ''"):
+ client.vaults.items.with_raw_response.perform_operation(
+ key="",
+ id_or_name="id_or_name",
+ type="authorize",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_upsert_overload_1(self, client: Kernel) -> None:
+ item = client.vaults.items.upsert(
+ key="x",
+ id_or_name="id_or_name",
+ spec={
+ "authorization": {
+ "client": {"type": "kernel_managed"},
+ "method": "oauth",
+ },
+ "provider": "link",
+ },
+ type="wallet",
+ )
+ assert_matches_type(VaultItem, item, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_upsert_with_all_params_overload_1(self, client: Kernel) -> None:
+ item = client.vaults.items.upsert(
+ key="x",
+ id_or_name="id_or_name",
+ spec={
+ "authorization": {
+ "client": {"type": "kernel_managed"},
+ "method": "oauth",
+ },
+ "provider": "link",
+ },
+ type="wallet",
+ )
+ assert_matches_type(VaultItem, item, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_upsert_overload_1(self, client: Kernel) -> None:
+ response = client.vaults.items.with_raw_response.upsert(
+ key="x",
+ id_or_name="id_or_name",
+ spec={
+ "authorization": {
+ "client": {"type": "kernel_managed"},
+ "method": "oauth",
+ },
+ "provider": "link",
+ },
+ type="wallet",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ item = response.parse()
+ assert_matches_type(VaultItem, item, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_upsert_overload_1(self, client: Kernel) -> None:
+ with client.vaults.items.with_streaming_response.upsert(
+ key="x",
+ id_or_name="id_or_name",
+ spec={
+ "authorization": {
+ "client": {"type": "kernel_managed"},
+ "method": "oauth",
+ },
+ "provider": "link",
+ },
+ type="wallet",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ item = response.parse()
+ assert_matches_type(VaultItem, item, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_path_params_upsert_overload_1(self, client: Kernel) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id_or_name` but received ''"):
+ client.vaults.items.with_raw_response.upsert(
+ key="x",
+ id_or_name="",
+ spec={
+ "authorization": {
+ "client": {"type": "kernel_managed"},
+ "method": "oauth",
+ },
+ "provider": "link",
+ },
+ type="wallet",
+ )
+
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `key` but received ''"):
+ client.vaults.items.with_raw_response.upsert(
+ key="",
+ id_or_name="id_or_name",
+ spec={
+ "authorization": {
+ "client": {"type": "kernel_managed"},
+ "method": "oauth",
+ },
+ "provider": "link",
+ },
+ type="wallet",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_upsert_overload_2(self, client: Kernel) -> None:
+ item = client.vaults.items.upsert(
+ key="x",
+ id_or_name="id_or_name",
+ spec={
+ "amount": 1,
+ "context": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
+ "currency": "bFx",
+ "merchant_name": "x",
+ "merchant_url": "https://example.com",
+ "payment_method_id": "x",
+ "provider": "link",
+ "test": True,
+ "wallet": "wallet",
+ },
+ type="card",
+ )
+ assert_matches_type(VaultItem, item, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_upsert_with_all_params_overload_2(self, client: Kernel) -> None:
+ item = client.vaults.items.upsert(
+ key="x",
+ id_or_name="id_or_name",
+ spec={
+ "amount": 1,
+ "context": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
+ "currency": "bFx",
+ "merchant_name": "x",
+ "merchant_url": "https://example.com",
+ "payment_method_id": "x",
+ "provider": "link",
+ "test": True,
+ "wallet": "wallet",
+ "expires_at": 0,
+ "line_items": [
+ {
+ "name": "name",
+ "description": "description",
+ "image_url": "image_url",
+ "product_url": "product_url",
+ "quantity": 1,
+ "sku": "sku",
+ "totals": [
+ {
+ "amount": 0,
+ "display_text": "display_text",
+ "type": "type",
+ }
+ ],
+ "unit_amount": 0,
+ "url": "url",
+ }
+ ],
+ "metadata": {"foo": "string"},
+ "totals": [
+ {
+ "amount": 0,
+ "display_text": "display_text",
+ "type": "type",
+ }
+ ],
+ },
+ type="card",
+ )
+ assert_matches_type(VaultItem, item, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_upsert_overload_2(self, client: Kernel) -> None:
+ response = client.vaults.items.with_raw_response.upsert(
+ key="x",
+ id_or_name="id_or_name",
+ spec={
+ "amount": 1,
+ "context": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
+ "currency": "bFx",
+ "merchant_name": "x",
+ "merchant_url": "https://example.com",
+ "payment_method_id": "x",
+ "provider": "link",
+ "test": True,
+ "wallet": "wallet",
+ },
+ type="card",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ item = response.parse()
+ assert_matches_type(VaultItem, item, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_upsert_overload_2(self, client: Kernel) -> None:
+ with client.vaults.items.with_streaming_response.upsert(
+ key="x",
+ id_or_name="id_or_name",
+ spec={
+ "amount": 1,
+ "context": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
+ "currency": "bFx",
+ "merchant_name": "x",
+ "merchant_url": "https://example.com",
+ "payment_method_id": "x",
+ "provider": "link",
+ "test": True,
+ "wallet": "wallet",
+ },
+ type="card",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ item = response.parse()
+ assert_matches_type(VaultItem, item, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_path_params_upsert_overload_2(self, client: Kernel) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id_or_name` but received ''"):
+ client.vaults.items.with_raw_response.upsert(
+ key="x",
+ id_or_name="",
+ spec={
+ "amount": 1,
+ "context": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
+ "currency": "bFx",
+ "merchant_name": "x",
+ "merchant_url": "https://example.com",
+ "payment_method_id": "x",
+ "provider": "link",
+ "test": True,
+ "wallet": "wallet",
+ },
+ type="card",
+ )
+
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `key` but received ''"):
+ client.vaults.items.with_raw_response.upsert(
+ key="",
+ id_or_name="id_or_name",
+ spec={
+ "amount": 1,
+ "context": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
+ "currency": "bFx",
+ "merchant_name": "x",
+ "merchant_url": "https://example.com",
+ "payment_method_id": "x",
+ "provider": "link",
+ "test": True,
+ "wallet": "wallet",
+ },
+ type="card",
+ )
+
+
+class TestAsyncItems:
+ parametrize = pytest.mark.parametrize(
+ "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_retrieve(self, async_client: AsyncKernel) -> None:
+ item = await async_client.vaults.items.retrieve(
+ key="x",
+ id_or_name="id_or_name",
+ )
+ assert_matches_type(VaultItem, item, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_retrieve_with_all_params(self, async_client: AsyncKernel) -> None:
+ item = await async_client.vaults.items.retrieve(
+ key="x",
+ id_or_name="id_or_name",
+ expand=["payment_methods"],
+ wait=0,
+ )
+ assert_matches_type(VaultItem, item, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_raw_response_retrieve(self, async_client: AsyncKernel) -> None:
+ response = await async_client.vaults.items.with_raw_response.retrieve(
+ key="x",
+ id_or_name="id_or_name",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ item = await response.parse()
+ assert_matches_type(VaultItem, item, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_streaming_response_retrieve(self, async_client: AsyncKernel) -> None:
+ async with async_client.vaults.items.with_streaming_response.retrieve(
+ key="x",
+ id_or_name="id_or_name",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ item = await response.parse()
+ assert_matches_type(VaultItem, item, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server 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_or_name` but received ''"):
+ await async_client.vaults.items.with_raw_response.retrieve(
+ key="x",
+ id_or_name="",
+ )
+
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `key` but received ''"):
+ await async_client.vaults.items.with_raw_response.retrieve(
+ key="",
+ id_or_name="id_or_name",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_update(self, async_client: AsyncKernel) -> None:
+ item = await async_client.vaults.items.update(
+ key="x",
+ id_or_name="id_or_name",
+ spec={
+ "amount": 1,
+ "context": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
+ "currency": "bFx",
+ "merchant_name": "x",
+ "merchant_url": "https://example.com",
+ "payment_method_id": "x",
+ "provider": "link",
+ "test": True,
+ "wallet": "wallet",
+ },
+ )
+ assert_matches_type(VaultItem, item, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_update_with_all_params(self, async_client: AsyncKernel) -> None:
+ item = await async_client.vaults.items.update(
+ key="x",
+ id_or_name="id_or_name",
+ spec={
+ "amount": 1,
+ "context": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
+ "currency": "bFx",
+ "merchant_name": "x",
+ "merchant_url": "https://example.com",
+ "payment_method_id": "x",
+ "provider": "link",
+ "test": True,
+ "wallet": "wallet",
+ "expires_at": 0,
+ "line_items": [
+ {
+ "name": "name",
+ "description": "description",
+ "image_url": "image_url",
+ "product_url": "product_url",
+ "quantity": 1,
+ "sku": "sku",
+ "totals": [
+ {
+ "amount": 0,
+ "display_text": "display_text",
+ "type": "type",
+ }
+ ],
+ "unit_amount": 0,
+ "url": "url",
+ }
+ ],
+ "metadata": {"foo": "string"},
+ "totals": [
+ {
+ "amount": 0,
+ "display_text": "display_text",
+ "type": "type",
+ }
+ ],
+ },
+ )
+ assert_matches_type(VaultItem, item, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_raw_response_update(self, async_client: AsyncKernel) -> None:
+ response = await async_client.vaults.items.with_raw_response.update(
+ key="x",
+ id_or_name="id_or_name",
+ spec={
+ "amount": 1,
+ "context": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
+ "currency": "bFx",
+ "merchant_name": "x",
+ "merchant_url": "https://example.com",
+ "payment_method_id": "x",
+ "provider": "link",
+ "test": True,
+ "wallet": "wallet",
+ },
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ item = await response.parse()
+ assert_matches_type(VaultItem, item, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_streaming_response_update(self, async_client: AsyncKernel) -> None:
+ async with async_client.vaults.items.with_streaming_response.update(
+ key="x",
+ id_or_name="id_or_name",
+ spec={
+ "amount": 1,
+ "context": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
+ "currency": "bFx",
+ "merchant_name": "x",
+ "merchant_url": "https://example.com",
+ "payment_method_id": "x",
+ "provider": "link",
+ "test": True,
+ "wallet": "wallet",
+ },
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ item = await response.parse()
+ assert_matches_type(VaultItem, item, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server 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_or_name` but received ''"):
+ await async_client.vaults.items.with_raw_response.update(
+ key="x",
+ id_or_name="",
+ spec={
+ "amount": 1,
+ "context": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
+ "currency": "bFx",
+ "merchant_name": "x",
+ "merchant_url": "https://example.com",
+ "payment_method_id": "x",
+ "provider": "link",
+ "test": True,
+ "wallet": "wallet",
+ },
+ )
+
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `key` but received ''"):
+ await async_client.vaults.items.with_raw_response.update(
+ key="",
+ id_or_name="id_or_name",
+ spec={
+ "amount": 1,
+ "context": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
+ "currency": "bFx",
+ "merchant_name": "x",
+ "merchant_url": "https://example.com",
+ "payment_method_id": "x",
+ "provider": "link",
+ "test": True,
+ "wallet": "wallet",
+ },
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_list(self, async_client: AsyncKernel) -> None:
+ item = await async_client.vaults.items.list(
+ "id_or_name",
+ )
+ assert_matches_type(ItemListResponse, item, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_raw_response_list(self, async_client: AsyncKernel) -> None:
+ response = await async_client.vaults.items.with_raw_response.list(
+ "id_or_name",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ item = await response.parse()
+ assert_matches_type(ItemListResponse, item, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_streaming_response_list(self, async_client: AsyncKernel) -> None:
+ async with async_client.vaults.items.with_streaming_response.list(
+ "id_or_name",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ item = await response.parse()
+ assert_matches_type(ItemListResponse, item, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_path_params_list(self, async_client: AsyncKernel) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id_or_name` but received ''"):
+ await async_client.vaults.items.with_raw_response.list(
+ "",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_delete(self, async_client: AsyncKernel) -> None:
+ item = await async_client.vaults.items.delete(
+ key="x",
+ id_or_name="id_or_name",
+ )
+ assert item is None
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_raw_response_delete(self, async_client: AsyncKernel) -> None:
+ response = await async_client.vaults.items.with_raw_response.delete(
+ key="x",
+ id_or_name="id_or_name",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ item = await response.parse()
+ assert item is None
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_streaming_response_delete(self, async_client: AsyncKernel) -> None:
+ async with async_client.vaults.items.with_streaming_response.delete(
+ key="x",
+ id_or_name="id_or_name",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ item = await response.parse()
+ assert item is None
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server 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_or_name` but received ''"):
+ await async_client.vaults.items.with_raw_response.delete(
+ key="x",
+ id_or_name="",
+ )
+
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `key` but received ''"):
+ await async_client.vaults.items.with_raw_response.delete(
+ key="",
+ id_or_name="id_or_name",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_events(self, async_client: AsyncKernel) -> None:
+ item = await async_client.vaults.items.events(
+ key="key",
+ id_or_name="id_or_name",
+ )
+ assert_matches_type(ItemEventsResponse, item, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_events_with_all_params(self, async_client: AsyncKernel) -> None:
+ item = await async_client.vaults.items.events(
+ key="key",
+ id_or_name="id_or_name",
+ after="after",
+ wait=0,
+ )
+ assert_matches_type(ItemEventsResponse, item, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_raw_response_events(self, async_client: AsyncKernel) -> None:
+ response = await async_client.vaults.items.with_raw_response.events(
+ key="key",
+ id_or_name="id_or_name",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ item = await response.parse()
+ assert_matches_type(ItemEventsResponse, item, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_streaming_response_events(self, async_client: AsyncKernel) -> None:
+ async with async_client.vaults.items.with_streaming_response.events(
+ key="key",
+ id_or_name="id_or_name",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ item = await response.parse()
+ assert_matches_type(ItemEventsResponse, item, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_path_params_events(self, async_client: AsyncKernel) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id_or_name` but received ''"):
+ await async_client.vaults.items.with_raw_response.events(
+ key="key",
+ id_or_name="",
+ )
+
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `key` but received ''"):
+ await async_client.vaults.items.with_raw_response.events(
+ key="",
+ id_or_name="id_or_name",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_perform_operation(self, async_client: AsyncKernel) -> None:
+ item = await async_client.vaults.items.perform_operation(
+ key="key",
+ id_or_name="id_or_name",
+ type="authorize",
+ )
+ assert_matches_type(VaultItem, item, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_raw_response_perform_operation(self, async_client: AsyncKernel) -> None:
+ response = await async_client.vaults.items.with_raw_response.perform_operation(
+ key="key",
+ id_or_name="id_or_name",
+ type="authorize",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ item = await response.parse()
+ assert_matches_type(VaultItem, item, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_streaming_response_perform_operation(self, async_client: AsyncKernel) -> None:
+ async with async_client.vaults.items.with_streaming_response.perform_operation(
+ key="key",
+ id_or_name="id_or_name",
+ type="authorize",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ item = await response.parse()
+ assert_matches_type(VaultItem, item, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_path_params_perform_operation(self, async_client: AsyncKernel) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id_or_name` but received ''"):
+ await async_client.vaults.items.with_raw_response.perform_operation(
+ key="key",
+ id_or_name="",
+ type="authorize",
+ )
+
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `key` but received ''"):
+ await async_client.vaults.items.with_raw_response.perform_operation(
+ key="",
+ id_or_name="id_or_name",
+ type="authorize",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_upsert_overload_1(self, async_client: AsyncKernel) -> None:
+ item = await async_client.vaults.items.upsert(
+ key="x",
+ id_or_name="id_or_name",
+ spec={
+ "authorization": {
+ "client": {"type": "kernel_managed"},
+ "method": "oauth",
+ },
+ "provider": "link",
+ },
+ type="wallet",
+ )
+ assert_matches_type(VaultItem, item, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_upsert_with_all_params_overload_1(self, async_client: AsyncKernel) -> None:
+ item = await async_client.vaults.items.upsert(
+ key="x",
+ id_or_name="id_or_name",
+ spec={
+ "authorization": {
+ "client": {"type": "kernel_managed"},
+ "method": "oauth",
+ },
+ "provider": "link",
+ },
+ type="wallet",
+ )
+ assert_matches_type(VaultItem, item, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_raw_response_upsert_overload_1(self, async_client: AsyncKernel) -> None:
+ response = await async_client.vaults.items.with_raw_response.upsert(
+ key="x",
+ id_or_name="id_or_name",
+ spec={
+ "authorization": {
+ "client": {"type": "kernel_managed"},
+ "method": "oauth",
+ },
+ "provider": "link",
+ },
+ type="wallet",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ item = await response.parse()
+ assert_matches_type(VaultItem, item, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_streaming_response_upsert_overload_1(self, async_client: AsyncKernel) -> None:
+ async with async_client.vaults.items.with_streaming_response.upsert(
+ key="x",
+ id_or_name="id_or_name",
+ spec={
+ "authorization": {
+ "client": {"type": "kernel_managed"},
+ "method": "oauth",
+ },
+ "provider": "link",
+ },
+ type="wallet",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ item = await response.parse()
+ assert_matches_type(VaultItem, item, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_path_params_upsert_overload_1(self, async_client: AsyncKernel) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id_or_name` but received ''"):
+ await async_client.vaults.items.with_raw_response.upsert(
+ key="x",
+ id_or_name="",
+ spec={
+ "authorization": {
+ "client": {"type": "kernel_managed"},
+ "method": "oauth",
+ },
+ "provider": "link",
+ },
+ type="wallet",
+ )
+
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `key` but received ''"):
+ await async_client.vaults.items.with_raw_response.upsert(
+ key="",
+ id_or_name="id_or_name",
+ spec={
+ "authorization": {
+ "client": {"type": "kernel_managed"},
+ "method": "oauth",
+ },
+ "provider": "link",
+ },
+ type="wallet",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_upsert_overload_2(self, async_client: AsyncKernel) -> None:
+ item = await async_client.vaults.items.upsert(
+ key="x",
+ id_or_name="id_or_name",
+ spec={
+ "amount": 1,
+ "context": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
+ "currency": "bFx",
+ "merchant_name": "x",
+ "merchant_url": "https://example.com",
+ "payment_method_id": "x",
+ "provider": "link",
+ "test": True,
+ "wallet": "wallet",
+ },
+ type="card",
+ )
+ assert_matches_type(VaultItem, item, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_upsert_with_all_params_overload_2(self, async_client: AsyncKernel) -> None:
+ item = await async_client.vaults.items.upsert(
+ key="x",
+ id_or_name="id_or_name",
+ spec={
+ "amount": 1,
+ "context": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
+ "currency": "bFx",
+ "merchant_name": "x",
+ "merchant_url": "https://example.com",
+ "payment_method_id": "x",
+ "provider": "link",
+ "test": True,
+ "wallet": "wallet",
+ "expires_at": 0,
+ "line_items": [
+ {
+ "name": "name",
+ "description": "description",
+ "image_url": "image_url",
+ "product_url": "product_url",
+ "quantity": 1,
+ "sku": "sku",
+ "totals": [
+ {
+ "amount": 0,
+ "display_text": "display_text",
+ "type": "type",
+ }
+ ],
+ "unit_amount": 0,
+ "url": "url",
+ }
+ ],
+ "metadata": {"foo": "string"},
+ "totals": [
+ {
+ "amount": 0,
+ "display_text": "display_text",
+ "type": "type",
+ }
+ ],
+ },
+ type="card",
+ )
+ assert_matches_type(VaultItem, item, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_raw_response_upsert_overload_2(self, async_client: AsyncKernel) -> None:
+ response = await async_client.vaults.items.with_raw_response.upsert(
+ key="x",
+ id_or_name="id_or_name",
+ spec={
+ "amount": 1,
+ "context": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
+ "currency": "bFx",
+ "merchant_name": "x",
+ "merchant_url": "https://example.com",
+ "payment_method_id": "x",
+ "provider": "link",
+ "test": True,
+ "wallet": "wallet",
+ },
+ type="card",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ item = await response.parse()
+ assert_matches_type(VaultItem, item, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_streaming_response_upsert_overload_2(self, async_client: AsyncKernel) -> None:
+ async with async_client.vaults.items.with_streaming_response.upsert(
+ key="x",
+ id_or_name="id_or_name",
+ spec={
+ "amount": 1,
+ "context": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
+ "currency": "bFx",
+ "merchant_name": "x",
+ "merchant_url": "https://example.com",
+ "payment_method_id": "x",
+ "provider": "link",
+ "test": True,
+ "wallet": "wallet",
+ },
+ type="card",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ item = await response.parse()
+ assert_matches_type(VaultItem, item, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_path_params_upsert_overload_2(self, async_client: AsyncKernel) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id_or_name` but received ''"):
+ await async_client.vaults.items.with_raw_response.upsert(
+ key="x",
+ id_or_name="",
+ spec={
+ "amount": 1,
+ "context": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
+ "currency": "bFx",
+ "merchant_name": "x",
+ "merchant_url": "https://example.com",
+ "payment_method_id": "x",
+ "provider": "link",
+ "test": True,
+ "wallet": "wallet",
+ },
+ type="card",
+ )
+
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `key` but received ''"):
+ await async_client.vaults.items.with_raw_response.upsert(
+ key="",
+ id_or_name="id_or_name",
+ spec={
+ "amount": 1,
+ "context": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
+ "currency": "bFx",
+ "merchant_name": "x",
+ "merchant_url": "https://example.com",
+ "payment_method_id": "x",
+ "provider": "link",
+ "test": True,
+ "wallet": "wallet",
+ },
+ type="card",
+ )