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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
".": "0.121.0"
".": "0.122.0"
}
2 changes: 1 addition & 1 deletion .stats.yml
Original file line number Diff line number Diff line change
@@ -1 +1 @@
configured_endpoints: 174
configured_endpoints: 175
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
# Changelog

## [0.122.0](https://github.com/kernel/kernel-node-sdk/compare/v0.121.0...v0.122.0) (2026-10-09)


### Features

* Accept client-encrypted credential values in vault items ([78ee783](https://github.com/kernel/kernel-node-sdk/commit/78ee783d057d99807cb2693a017d22714113b94e))
* Add feature-gated Korean ISP proxies ([96d63e2](https://github.com/kernel/kernel-node-sdk/commit/96d63e2d31b3ee1b3d65d5056db49f58705f96ef))
* Describe vault fill as safe to retry ([b96e6ca](https://github.com/kernel/kernel-node-sdk/commit/b96e6cadb4decdbb9f2618853b1f571aa5af7f2b))
* Infer a challenge result for unobserved captcha providers in the relay ([84022be](https://github.com/kernel/kernel-node-sdk/commit/84022be96b336b7f43a8e89293b8c72985ddbbbe))
* Support proxy routes in browser pools ([e5b2ffc](https://github.com/kernel/kernel-node-sdk/commit/e5b2ffc07188d09ca6b04c253b5daf394aac7fbd))

## [0.121.0](https://github.com/kernel/kernel-node-sdk/compare/v0.120.0...v0.121.0) (2026-10-07)


Expand Down
2 changes: 2 additions & 0 deletions api.md
Original file line number Diff line number Diff line change
Expand Up @@ -492,12 +492,14 @@ Methods:
Types:

- <code><a href="./src/resources/vaults/vaults.ts">Vault</a></code>
- <code><a href="./src/resources/vaults/vaults.ts">VaultEncryptionKey</a></code>

Methods:

- <code title="get /vaults/{id_or_name}">client.vaults.<a href="./src/resources/vaults/vaults.ts">retrieve</a>(idOrName) -> Vault</code>
- <code title="get /vaults">client.vaults.<a href="./src/resources/vaults/vaults.ts">list</a>({ ...params }) -> VaultsOffsetPagination</code>
- <code title="delete /vaults/{id_or_name}">client.vaults.<a href="./src/resources/vaults/vaults.ts">delete</a>(idOrName) -> void</code>
- <code title="get /vaults/{id_or_name}/encryption_key">client.vaults.<a href="./src/resources/vaults/vaults.ts">retrieveEncryptionKey</a>(idOrName) -> VaultEncryptionKey</code>
- <code title="post /vaults">client.vaults.<a href="./src/resources/vaults/vaults.ts">upsert</a>({ ...params }) -> Vault</code>

## Items
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@onkernel/sdk",
"version": "0.121.0",
"version": "0.122.0",
"description": "The official TypeScript library for the Kernel API",
"author": "Kernel <>",
"types": "dist/index.d.ts",
Expand Down
2 changes: 2 additions & 0 deletions src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,7 @@ import {
import { Telemetry } from './resources/telemetry/telemetry';
import {
Vault,
VaultEncryptionKey,
VaultListParams,
VaultUpsertParams,
Vaults,
Expand Down Expand Up @@ -1313,6 +1314,7 @@ export declare namespace Kernel {
export {
Vaults as Vaults,
type Vault as Vault,
type VaultEncryptionKey as VaultEncryptionKey,
type VaultsOffsetPagination as VaultsOffsetPagination,
type VaultListParams as VaultListParams,
type VaultUpsertParams as VaultUpsertParams,
Expand Down
12 changes: 8 additions & 4 deletions src/resources/browser-pools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -585,7 +585,9 @@ export interface BrowserPoolCreateParams {
name?: string;

/**
* Network configuration applied to browsers in this pool.
* Network configuration applied to browsers in this pool. Proxy routes require
* proxy-v3; the pool will not provision browsers through Envoy if proxy-v3 is
* unavailable.
*/
network?: BrowsersAPI.BrowserNetworkConfig;

Expand Down Expand Up @@ -857,9 +859,11 @@ export interface BrowserPoolUpdateParams {
/**
* If provided, replaces the pool's network configuration. Omit to leave the
* existing configuration unchanged; an empty object ({}) removes it, while
* network: {private_hosts: []} sets an explicit empty list. Only applied to
* browsers created in the pool after the update; browsers already in the pool keep
* their configuration until discarded (see discard_all_idle).
* network: {private_hosts: []} or network: {proxy_routes: []} sets an explicit
* empty list. Proxy routes require proxy-v3; the pool will not provision browsers
* through Envoy if proxy-v3 is unavailable. Only applied to browsers created in
* the pool after the update; browsers already in the pool keep their configuration
* until discarded (see discard_all_idle).
*/
network?: BrowsersAPI.BrowserNetworkConfig;

Expand Down
55 changes: 29 additions & 26 deletions src/resources/browsers/browsers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -379,8 +379,9 @@ export interface BrowserNetworkConfig {
* Enforced at Kernel's egress proxy only: destinations in private_hosts, and
* processes in the browser VM that do not use the browser's proxy, are not
* filtered, and Kernel's own control traffic is always allowed. Can be replaced or
* removed while the session runs with PATCH /browsers/{id_or_name}. Requires proxy
* v3. Not supported on browser pools.
* removed while the session runs with PATCH /browsers/{id_or_name}, but not added
* to a browser created without one. Requires proxy v3. Not supported on browser
* pools.
*/
allowed_hosts?: Array<string>;

Expand Down Expand Up @@ -411,20 +412,20 @@ export interface BrowserNetworkConfig {
private_hosts?: Array<string>;

/**
* Per-destination proxy routes for a browser session. After setup, a destination
* hostname is matched against every route's hosts, regardless of port; route order
* does not matter. An exact hostname beats a wildcard, and a longer wildcard
* suffix beats a shorter one (for a.b.example.com: "a.b.example.com" >
* "_.b.example.com" > "_.example.com"). A host pattern may appear in only one
* route. "\*.example.com" matches subdomains only, not example.com. A matched
* request selects the route's proxy instead of the session's top-level proxy
* (including mode: direct); the route proxy's own bypass_hosts still apply. If the
* route proxy becomes unavailable, matched requests fail closed without falling
* back. Requests that match no route use the session's default egress from the
* top-level proxy field (or the browser default when proxy is omitted: stealth
* proxy or direct egress). Routes take effect once the session is created;
* start_url and other traffic during browser setup use the top-level proxy.
* Setting routes requires proxy v3. Not supported on browser pools.
* Per-destination proxy routes for a browser session. A destination hostname is
* matched against every route's hosts, regardless of port; route order does not
* matter. An exact hostname beats a wildcard, and a longer wildcard suffix beats a
* shorter one (for a.b.example.com: "a.b.example.com" > "_.b.example.com" >
* "_.example.com"). A host pattern may appear in only one route. "\*.example.com"
* matches subdomains only, not example.com. A matched request selects the route's
* proxy instead of the session's top-level proxy (including mode: direct); the
* route proxy's own bypass_hosts still apply. If the route proxy becomes
* unavailable, matched requests fail closed without falling back. Requests that
* match no route use the session's default egress from the top-level proxy field
* (or the browser default when proxy is omitted: stealth proxy or direct egress).
* Routes apply from the start of the session, including to start_url and other
* traffic during browser setup. Setting routes requires proxy v3. Browser pools
* also support these routes.
*/
proxy_routes?: Array<BrowserNetworkConfig.ProxyRoute>;
}
Expand Down Expand Up @@ -464,16 +465,18 @@ export namespace BrowserNetworkConfig {
export interface BrowserNetworkUpdate {
/**
* Replaces the session's egress allowlist, using the same entry rules as
* network.allowed_hosts on create. Omit to leave the allowlist unchanged, or set
* to null to remove it and return to unfiltered egress; an empty list is invalid.
* The new list applies without restarting the browser: new requests to
* destinations it no longer allows are refused within a few seconds, and open
* connections to them are closed within about 30 seconds, or up to 10 minutes
* during a Kernel deploy. Connections to destinations it still allows, such as
* WebSockets, stay open. A start_url in the same request must be allowed by the
* updated list, and is loaded only after the list takes effect. Requires a browser
* created with proxy v3, and not supported on pooled browsers. If the request
* fails, retry it: the new list may already apply to some requests.
* network.allowed_hosts on create. Only an allowlist the browser was created with
* can be changed: a browser created without one can't be given one, and an
* allowlist removed with null can't be added back. Omit to leave the allowlist
* unchanged, or set to null to remove it and return to unfiltered egress; an empty
* list is invalid. The new list applies without restarting the browser: new
* requests to destinations it no longer allows are refused within a few seconds,
* and open connections to them are closed within about 30 seconds, or up to 10
* minutes during a Kernel deploy. Connections to destinations it still allows,
* such as WebSockets, stay open. A start_url in the same request must be allowed
* by the updated list, and is loaded only after the list takes effect. Requires a
* browser created with proxy v3, and not supported on pooled browsers. If the
* request fails, retry it: the new list may already apply to some requests.
*/
allowed_hosts?: Array<string> | null;
}
Expand Down
143 changes: 111 additions & 32 deletions src/resources/browsers/telemetry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -194,15 +194,19 @@ export namespace BrowserCallStack {
}

/**
* A visible captcha challenge reached a terminal outcome.
* A captcha challenge reached an observed or inferred terminal outcome.
*/
export interface BrowserCaptchaChallengeResultEvent {
category: 'captcha';

/**
* Per-challenge payload. This event is emitted once per challenge and determines
* its overall outcome; captcha_solve_started and captcha_solve_result describe
* individual tasks and may occur multiple times within the challenge.
* An observed challenge emits one outcome across any number of solver tasks. For
* eligible providers without a widget observer, each successful token task emits
* an inferred solved result instead; multiple such results may belong to one
* challenge. Failed tasks and image_challenge rounds produce no inferred result.
* Exactly one of challenge_id or task_id is present: challenge_id on an observed
* result, task_id on an inferred one. A challenge whose tasks all fail produces
* task events only, so consumers fall back to captcha_solve_result for it.
*/
data: BrowserCaptchaChallengeResultEvent.Data;

Expand All @@ -226,15 +230,17 @@ export interface BrowserCaptchaChallengeResultEvent {

export namespace BrowserCaptchaChallengeResultEvent {
/**
* Per-challenge payload. This event is emitted once per challenge and determines
* its overall outcome; captcha_solve_started and captcha_solve_result describe
* individual tasks and may occur multiple times within the challenge.
* An observed challenge emits one outcome across any number of solver tasks. For
* eligible providers without a widget observer, each successful token task emits
* an inferred solved result instead; multiple such results may belong to one
* challenge. Failed tasks and image_challenge rounds produce no inferred result.
* Exactly one of challenge_id or task_id is present: challenge_id on an observed
* result, task_id on an inferred one. A challenge whose tasks all fail produces
* task events only, so consumers fall back to captcha_solve_result for it.
*/
export interface Data {
/**
* Captcha kind. Enterprise reCAPTCHA variants are grouped into their version
* bucket (recaptcha_v2 or recaptcha_v3), press-and-hold challenges use
* press_and_hold, and unlisted kinds use other.
* @deprecated Deprecated: use captcha_provider.
*/
captcha_type:
| 'hcaptcha'
Expand All @@ -245,34 +251,67 @@ export namespace BrowserCaptchaChallengeResultEvent {
| 'press_and_hold'
| 'other';

/**
* Wall-clock duration from the challenge appearing to its terminal outcome,
* covering every solver attempt in between. For an inferred result, the duration
* of its solver task.
*/
duration_ms: number;

/**
* Terminal outcome of a challenge. solved: the page observed the challenge clear
* after a solver attempt, or an inferred result reports a token for the whole
* widget without page observation. failure: a terminal solver failure occurred, or
* all attempts ended while the challenge remained. timeout: the challenge-level
* wait budget expired while the challenge remained. abandoned: observation ended
* without an attributable terminal challenge outcome. This includes a dismissed
* widget or page unload without a solved signal or terminal solver outcome, and a
* token appearing while multiple same-provider challenges are open, because the
* producer cannot attribute that token to this visible challenge. A
* captcha_solve_result with the same challenge_id may therefore report success
* while the challenge result reports abandoned. A solved challenge does not prove
* the site accepted the token or that the guarded action succeeded.
*/
status: 'solved' | 'failure' | 'timeout' | 'abandoned';

/**
* Captcha product the challenge belongs to, not the service that solved it.
* Enterprise reCAPTCHA variants are grouped into their version bucket
* (recaptcha_v2 or recaptcha_v3), FunCaptcha uses arkose, press-and-hold
* challenges served by HUMAN (formerly PerimeterX) use human, and unlisted
* products use other.
*/
captcha_provider?:
| 'hcaptcha'
| 'recaptcha_v2'
| 'recaptcha_v3'
| 'turnstile'
| 'geetest'
| 'arkose'
| 'human'
| 'other';

/**
* Opaque identifier shared by events for one visible challenge. An image-grid
* captcha may create multiple task_id values for one challenge_id. The same value
* may continue across a page reload when the challenge episode continues. It does
* not indicate task ordering or challenge completion.
*/
challenge_id: string;
challenge_id?: string;

/**
* Wall-clock duration from the challenge appearing to its terminal outcome,
* covering every solver attempt in between.
* True when the relay derived this result from a successful token task without
* observing the page. An inferred result has task_id instead of challenge_id.
* Absent on page-observed results.
*/
duration_ms: number;
inferred?: boolean;

/**
* Terminal outcome of the visible challenge. solved: the page observed the
* challenge clear after a solver attempt. failure: a terminal solver failure
* occurred, or all attempts ended while the challenge remained. timeout: the
* challenge-level wait budget expired while the challenge remained. abandoned:
* observation ended without an attributable terminal challenge outcome. This
* includes a dismissed widget or page unload without a solved signal or terminal
* solver outcome, and a token appearing while multiple same-provider challenges
* are open, because the producer cannot attribute that token to this visible
* challenge. A captcha_solve_result with the same challenge_id may therefore
* report success while the challenge result reports abandoned. A solved challenge
* does not prove the site accepted the token or that the guarded action succeeded.
* The task_id of the solver task an inferred result was derived from. Join on it
* to pair the result with that task's captcha_solve_started and
* captcha_solve_result. Present only when inferred is true.
*/
status: 'solved' | 'failure' | 'timeout' | 'abandoned';
task_id?: string;

/**
* Host of the page where the challenge appeared.
Expand Down Expand Up @@ -315,9 +354,7 @@ export interface BrowserCaptchaSolveResultEvent {
export namespace BrowserCaptchaSolveResultEvent {
export interface Data {
/**
* Captcha kind. Enterprise reCAPTCHA variants are grouped into their version
* bucket (recaptcha_v2 or recaptcha_v3), press-and-hold challenges use
* press_and_hold, and unlisted kinds use other.
* @deprecated Deprecated: use captcha_provider and task_kind.
*/
captcha_type:
| 'hcaptcha'
Expand All @@ -343,6 +380,23 @@ export namespace BrowserCaptchaSolveResultEvent {
*/
status: 'success' | 'failure' | 'timeout' | 'abandoned';

/**
* Captcha product the challenge belongs to, not the service that solved it.
* Enterprise reCAPTCHA variants are grouped into their version bucket
* (recaptcha_v2 or recaptcha_v3), FunCaptcha uses arkose, press-and-hold
* challenges served by HUMAN (formerly PerimeterX) use human, and unlisted
* products use other.
*/
captcha_provider?:
| 'hcaptcha'
| 'recaptcha_v2'
| 'recaptcha_v3'
| 'turnstile'
| 'geetest'
| 'arkose'
| 'human'
| 'other';

/**
* Opaque identifier shared by events for one visible challenge. An image-grid
* captcha may create multiple task_id values for one challenge_id. The same value
Expand All @@ -362,6 +416,11 @@ export namespace BrowserCaptchaSolveResultEvent {
*/
task_id?: string;

/**
* What the solver task produces. Absent when the producer cannot tell.
*/
task_kind?: 'token' | 'image_challenge' | 'press_and_hold';

/**
* Host of the page where the captcha was solved.
*/
Expand Down Expand Up @@ -415,9 +474,7 @@ export namespace BrowserCaptchaSolveStartedEvent {
*/
export interface Data {
/**
* Captcha kind. Enterprise reCAPTCHA variants are grouped into their version
* bucket (recaptcha_v2 or recaptcha_v3), press-and-hold challenges use
* press_and_hold, and unlisted kinds use other.
* @deprecated Deprecated: use captcha_provider and task_kind.
*/
captcha_type:
| 'hcaptcha'
Expand All @@ -428,6 +485,23 @@ export namespace BrowserCaptchaSolveStartedEvent {
| 'press_and_hold'
| 'other';

/**
* Captcha product the challenge belongs to, not the service that solved it.
* Enterprise reCAPTCHA variants are grouped into their version bucket
* (recaptcha_v2 or recaptcha_v3), FunCaptcha uses arkose, press-and-hold
* challenges served by HUMAN (formerly PerimeterX) use human, and unlisted
* products use other.
*/
captcha_provider?:
| 'hcaptcha'
| 'recaptcha_v2'
| 'recaptcha_v3'
| 'turnstile'
| 'geetest'
| 'arkose'
| 'human'
| 'other';

/**
* Opaque identifier shared by events for one visible challenge. An image-grid
* captcha may create multiple task_id values for one challenge_id. The same value
Expand All @@ -441,6 +515,11 @@ export namespace BrowserCaptchaSolveStartedEvent {
*/
task_id?: string;

/**
* What the solver task produces. Absent when the producer cannot tell.
*/
task_kind?: 'token' | 'image_challenge' | 'press_and_hold';

/**
* Host of the page where the captcha is being solved. May be empty for solver
* tasks that carry no page URL.
Expand Down
Loading
Loading