From 8b22180766c592d1480e26fc781ffd5e1b623051 Mon Sep 17 00:00:00 2001 From: "kernel-internal[bot]" <260533166+kernel-internal[bot]@users.noreply.github.com> Date: Thu, 17 Sep 2026 19:57:57 +0000 Subject: [PATCH 1/4] feat: Expose organization-wide concurrent browser capacity Stainless-Generated-From: 3cbbdadb5bad3b3d3192976206eaf515db7a1263 --- src/kernel/resources/organization/limits.py | 10 ++++++++-- src/kernel/types/organization/org_limits.py | 13 +++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/kernel/resources/organization/limits.py b/src/kernel/resources/organization/limits.py index 9dcd9dbb..5654164b 100644 --- a/src/kernel/resources/organization/limits.py +++ b/src/kernel/resources/organization/limits.py @@ -55,7 +55,10 @@ def retrieve( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> OrgLimits: - """Get the organization's effective limits and managed auth and vault usage.""" + """ + Get the organization's effective limits and current concurrency, managed auth, + and vault usage. + """ return self._get( "/org/limits", options=make_request_options( @@ -138,7 +141,10 @@ async def retrieve( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> OrgLimits: - """Get the organization's effective limits and managed auth and vault usage.""" + """ + Get the organization's effective limits and current concurrency, managed auth, + and vault usage. + """ return await self._get( "/org/limits", options=make_request_options( diff --git a/src/kernel/types/organization/org_limits.py b/src/kernel/types/organization/org_limits.py index 4e24a5f0..fbe26e76 100644 --- a/src/kernel/types/organization/org_limits.py +++ b/src/kernel/types/organization/org_limits.py @@ -15,6 +15,19 @@ class OrgLimits(BaseModel): remaining capacity before a create is rejected with 403 insufficient_plan. """ + concurrent_sessions_available: Optional[int] = None + """Number of concurrent browser slots currently available to the organization. + + This is the effective concurrency limit minus active on-demand sessions and + browser pool reservations, floored at zero. Null when usage cannot be read. + """ + + concurrent_sessions_used: Optional[int] = None + """ + Current organization-wide concurrent browser usage, including active on-demand + sessions and browser pool reservations. Null when usage cannot be read. + """ + max_auth_connections: Optional[int] = None """Maximum managed auth connections the organization's plan allows. From 1a408c41c0fd043ff69187f7d62bc721f9e5f867 Mon Sep 17 00:00:00 2001 From: "kernel-internal[bot]" <260533166+kernel-internal[bot]@users.noreply.github.com> Date: Thu, 17 Sep 2026 21:07:10 +0000 Subject: [PATCH 2/4] feat: Preserve credential field order Stainless-Generated-From: 0df566e7c79bb73166acc226effc1c9f331264be --- src/kernel/resources/vaults/items.py | 8 +- .../credential_vault_field_definition.py | 3 + .../credential_vault_field_input_param.py | 3 + .../credential_vault_item_request_param.py | 4 +- .../vaults/credential_vault_item_spec.py | 7 +- .../credential_vault_item_spec_input_param.py | 11 +- src/kernel/types/vaults/item_upsert_params.py | 4 +- tests/api_resources/vaults/test_items.py | 104 +++++++++++++++--- 8 files changed, 119 insertions(+), 25 deletions(-) diff --git a/src/kernel/resources/vaults/items.py b/src/kernel/resources/vaults/items.py index 8c720ee5..a9058c09 100644 --- a/src/kernel/resources/vaults/items.py +++ b/src/kernel/resources/vaults/items.py @@ -757,7 +757,9 @@ def upsert( Args: spec: Credential fields are for login and other non-payment credentials. Do not store, collect, or fill credit card data in credential items. Use wallet and card item - types for credit cards and payment checkout instead. + types for credit cards and payment checkout instead. Field order is preserved in + the user-facing collection form, so list fields in the same top-to-bottom order + as the website. extra_headers: Send extra headers @@ -1528,7 +1530,9 @@ async def upsert( Args: spec: Credential fields are for login and other non-payment credentials. Do not store, collect, or fill credit card data in credential items. Use wallet and card item - types for credit cards and payment checkout instead. + types for credit cards and payment checkout instead. Field order is preserved in + the user-facing collection form, so list fields in the same top-to-bottom order + as the website. extra_headers: Send extra headers diff --git a/src/kernel/types/vaults/credential_vault_field_definition.py b/src/kernel/types/vaults/credential_vault_field_definition.py index 9350813b..0ea64ec7 100644 --- a/src/kernel/types/vaults/credential_vault_field_definition.py +++ b/src/kernel/types/vaults/credential_vault_field_definition.py @@ -7,6 +7,9 @@ class CredentialVaultFieldDefinition(BaseModel): + name: str + """Stable field name used to key values, updates, and browser fills.""" + required: bool """Whether a nonempty value is required for readiness and form submission.""" diff --git a/src/kernel/types/vaults/credential_vault_field_input_param.py b/src/kernel/types/vaults/credential_vault_field_input_param.py index 2cf68978..c5795ce1 100644 --- a/src/kernel/types/vaults/credential_vault_field_input_param.py +++ b/src/kernel/types/vaults/credential_vault_field_input_param.py @@ -10,6 +10,9 @@ class CredentialVaultFieldInputParam(TypedDict, total=False): + name: Required[str] + """Unique stable field name used to key values, updates, and browser fills.""" + type: Required[CredentialVaultFieldType] """ Text, email, and password have form inputs; totp does not and is omitted from diff --git a/src/kernel/types/vaults/credential_vault_item_request_param.py b/src/kernel/types/vaults/credential_vault_item_request_param.py index 579d7a0b..169af036 100644 --- a/src/kernel/types/vaults/credential_vault_item_request_param.py +++ b/src/kernel/types/vaults/credential_vault_item_request_param.py @@ -30,7 +30,9 @@ class CredentialVaultItemRequestParam(TypedDict, total=False): """Credential fields are for login and other non-payment credentials. Do not store, collect, or fill credit card data in credential items. Use wallet - and card item types for credit cards and payment checkout instead. + and card item types for credit cards and payment checkout instead. Field order + is preserved in the user-facing collection form, so list fields in the same + top-to-bottom order as the website. """ type: Required[Literal["credential"]] diff --git a/src/kernel/types/vaults/credential_vault_item_spec.py b/src/kernel/types/vaults/credential_vault_item_spec.py index e953f416..307d2b25 100644 --- a/src/kernel/types/vaults/credential_vault_item_spec.py +++ b/src/kernel/types/vaults/credential_vault_item_spec.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 List, Optional from ..._models import BaseModel from .credential_vault_field_definition import CredentialVaultFieldDefinition @@ -9,7 +9,10 @@ class CredentialVaultItemSpec(BaseModel): - fields: Dict[str, CredentialVaultFieldDefinition] + fields: List[CredentialVaultFieldDefinition] + """ + Ordered field definitions rendered in this order by credential collection forms. + """ description: Optional[str] = None """ diff --git a/src/kernel/types/vaults/credential_vault_item_spec_input_param.py b/src/kernel/types/vaults/credential_vault_item_spec_input_param.py index a0e8850a..ab4eaee8 100644 --- a/src/kernel/types/vaults/credential_vault_item_spec_input_param.py +++ b/src/kernel/types/vaults/credential_vault_item_spec_input_param.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import Dict +from typing import Iterable from typing_extensions import Required, TypedDict from .credential_vault_field_input_param import CredentialVaultFieldInputParam @@ -13,10 +13,15 @@ class CredentialVaultItemSpecInputParam(TypedDict, total=False): """Credential fields are for login and other non-payment credentials. - Do not store, collect, or fill credit card data in credential items. Use wallet and card item types for credit cards and payment checkout instead. + Do not store, collect, or fill credit card data in credential items. Use wallet and card item types for credit cards and payment checkout instead. Field order is preserved in the user-facing collection form, so list fields in the same top-to-bottom order as the website. """ - fields: Required[Dict[str, CredentialVaultFieldInputParam]] + fields: Required[Iterable[CredentialVaultFieldInputParam]] + """Ordered field definitions. + + Use the website's top-to-bottom field order; the collection form renders this + order unchanged. + """ description: str """ diff --git a/src/kernel/types/vaults/item_upsert_params.py b/src/kernel/types/vaults/item_upsert_params.py index 5890280a..4e4799dd 100644 --- a/src/kernel/types/vaults/item_upsert_params.py +++ b/src/kernel/types/vaults/item_upsert_params.py @@ -194,7 +194,9 @@ class CredentialVaultItemRequest(TypedDict, total=False): """Credential fields are for login and other non-payment credentials. Do not store, collect, or fill credit card data in credential items. Use wallet - and card item types for credit cards and payment checkout instead. + and card item types for credit cards and payment checkout instead. Field order + is preserved in the user-facing collection form, so list fields in the same + top-to-bottom order as the website. """ type: Required[Literal["credential"]] diff --git a/tests/api_resources/vaults/test_items.py b/tests/api_resources/vaults/test_items.py index b80631eb..75e84e15 100644 --- a/tests/api_resources/vaults/test_items.py +++ b/tests/api_resources/vaults/test_items.py @@ -1144,7 +1144,14 @@ def test_method_upsert_overload_3(self, client: Kernel) -> None: item = client.vaults.items.upsert( key="x", id_or_name="id_or_name", - spec={"fields": {"foo": {"type": "text"}}}, + spec={ + "fields": [ + { + "name": "name", + "type": "text", + } + ] + }, type="credential", ) assert_matches_type(VaultItem, item, path=["response"]) @@ -1156,14 +1163,15 @@ def test_method_upsert_with_all_params_overload_3(self, client: Kernel) -> None: key="x", id_or_name="id_or_name", spec={ - "fields": { - "foo": { + "fields": [ + { + "name": "name", "type": "text", "required": True, "sensitive": True, "value": "x", } - }, + ], "description": "description", }, type="credential", @@ -1176,7 +1184,14 @@ def test_raw_response_upsert_overload_3(self, client: Kernel) -> None: response = client.vaults.items.with_raw_response.upsert( key="x", id_or_name="id_or_name", - spec={"fields": {"foo": {"type": "text"}}}, + spec={ + "fields": [ + { + "name": "name", + "type": "text", + } + ] + }, type="credential", ) @@ -1191,7 +1206,14 @@ def test_streaming_response_upsert_overload_3(self, client: Kernel) -> None: with client.vaults.items.with_streaming_response.upsert( key="x", id_or_name="id_or_name", - spec={"fields": {"foo": {"type": "text"}}}, + spec={ + "fields": [ + { + "name": "name", + "type": "text", + } + ] + }, type="credential", ) as response: assert not response.is_closed @@ -1209,7 +1231,14 @@ def test_path_params_upsert_overload_3(self, client: Kernel) -> None: client.vaults.items.with_raw_response.upsert( key="x", id_or_name="", - spec={"fields": {"foo": {"type": "text"}}}, + spec={ + "fields": [ + { + "name": "name", + "type": "text", + } + ] + }, type="credential", ) @@ -1217,7 +1246,14 @@ def test_path_params_upsert_overload_3(self, client: Kernel) -> None: client.vaults.items.with_raw_response.upsert( key="", id_or_name="id_or_name", - spec={"fields": {"foo": {"type": "text"}}}, + spec={ + "fields": [ + { + "name": "name", + "type": "text", + } + ] + }, type="credential", ) @@ -2349,7 +2385,14 @@ async def test_method_upsert_overload_3(self, async_client: AsyncKernel) -> None item = await async_client.vaults.items.upsert( key="x", id_or_name="id_or_name", - spec={"fields": {"foo": {"type": "text"}}}, + spec={ + "fields": [ + { + "name": "name", + "type": "text", + } + ] + }, type="credential", ) assert_matches_type(VaultItem, item, path=["response"]) @@ -2361,14 +2404,15 @@ async def test_method_upsert_with_all_params_overload_3(self, async_client: Asyn key="x", id_or_name="id_or_name", spec={ - "fields": { - "foo": { + "fields": [ + { + "name": "name", "type": "text", "required": True, "sensitive": True, "value": "x", } - }, + ], "description": "description", }, type="credential", @@ -2381,7 +2425,14 @@ async def test_raw_response_upsert_overload_3(self, async_client: AsyncKernel) - response = await async_client.vaults.items.with_raw_response.upsert( key="x", id_or_name="id_or_name", - spec={"fields": {"foo": {"type": "text"}}}, + spec={ + "fields": [ + { + "name": "name", + "type": "text", + } + ] + }, type="credential", ) @@ -2396,7 +2447,14 @@ async def test_streaming_response_upsert_overload_3(self, async_client: AsyncKer async with async_client.vaults.items.with_streaming_response.upsert( key="x", id_or_name="id_or_name", - spec={"fields": {"foo": {"type": "text"}}}, + spec={ + "fields": [ + { + "name": "name", + "type": "text", + } + ] + }, type="credential", ) as response: assert not response.is_closed @@ -2414,7 +2472,14 @@ async def test_path_params_upsert_overload_3(self, async_client: AsyncKernel) -> await async_client.vaults.items.with_raw_response.upsert( key="x", id_or_name="", - spec={"fields": {"foo": {"type": "text"}}}, + spec={ + "fields": [ + { + "name": "name", + "type": "text", + } + ] + }, type="credential", ) @@ -2422,6 +2487,13 @@ async def test_path_params_upsert_overload_3(self, async_client: AsyncKernel) -> await async_client.vaults.items.with_raw_response.upsert( key="", id_or_name="id_or_name", - spec={"fields": {"foo": {"type": "text"}}}, + spec={ + "fields": [ + { + "name": "name", + "type": "text", + } + ] + }, type="credential", ) From 569a604ad58c278c83bda5068c8a6080334d085f Mon Sep 17 00:00:00 2001 From: "kernel-internal[bot]" <260533166+kernel-internal[bot]@users.noreply.github.com> Date: Thu, 17 Sep 2026 21:32:13 +0000 Subject: [PATCH 3/4] feat: Accept opaque AgentCard vaulted card IDs Stainless-Generated-From: 77ed6712c80370958baad94c48aa88b305a33690 --- src/kernel/types/vaults/card_vault_item_spec.py | 5 +++-- src/kernel/types/vaults/card_vault_item_spec_param.py | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/kernel/types/vaults/card_vault_item_spec.py b/src/kernel/types/vaults/card_vault_item_spec.py index 0bb0b77a..0c73d9bf 100644 --- a/src/kernel/types/vaults/card_vault_item_spec.py +++ b/src/kernel/types/vaults/card_vault_item_spec.py @@ -113,9 +113,10 @@ class AgentCardCardVaultItemSpec(BaseModel): """Wallet item key used to authorize checkouts.""" card_id: Optional[str] = None - """AgentCard vaulted card to pay with. + """Opaque card ID returned by AgentCard for a card in the connected wallet. - Omitted, the cardholder picks on the approval screen. + Pass it through unchanged without assuming a prefix or format. Omitted, the + cardholder picks on the approval screen. """ diff --git a/src/kernel/types/vaults/card_vault_item_spec_param.py b/src/kernel/types/vaults/card_vault_item_spec_param.py index a1680703..7172d066 100644 --- a/src/kernel/types/vaults/card_vault_item_spec_param.py +++ b/src/kernel/types/vaults/card_vault_item_spec_param.py @@ -112,9 +112,10 @@ class AgentCardCardVaultItemSpec(TypedDict, total=False): """Wallet item key used to authorize checkouts.""" card_id: str - """AgentCard vaulted card to pay with. + """Opaque card ID returned by AgentCard for a card in the connected wallet. - Omitted, the cardholder picks on the approval screen. + Pass it through unchanged without assuming a prefix or format. Omitted, the + cardholder picks on the approval screen. """ From 79fa360ccad3a8403ce45b4694dee6ddfb47f04e Mon Sep 17 00:00:00 2001 From: "kernel-internal[bot]" <260533166+kernel-internal[bot]@users.noreply.github.com> Date: Thu, 17 Sep 2026 21:36:54 +0000 Subject: [PATCH 4/4] release: 0.109.0 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 9 +++++++++ pyproject.toml | 2 +- src/kernel/_version.py | 2 +- 4 files changed, 12 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 3e05ae56..3ca49358 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.108.0" + ".": "0.109.0" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 1417baaa..6d7f91fb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # Changelog +## [0.109.0](https://github.com/kernel/kernel-python-sdk/compare/v0.108.0...v0.109.0) (2026-09-17) + + +### Features + +* Accept opaque AgentCard vaulted card IDs ([569a604](https://github.com/kernel/kernel-python-sdk/commit/569a604ad58c278c83bda5068c8a6080334d085f)) +* Expose organization-wide concurrent browser capacity ([8b22180](https://github.com/kernel/kernel-python-sdk/commit/8b22180766c592d1480e26fc781ffd5e1b623051)) +* Preserve credential field order ([1a408c4](https://github.com/kernel/kernel-python-sdk/commit/1a408c41c0fd043ff69187f7d62bc721f9e5f867)) + ## [0.108.0](https://github.com/kernel/kernel-python-sdk/compare/v0.107.0...v0.108.0) (2026-09-17) diff --git a/pyproject.toml b/pyproject.toml index 3a9c0dee..e98679a6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "kernel" -version = "0.108.0" +version = "0.109.0" description = "The official Python library for the kernel API" dynamic = ["readme"] license = "Apache-2.0" diff --git a/src/kernel/_version.py b/src/kernel/_version.py index 5c651d4a..a6550577 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.108.0" # x-release-please-version +__version__ = "0.109.0" # x-release-please-version