diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index 13708fa..64f3cdd 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "0.7.1"
+ ".": "0.8.0"
}
diff --git a/.stats.yml b/.stats.yml
index aa1aff7..a0553b1 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
-configured_endpoints: 18
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-d173129101e26f450c200e84430d993479c034700cf826917425d513b88912e6.yml
-openapi_spec_hash: 150b86da7588979d7619b1a894e4720c
-config_hash: eaeed470b1070b34df69c49d68e67355
+configured_endpoints: 21
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-a5b1d2c806c42c1534eefc8d34516f7f6e4ab68cb6a836534ee549bdbe4653f3.yml
+openapi_spec_hash: 0be350cc8ddbd1fc7e058ce6c3a44ee8
+config_hash: 307153ecd5b85f77ce8e0d87f6e5dfab
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 71387ef..8a0ee17 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,18 @@
# Changelog
+## 0.8.0 (2025-07-16)
+
+Full Changelog: [v0.7.1...v0.8.0](https://github.com/onkernel/kernel-node-sdk/compare/v0.7.1...v0.8.0)
+
+### Features
+
+* **api:** manual updates ([d073427](https://github.com/onkernel/kernel-node-sdk/commit/d0734275dd0014d8710a08eaa3a732d4530abe4f))
+
+
+### Chores
+
+* make some internal functions async ([b5d654f](https://github.com/onkernel/kernel-node-sdk/commit/b5d654f72557c9f5949e2067f6e61a5dcd514b03))
+
## 0.7.1 (2025-07-08)
Full Changelog: [v0.7.0...v0.7.1](https://github.com/onkernel/kernel-node-sdk/compare/v0.7.0...v0.7.1)
diff --git a/api.md b/api.md
index eeda41d..6d4c5ed 100644
--- a/api.md
+++ b/api.md
@@ -70,16 +70,29 @@ Methods:
Types:
-- BrowserPersistence
-- BrowserCreateResponse
-- BrowserRetrieveResponse
-- BrowserListResponse
+- BrowserPersistence
+- BrowserCreateResponse
+- BrowserRetrieveResponse
+- BrowserListResponse
Methods:
-- client.browsers.create({ ...params }) -> BrowserCreateResponse
-- client.browsers.retrieve(id) -> BrowserRetrieveResponse
-- client.browsers.list() -> BrowserListResponse
-- client.browsers.delete({ ...params }) -> void
-- client.browsers.deleteByID(id) -> void
-- client.browsers.retrieveReplay(id) -> Response
+- client.browsers.create({ ...params }) -> BrowserCreateResponse
+- client.browsers.retrieve(id) -> BrowserRetrieveResponse
+- client.browsers.list() -> BrowserListResponse
+- client.browsers.delete({ ...params }) -> void
+- client.browsers.deleteByID(id) -> void
+
+## Replays
+
+Types:
+
+- ReplayListResponse
+- ReplayStartResponse
+
+Methods:
+
+- client.browsers.replays.list(id) -> ReplayListResponse
+- client.browsers.replays.download(replayID, { ...params }) -> Response
+- client.browsers.replays.start(id, { ...params }) -> ReplayStartResponse
+- client.browsers.replays.stop(replayID, { ...params }) -> void
diff --git a/package.json b/package.json
index 9abb848..c82d243 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@onkernel/sdk",
- "version": "0.7.1",
+ "version": "0.8.0",
"description": "The official TypeScript library for the Kernel API",
"author": "Kernel <>",
"types": "dist/index.d.ts",
diff --git a/src/client.ts b/src/client.ts
index b8f3925..76ae00d 100644
--- a/src/client.ts
+++ b/src/client.ts
@@ -16,15 +16,6 @@ import * as Errors from './core/error';
import * as Uploads from './core/uploads';
import * as API from './resources/index';
import { APIPromise } from './core/api-promise';
-import {
- BrowserCreateParams,
- BrowserCreateResponse,
- BrowserDeleteParams,
- BrowserListResponse,
- BrowserPersistence,
- BrowserRetrieveResponse,
- Browsers,
-} from './resources/browsers';
import {
DeploymentCreateParams,
DeploymentCreateResponse,
@@ -48,6 +39,15 @@ import {
Invocations,
} from './resources/invocations';
import { AppListParams, AppListResponse, Apps } from './resources/apps/apps';
+import {
+ BrowserCreateParams,
+ BrowserCreateResponse,
+ BrowserDeleteParams,
+ BrowserListResponse,
+ BrowserPersistence,
+ BrowserRetrieveResponse,
+ Browsers,
+} from './resources/browsers/browsers';
import { type Fetch } from './internal/builtin-types';
import { HeadersLike, NullableHeaders, buildHeaders } from './internal/headers';
import { FinalRequestOptions, RequestOptions } from './internal/request-options';
@@ -230,7 +230,7 @@ export class Kernel {
* Create a new client instance re-using the same options given to the current client with optional overriding.
*/
withOptions(options: Partial): this {
- return new (this.constructor as any as new (props: ClientOptions) => typeof this)({
+ const client = new (this.constructor as any as new (props: ClientOptions) => typeof this)({
...this._options,
environment: options.environment ? options.environment : undefined,
baseURL: options.environment ? undefined : this.baseURL,
@@ -243,6 +243,7 @@ export class Kernel {
apiKey: this.apiKey,
...options,
});
+ return client;
}
/**
@@ -260,7 +261,7 @@ export class Kernel {
return;
}
- protected authHeaders(opts: FinalRequestOptions): NullableHeaders | undefined {
+ protected async authHeaders(opts: FinalRequestOptions): Promise {
return buildHeaders([{ Authorization: `Bearer ${this.apiKey}` }]);
}
@@ -392,7 +393,9 @@ export class Kernel {
await this.prepareOptions(options);
- const { req, url, timeout } = this.buildRequest(options, { retryCount: maxRetries - retriesRemaining });
+ const { req, url, timeout } = await this.buildRequest(options, {
+ retryCount: maxRetries - retriesRemaining,
+ });
await this.prepareRequest(req, { url, options });
@@ -470,7 +473,7 @@ export class Kernel {
} with status ${response.status} in ${headersTime - startTime}ms`;
if (!response.ok) {
- const shouldRetry = this.shouldRetry(response);
+ const shouldRetry = await this.shouldRetry(response);
if (retriesRemaining && shouldRetry) {
const retryMessage = `retrying, ${retriesRemaining} attempts remaining`;
@@ -569,7 +572,7 @@ export class Kernel {
}
}
- private shouldRetry(response: Response): boolean {
+ private async shouldRetry(response: Response): Promise {
// Note this is not a standard header.
const shouldRetryHeader = response.headers.get('x-should-retry');
@@ -646,10 +649,10 @@ export class Kernel {
return sleepSeconds * jitter * 1000;
}
- buildRequest(
+ async buildRequest(
inputOptions: FinalRequestOptions,
{ retryCount = 0 }: { retryCount?: number } = {},
- ): { req: FinalizedRequestInit; url: string; timeout: number } {
+ ): Promise<{ req: FinalizedRequestInit; url: string; timeout: number }> {
const options = { ...inputOptions };
const { method, path, query, defaultBaseURL } = options;
@@ -657,7 +660,7 @@ export class Kernel {
if ('timeout' in options) validatePositiveInteger('timeout', options.timeout);
options.timeout = options.timeout ?? this.timeout;
const { bodyHeaders, body } = this.buildBody({ options });
- const reqHeaders = this.buildHeaders({ options: inputOptions, method, bodyHeaders, retryCount });
+ const reqHeaders = await this.buildHeaders({ options: inputOptions, method, bodyHeaders, retryCount });
const req: FinalizedRequestInit = {
method,
@@ -673,7 +676,7 @@ export class Kernel {
return { req, url, timeout: options.timeout };
}
- private buildHeaders({
+ private async buildHeaders({
options,
method,
bodyHeaders,
@@ -683,7 +686,7 @@ export class Kernel {
method: HTTPMethod;
bodyHeaders: HeadersLike;
retryCount: number;
- }): Headers {
+ }): Promise {
let idempotencyHeaders: HeadersLike = {};
if (this.idempotencyHeader && method !== 'get') {
if (!options.idempotencyKey) options.idempotencyKey = this.defaultIdempotencyKey();
@@ -699,7 +702,7 @@ export class Kernel {
...(options.timeout ? { 'X-Stainless-Timeout': String(Math.trunc(options.timeout / 1000)) } : {}),
...getPlatformHeaders(),
},
- this.authHeaders(options),
+ await this.authHeaders(options),
this._options.defaultHeaders,
bodyHeaders,
options.headers,
diff --git a/src/resources/browsers.ts b/src/resources/browsers.ts
index 14398d4..7d73ffd 100644
--- a/src/resources/browsers.ts
+++ b/src/resources/browsers.ts
@@ -1,253 +1,3 @@
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-import { APIResource } from '../core/resource';
-import * as BrowsersAPI from './browsers';
-import { APIPromise } from '../core/api-promise';
-import { buildHeaders } from '../internal/headers';
-import { RequestOptions } from '../internal/request-options';
-import { path } from '../internal/utils/path';
-
-export class Browsers extends APIResource {
- /**
- * Create a new browser session from within an action.
- *
- * @example
- * ```ts
- * const browser = await client.browsers.create();
- * ```
- */
- create(
- body: BrowserCreateParams | null | undefined = {},
- options?: RequestOptions,
- ): APIPromise {
- return this._client.post('/browsers', { body, ...options });
- }
-
- /**
- * Get information about a browser session.
- *
- * @example
- * ```ts
- * const browser = await client.browsers.retrieve(
- * 'htzv5orfit78e1m2biiifpbv',
- * );
- * ```
- */
- retrieve(id: string, options?: RequestOptions): APIPromise {
- return this._client.get(path`/browsers/${id}`, options);
- }
-
- /**
- * List active browser sessions
- *
- * @example
- * ```ts
- * const browsers = await client.browsers.list();
- * ```
- */
- list(options?: RequestOptions): APIPromise {
- return this._client.get('/browsers', options);
- }
-
- /**
- * Delete a persistent browser session by its persistent_id.
- *
- * @example
- * ```ts
- * await client.browsers.delete({
- * persistent_id: 'persistent_id',
- * });
- * ```
- */
- delete(params: BrowserDeleteParams, options?: RequestOptions): APIPromise {
- const { persistent_id } = params;
- return this._client.delete('/browsers', {
- query: { persistent_id },
- ...options,
- headers: buildHeaders([{ Accept: '*/*' }, options?.headers]),
- });
- }
-
- /**
- * Delete a browser session by ID
- *
- * @example
- * ```ts
- * await client.browsers.deleteByID(
- * 'htzv5orfit78e1m2biiifpbv',
- * );
- * ```
- */
- deleteByID(id: string, options?: RequestOptions): APIPromise {
- return this._client.delete(path`/browsers/${id}`, {
- ...options,
- headers: buildHeaders([{ Accept: '*/*' }, options?.headers]),
- });
- }
-
- /**
- * Get browser session replay.
- *
- * @example
- * ```ts
- * const response = await client.browsers.retrieveReplay(
- * 'htzv5orfit78e1m2biiifpbv',
- * );
- *
- * const content = await response.blob();
- * console.log(content);
- * ```
- */
- retrieveReplay(id: string, options?: RequestOptions): APIPromise {
- return this._client.get(path`/browsers/${id}/replay`, {
- ...options,
- headers: buildHeaders([{ Accept: 'video/mp4' }, options?.headers]),
- __binaryResponse: true,
- });
- }
-}
-
-/**
- * Optional persistence configuration for the browser session.
- */
-export interface BrowserPersistence {
- /**
- * Unique identifier for the persistent browser session.
- */
- id: string;
-}
-
-export interface BrowserCreateResponse {
- /**
- * Websocket URL for Chrome DevTools Protocol connections to the browser session
- */
- cdp_ws_url: string;
-
- /**
- * Unique identifier for the browser session
- */
- session_id: string;
-
- /**
- * Remote URL for live viewing the browser session. Only available for non-headless
- * browsers.
- */
- browser_live_view_url?: string;
-
- /**
- * Optional persistence configuration for the browser session.
- */
- persistence?: BrowserPersistence;
-
- /**
- * Remote URL for viewing the browser session replay if enabled
- */
- replay_view_url?: string;
-}
-
-export interface BrowserRetrieveResponse {
- /**
- * Websocket URL for Chrome DevTools Protocol connections to the browser session
- */
- cdp_ws_url: string;
-
- /**
- * Unique identifier for the browser session
- */
- session_id: string;
-
- /**
- * Remote URL for live viewing the browser session. Only available for non-headless
- * browsers.
- */
- browser_live_view_url?: string;
-
- /**
- * Optional persistence configuration for the browser session.
- */
- persistence?: BrowserPersistence;
-
- /**
- * Remote URL for viewing the browser session replay if enabled
- */
- replay_view_url?: string;
-}
-
-export type BrowserListResponse = Array;
-
-export namespace BrowserListResponse {
- export interface BrowserListResponseItem {
- /**
- * Websocket URL for Chrome DevTools Protocol connections to the browser session
- */
- cdp_ws_url: string;
-
- /**
- * Unique identifier for the browser session
- */
- session_id: string;
-
- /**
- * Remote URL for live viewing the browser session. Only available for non-headless
- * browsers.
- */
- browser_live_view_url?: string;
-
- /**
- * Optional persistence configuration for the browser session.
- */
- persistence?: BrowsersAPI.BrowserPersistence;
-
- /**
- * Remote URL for viewing the browser session replay if enabled
- */
- replay_view_url?: string;
- }
-}
-
-export interface BrowserCreateParams {
- /**
- * If true, launches the browser using a headless image (no VNC/GUI). Defaults to
- * false.
- */
- headless?: boolean;
-
- /**
- * action invocation ID
- */
- invocation_id?: string;
-
- /**
- * Optional persistence configuration for the browser session.
- */
- persistence?: BrowserPersistence;
-
- /**
- * If true, enables replay recording of the browser session. Defaults to false.
- */
- replay?: boolean;
-
- /**
- * If true, launches the browser in stealth mode to reduce detection by anti-bot
- * mechanisms.
- */
- stealth?: boolean;
-}
-
-export interface BrowserDeleteParams {
- /**
- * Persistent browser identifier
- */
- persistent_id: string;
-}
-
-export declare namespace Browsers {
- export {
- type BrowserPersistence as BrowserPersistence,
- type BrowserCreateResponse as BrowserCreateResponse,
- type BrowserRetrieveResponse as BrowserRetrieveResponse,
- type BrowserListResponse as BrowserListResponse,
- type BrowserCreateParams as BrowserCreateParams,
- type BrowserDeleteParams as BrowserDeleteParams,
- };
-}
+export * from './browsers/index';
diff --git a/src/resources/browsers/browsers.ts b/src/resources/browsers/browsers.ts
new file mode 100644
index 0000000..1f8f204
--- /dev/null
+++ b/src/resources/browsers/browsers.ts
@@ -0,0 +1,234 @@
+// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+import { APIResource } from '../../core/resource';
+import * as BrowsersAPI from './browsers';
+import * as ReplaysAPI from './replays';
+import {
+ ReplayDownloadParams,
+ ReplayListResponse,
+ ReplayStartParams,
+ ReplayStartResponse,
+ ReplayStopParams,
+ Replays,
+} from './replays';
+import { APIPromise } from '../../core/api-promise';
+import { buildHeaders } from '../../internal/headers';
+import { RequestOptions } from '../../internal/request-options';
+import { path } from '../../internal/utils/path';
+
+export class Browsers extends APIResource {
+ replays: ReplaysAPI.Replays = new ReplaysAPI.Replays(this._client);
+
+ /**
+ * Create a new browser session from within an action.
+ *
+ * @example
+ * ```ts
+ * const browser = await client.browsers.create();
+ * ```
+ */
+ create(
+ body: BrowserCreateParams | null | undefined = {},
+ options?: RequestOptions,
+ ): APIPromise {
+ return this._client.post('/browsers', { body, ...options });
+ }
+
+ /**
+ * Get information about a browser session.
+ *
+ * @example
+ * ```ts
+ * const browser = await client.browsers.retrieve(
+ * 'htzv5orfit78e1m2biiifpbv',
+ * );
+ * ```
+ */
+ retrieve(id: string, options?: RequestOptions): APIPromise {
+ return this._client.get(path`/browsers/${id}`, options);
+ }
+
+ /**
+ * List active browser sessions
+ *
+ * @example
+ * ```ts
+ * const browsers = await client.browsers.list();
+ * ```
+ */
+ list(options?: RequestOptions): APIPromise {
+ return this._client.get('/browsers', options);
+ }
+
+ /**
+ * Delete a persistent browser session by its persistent_id.
+ *
+ * @example
+ * ```ts
+ * await client.browsers.delete({
+ * persistent_id: 'persistent_id',
+ * });
+ * ```
+ */
+ delete(params: BrowserDeleteParams, options?: RequestOptions): APIPromise {
+ const { persistent_id } = params;
+ return this._client.delete('/browsers', {
+ query: { persistent_id },
+ ...options,
+ headers: buildHeaders([{ Accept: '*/*' }, options?.headers]),
+ });
+ }
+
+ /**
+ * Delete a browser session by ID
+ *
+ * @example
+ * ```ts
+ * await client.browsers.deleteByID(
+ * 'htzv5orfit78e1m2biiifpbv',
+ * );
+ * ```
+ */
+ deleteByID(id: string, options?: RequestOptions): APIPromise {
+ return this._client.delete(path`/browsers/${id}`, {
+ ...options,
+ headers: buildHeaders([{ Accept: '*/*' }, options?.headers]),
+ });
+ }
+}
+
+/**
+ * Optional persistence configuration for the browser session.
+ */
+export interface BrowserPersistence {
+ /**
+ * Unique identifier for the persistent browser session.
+ */
+ id: string;
+}
+
+export interface BrowserCreateResponse {
+ /**
+ * Websocket URL for Chrome DevTools Protocol connections to the browser session
+ */
+ cdp_ws_url: string;
+
+ /**
+ * Unique identifier for the browser session
+ */
+ session_id: string;
+
+ /**
+ * Remote URL for live viewing the browser session. Only available for non-headless
+ * browsers.
+ */
+ browser_live_view_url?: string;
+
+ /**
+ * Optional persistence configuration for the browser session.
+ */
+ persistence?: BrowserPersistence;
+}
+
+export interface BrowserRetrieveResponse {
+ /**
+ * Websocket URL for Chrome DevTools Protocol connections to the browser session
+ */
+ cdp_ws_url: string;
+
+ /**
+ * Unique identifier for the browser session
+ */
+ session_id: string;
+
+ /**
+ * Remote URL for live viewing the browser session. Only available for non-headless
+ * browsers.
+ */
+ browser_live_view_url?: string;
+
+ /**
+ * Optional persistence configuration for the browser session.
+ */
+ persistence?: BrowserPersistence;
+}
+
+export type BrowserListResponse = Array;
+
+export namespace BrowserListResponse {
+ export interface BrowserListResponseItem {
+ /**
+ * Websocket URL for Chrome DevTools Protocol connections to the browser session
+ */
+ cdp_ws_url: string;
+
+ /**
+ * Unique identifier for the browser session
+ */
+ session_id: string;
+
+ /**
+ * Remote URL for live viewing the browser session. Only available for non-headless
+ * browsers.
+ */
+ browser_live_view_url?: string;
+
+ /**
+ * Optional persistence configuration for the browser session.
+ */
+ persistence?: BrowsersAPI.BrowserPersistence;
+ }
+}
+
+export interface BrowserCreateParams {
+ /**
+ * If true, launches the browser using a headless image (no VNC/GUI). Defaults to
+ * false.
+ */
+ headless?: boolean;
+
+ /**
+ * action invocation ID
+ */
+ invocation_id?: string;
+
+ /**
+ * Optional persistence configuration for the browser session.
+ */
+ persistence?: BrowserPersistence;
+
+ /**
+ * If true, launches the browser in stealth mode to reduce detection by anti-bot
+ * mechanisms.
+ */
+ stealth?: boolean;
+}
+
+export interface BrowserDeleteParams {
+ /**
+ * Persistent browser identifier
+ */
+ persistent_id: string;
+}
+
+Browsers.Replays = Replays;
+
+export declare namespace Browsers {
+ export {
+ type BrowserPersistence as BrowserPersistence,
+ type BrowserCreateResponse as BrowserCreateResponse,
+ type BrowserRetrieveResponse as BrowserRetrieveResponse,
+ type BrowserListResponse as BrowserListResponse,
+ type BrowserCreateParams as BrowserCreateParams,
+ type BrowserDeleteParams as BrowserDeleteParams,
+ };
+
+ export {
+ Replays as Replays,
+ type ReplayListResponse as ReplayListResponse,
+ type ReplayStartResponse as ReplayStartResponse,
+ type ReplayDownloadParams as ReplayDownloadParams,
+ type ReplayStartParams as ReplayStartParams,
+ type ReplayStopParams as ReplayStopParams,
+ };
+}
diff --git a/src/resources/browsers/index.ts b/src/resources/browsers/index.ts
new file mode 100644
index 0000000..deb5900
--- /dev/null
+++ b/src/resources/browsers/index.ts
@@ -0,0 +1,19 @@
+// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+export {
+ Browsers,
+ type BrowserPersistence,
+ type BrowserCreateResponse,
+ type BrowserRetrieveResponse,
+ type BrowserListResponse,
+ type BrowserCreateParams,
+ type BrowserDeleteParams,
+} from './browsers';
+export {
+ Replays,
+ type ReplayListResponse,
+ type ReplayStartResponse,
+ type ReplayDownloadParams,
+ type ReplayStartParams,
+ type ReplayStopParams,
+} from './replays';
diff --git a/src/resources/browsers/replays.ts b/src/resources/browsers/replays.ts
new file mode 100644
index 0000000..208d8c3
--- /dev/null
+++ b/src/resources/browsers/replays.ts
@@ -0,0 +1,168 @@
+// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+import { APIResource } from '../../core/resource';
+import { APIPromise } from '../../core/api-promise';
+import { buildHeaders } from '../../internal/headers';
+import { RequestOptions } from '../../internal/request-options';
+import { path } from '../../internal/utils/path';
+
+export class Replays extends APIResource {
+ /**
+ * List all replays for the specified browser session.
+ *
+ * @example
+ * ```ts
+ * const replays = await client.browsers.replays.list('id');
+ * ```
+ */
+ list(id: string, options?: RequestOptions): APIPromise {
+ return this._client.get(path`/browsers/${id}/replays`, options);
+ }
+
+ /**
+ * Download or stream the specified replay recording.
+ *
+ * @example
+ * ```ts
+ * const response = await client.browsers.replays.download(
+ * 'replay_id',
+ * { id: 'id' },
+ * );
+ *
+ * const content = await response.blob();
+ * console.log(content);
+ * ```
+ */
+ download(replayID: string, params: ReplayDownloadParams, options?: RequestOptions): APIPromise {
+ const { id } = params;
+ return this._client.get(path`/browsers/${id}/replays/${replayID}`, {
+ ...options,
+ headers: buildHeaders([{ Accept: 'video/mp4' }, options?.headers]),
+ __binaryResponse: true,
+ });
+ }
+
+ /**
+ * Start recording the browser session and return a replay ID.
+ *
+ * @example
+ * ```ts
+ * const response = await client.browsers.replays.start('id');
+ * ```
+ */
+ start(
+ id: string,
+ body: ReplayStartParams | null | undefined = {},
+ options?: RequestOptions,
+ ): APIPromise {
+ return this._client.post(path`/browsers/${id}/replays`, { body, ...options });
+ }
+
+ /**
+ * Stop the specified replay recording and persist the video.
+ *
+ * @example
+ * ```ts
+ * await client.browsers.replays.stop('replay_id', {
+ * id: 'id',
+ * });
+ * ```
+ */
+ stop(replayID: string, params: ReplayStopParams, options?: RequestOptions): APIPromise {
+ const { id } = params;
+ return this._client.post(path`/browsers/${id}/replays/${replayID}/stop`, {
+ ...options,
+ headers: buildHeaders([{ Accept: '*/*' }, options?.headers]),
+ });
+ }
+}
+
+export type ReplayListResponse = Array;
+
+export namespace ReplayListResponse {
+ /**
+ * Information about a browser replay recording.
+ */
+ export interface ReplayListResponseItem {
+ /**
+ * Unique identifier for the replay recording.
+ */
+ replay_id: string;
+
+ /**
+ * Timestamp when replay finished
+ */
+ finished_at?: string | null;
+
+ /**
+ * URL for viewing the replay recording.
+ */
+ replay_view_url?: string;
+
+ /**
+ * Timestamp when replay started
+ */
+ started_at?: string | null;
+ }
+}
+
+/**
+ * Information about a browser replay recording.
+ */
+export interface ReplayStartResponse {
+ /**
+ * Unique identifier for the replay recording.
+ */
+ replay_id: string;
+
+ /**
+ * Timestamp when replay finished
+ */
+ finished_at?: string | null;
+
+ /**
+ * URL for viewing the replay recording.
+ */
+ replay_view_url?: string;
+
+ /**
+ * Timestamp when replay started
+ */
+ started_at?: string | null;
+}
+
+export interface ReplayDownloadParams {
+ /**
+ * Browser session ID
+ */
+ id: string;
+}
+
+export interface ReplayStartParams {
+ /**
+ * Recording framerate in fps.
+ */
+ framerate?: number;
+
+ /**
+ * Maximum recording duration in seconds.
+ */
+ max_duration_in_seconds?: number;
+}
+
+export interface ReplayStopParams {
+ /**
+ * Browser session ID
+ */
+ id: string;
+}
+
+export declare namespace Replays {
+ export {
+ type ReplayListResponse as ReplayListResponse,
+ type ReplayStartResponse as ReplayStartResponse,
+ type ReplayDownloadParams as ReplayDownloadParams,
+ type ReplayStartParams as ReplayStartParams,
+ type ReplayStopParams as ReplayStopParams,
+ };
+}
diff --git a/src/resources/index.ts b/src/resources/index.ts
index b48f0f0..f51eb77 100644
--- a/src/resources/index.ts
+++ b/src/resources/index.ts
@@ -10,7 +10,7 @@ export {
type BrowserListResponse,
type BrowserCreateParams,
type BrowserDeleteParams,
-} from './browsers';
+} from './browsers/browsers';
export {
Deployments,
type DeploymentStateEvent,
diff --git a/src/version.ts b/src/version.ts
index 5e85c4b..23f967c 100644
--- a/src/version.ts
+++ b/src/version.ts
@@ -1 +1 @@
-export const VERSION = '0.7.1'; // x-release-please-version
+export const VERSION = '0.8.0'; // x-release-please-version
diff --git a/tests/api-resources/browsers.test.ts b/tests/api-resources/browsers/browsers.test.ts
similarity index 99%
rename from tests/api-resources/browsers.test.ts
rename to tests/api-resources/browsers/browsers.test.ts
index b066fa2..d28bd02 100644
--- a/tests/api-resources/browsers.test.ts
+++ b/tests/api-resources/browsers/browsers.test.ts
@@ -29,7 +29,6 @@ describe('resource browsers', () => {
headless: false,
invocation_id: 'rr33xuugxj9h0bkf1rdt2bet',
persistence: { id: 'my-awesome-browser-for-user-1234' },
- replay: true,
stealth: true,
},
{ path: '/_stainless_unknown_path' },
diff --git a/tests/api-resources/browsers/replays.test.ts b/tests/api-resources/browsers/replays.test.ts
new file mode 100644
index 0000000..23a4cd9
--- /dev/null
+++ b/tests/api-resources/browsers/replays.test.ts
@@ -0,0 +1,68 @@
+// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+import Kernel from '@onkernel/sdk';
+
+const client = new Kernel({
+ apiKey: 'My API Key',
+ baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010',
+});
+
+describe('resource replays', () => {
+ // skipped: tests are disabled for the time being
+ test.skip('list', async () => {
+ const responsePromise = client.browsers.replays.list('id');
+ const rawResponse = await responsePromise.asResponse();
+ expect(rawResponse).toBeInstanceOf(Response);
+ const response = await responsePromise;
+ expect(response).not.toBeInstanceOf(Response);
+ const dataAndResponse = await responsePromise.withResponse();
+ expect(dataAndResponse.data).toBe(response);
+ expect(dataAndResponse.response).toBe(rawResponse);
+ });
+
+ // skipped: tests are disabled for the time being
+ test.skip('download: required and optional params', async () => {
+ const response = await client.browsers.replays.download('replay_id', { id: 'id' });
+ });
+
+ // skipped: tests are disabled for the time being
+ test.skip('start', async () => {
+ const responsePromise = client.browsers.replays.start('id');
+ const rawResponse = await responsePromise.asResponse();
+ expect(rawResponse).toBeInstanceOf(Response);
+ const response = await responsePromise;
+ expect(response).not.toBeInstanceOf(Response);
+ const dataAndResponse = await responsePromise.withResponse();
+ expect(dataAndResponse.data).toBe(response);
+ expect(dataAndResponse.response).toBe(rawResponse);
+ });
+
+ // skipped: tests are disabled for the time being
+ test.skip('start: request options and params are passed correctly', async () => {
+ // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error
+ await expect(
+ client.browsers.replays.start(
+ 'id',
+ { framerate: 1, max_duration_in_seconds: 1 },
+ { path: '/_stainless_unknown_path' },
+ ),
+ ).rejects.toThrow(Kernel.NotFoundError);
+ });
+
+ // skipped: tests are disabled for the time being
+ test.skip('stop: only required params', async () => {
+ const responsePromise = client.browsers.replays.stop('replay_id', { id: 'id' });
+ const rawResponse = await responsePromise.asResponse();
+ expect(rawResponse).toBeInstanceOf(Response);
+ const response = await responsePromise;
+ expect(response).not.toBeInstanceOf(Response);
+ const dataAndResponse = await responsePromise.withResponse();
+ expect(dataAndResponse.data).toBe(response);
+ expect(dataAndResponse.response).toBe(rawResponse);
+ });
+
+ // skipped: tests are disabled for the time being
+ test.skip('stop: required and optional params', async () => {
+ const response = await client.browsers.replays.stop('replay_id', { id: 'id' });
+ });
+});
diff --git a/tests/index.test.ts b/tests/index.test.ts
index 5c12c9a..68b144c 100644
--- a/tests/index.test.ts
+++ b/tests/index.test.ts
@@ -26,13 +26,13 @@ describe('instantiate client', () => {
apiKey: 'My API Key',
});
- test('they are used in the request', () => {
- const { req } = client.buildRequest({ path: '/foo', method: 'post' });
+ test('they are used in the request', async () => {
+ const { req } = await client.buildRequest({ path: '/foo', method: 'post' });
expect(req.headers.get('x-my-default-header')).toEqual('2');
});
- test('can ignore `undefined` and leave the default', () => {
- const { req } = client.buildRequest({
+ test('can ignore `undefined` and leave the default', async () => {
+ const { req } = await client.buildRequest({
path: '/foo',
method: 'post',
headers: { 'X-My-Default-Header': undefined },
@@ -40,8 +40,8 @@ describe('instantiate client', () => {
expect(req.headers.get('x-my-default-header')).toEqual('2');
});
- test('can be removed with `null`', () => {
- const { req } = client.buildRequest({
+ test('can be removed with `null`', async () => {
+ const { req } = await client.buildRequest({
path: '/foo',
method: 'post',
headers: { 'X-My-Default-Header': null },
@@ -357,7 +357,7 @@ describe('instantiate client', () => {
});
describe('withOptions', () => {
- test('creates a new client with overridden options', () => {
+ test('creates a new client with overridden options', async () => {
const client = new Kernel({ baseURL: 'http://localhost:5000/', maxRetries: 3, apiKey: 'My API Key' });
const newClient = client.withOptions({
@@ -378,7 +378,7 @@ describe('instantiate client', () => {
expect(newClient.constructor).toBe(client.constructor);
});
- test('inherits options from the parent client', () => {
+ test('inherits options from the parent client', async () => {
const client = new Kernel({
baseURL: 'http://localhost:5000/',
defaultHeaders: { 'X-Test-Header': 'test-value' },
@@ -393,7 +393,7 @@ describe('instantiate client', () => {
// Test inherited options remain the same
expect(newClient.buildURL('/foo', null)).toEqual('http://localhost:5001/foo?test-param=test-value');
- const { req } = newClient.buildRequest({ path: '/foo', method: 'get' });
+ const { req } = await newClient.buildRequest({ path: '/foo', method: 'get' });
expect(req.headers.get('x-test-header')).toEqual('test-value');
});
@@ -443,8 +443,8 @@ describe('request building', () => {
const client = new Kernel({ apiKey: 'My API Key' });
describe('custom headers', () => {
- test('handles undefined', () => {
- const { req } = client.buildRequest({
+ test('handles undefined', async () => {
+ const { req } = await client.buildRequest({
path: '/foo',
method: 'post',
body: { value: 'hello' },
@@ -479,8 +479,8 @@ describe('default encoder', () => {
}
}
for (const jsonValue of [{}, [], { __proto__: null }, new Serializable(), new Collection(['item'])]) {
- test(`serializes ${util.inspect(jsonValue)} as json`, () => {
- const { req } = client.buildRequest({
+ test(`serializes ${util.inspect(jsonValue)} as json`, async () => {
+ const { req } = await client.buildRequest({
path: '/foo',
method: 'post',
body: jsonValue,
@@ -503,7 +503,7 @@ describe('default encoder', () => {
asyncIterable,
]) {
test(`converts ${util.inspect(streamValue)} to ReadableStream`, async () => {
- const { req } = client.buildRequest({
+ const { req } = await client.buildRequest({
path: '/foo',
method: 'post',
body: streamValue,
@@ -516,7 +516,7 @@ describe('default encoder', () => {
}
test(`can set content-type for ReadableStream`, async () => {
- const { req } = client.buildRequest({
+ const { req } = await client.buildRequest({
path: '/foo',
method: 'post',
body: new Response('a\nb\nc\n').body,