diff --git a/.release-please-manifest.json b/.release-please-manifest.json index e7ca613..13708fa 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.7.0" + ".": "0.7.1" } diff --git a/.stats.yml b/.stats.yml index 401ed65..aa1aff7 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-3ec96d0022acb32aa2676c2e7ae20152b899a776ccd499380c334c955b9ba071.yml -openapi_spec_hash: b64c095d82185c1cd0355abea88b606f -config_hash: 00ec9df250b9dc077f8d3b93a442d252 +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 diff --git a/CHANGELOG.md b/CHANGELOG.md index 54a37d1..71387ef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,23 @@ # Changelog +## 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) + +### Features + +* **api:** manual updates ([a018f17](https://github.com/onkernel/kernel-node-sdk/commit/a018f171c8161b3595fd66c9b2c8ca458e50deec)) + + +### Bug Fixes + +* avoid console usage ([f37b356](https://github.com/onkernel/kernel-node-sdk/commit/f37b3560b92abc5a85416b9b69f03a70b3ff71cf)) + + +### Chores + +* add docs to RequestOptions type ([fcb82ff](https://github.com/onkernel/kernel-node-sdk/commit/fcb82ff3d5c14af006bba0e441d57baf318a19cf)) + ## 0.7.0 (2025-07-02) Full Changelog: [v0.6.5...v0.7.0](https://github.com/onkernel/kernel-node-sdk/compare/v0.6.5...v0.7.0) diff --git a/api.md b/api.md index 736d6e7..eeda41d 100644 --- a/api.md +++ b/api.md @@ -82,3 +82,4 @@ Methods: - client.browsers.list() -> BrowserListResponse - client.browsers.delete({ ...params }) -> void - client.browsers.deleteByID(id) -> void +- client.browsers.retrieveReplay(id) -> Response diff --git a/package.json b/package.json index dce29ff..9abb848 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.7.0", + "version": "0.7.1", "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 3b75d5b..b8f3925 100644 --- a/src/client.ts +++ b/src/client.ts @@ -95,6 +95,8 @@ export interface ClientOptions { * * Note that request timeouts are retried by default, so in a worst-case scenario you may wait * much longer than this timeout before the promise succeeds or fails. + * + * @unit milliseconds */ timeout?: number | undefined; /** diff --git a/src/core/streaming.ts b/src/core/streaming.ts index 7191ee4..a24bcfe 100644 --- a/src/core/streaming.ts +++ b/src/core/streaming.ts @@ -5,6 +5,8 @@ import { findDoubleNewlineIndex, LineDecoder } from '../internal/decoders/line'; import { ReadableStreamToAsyncIterable } from '../internal/shims'; import { isAbortError } from '../internal/errors'; import { encodeUTF8 } from '../internal/utils/bytes'; +import { loggerFor } from '../internal/utils/log'; +import type { Kernel } from '../client'; type Bytes = string | ArrayBuffer | Uint8Array | null | undefined; @@ -16,16 +18,24 @@ export type ServerSentEvent = { export class Stream implements AsyncIterable { controller: AbortController; + #client: Kernel | undefined; constructor( private iterator: () => AsyncIterator, controller: AbortController, + client?: Kernel, ) { this.controller = controller; + this.#client = client; } - static fromSSEResponse(response: Response, controller: AbortController): Stream { + static fromSSEResponse( + response: Response, + controller: AbortController, + client?: Kernel, + ): Stream { let consumed = false; + const logger = client ? loggerFor(client) : console; async function* iterator(): AsyncIterator { if (consumed) { @@ -38,8 +48,8 @@ export class Stream implements AsyncIterable { try { yield JSON.parse(sse.data); } catch (e) { - console.error(`Could not parse message into JSON:`, sse.data); - console.error(`From chunk:`, sse.raw); + logger.error(`Could not parse message into JSON:`, sse.data); + logger.error(`From chunk:`, sse.raw); throw e; } } @@ -54,14 +64,18 @@ export class Stream implements AsyncIterable { } } - return new Stream(iterator, controller); + return new Stream(iterator, controller, client); } /** * Generates a Stream from a newline-separated ReadableStream * where each item is a JSON value. */ - static fromReadableStream(readableStream: ReadableStream, controller: AbortController): Stream { + static fromReadableStream( + readableStream: ReadableStream, + controller: AbortController, + client?: Kernel, + ): Stream { let consumed = false; async function* iterLines(): AsyncGenerator { @@ -101,7 +115,7 @@ export class Stream implements AsyncIterable { } } - return new Stream(iterator, controller); + return new Stream(iterator, controller, client); } [Symbol.asyncIterator](): AsyncIterator { @@ -131,8 +145,8 @@ export class Stream implements AsyncIterable { }; return [ - new Stream(() => teeIterator(left), this.controller), - new Stream(() => teeIterator(right), this.controller), + new Stream(() => teeIterator(left), this.controller, this.#client), + new Stream(() => teeIterator(right), this.controller, this.#client), ]; } diff --git a/src/internal/parse.ts b/src/internal/parse.ts index 18d0b41..7fe9be4 100644 --- a/src/internal/parse.ts +++ b/src/internal/parse.ts @@ -24,10 +24,10 @@ export async function defaultParseResponse(client: Kernel, props: APIResponse // that if you set `stream: true` the response type must also be `Stream` if (props.options.__streamClass) { - return props.options.__streamClass.fromSSEResponse(response, props.controller) as any; + return props.options.__streamClass.fromSSEResponse(response, props.controller, client) as any; } - return Stream.fromSSEResponse(response, props.controller) as any; + return Stream.fromSSEResponse(response, props.controller, client) as any; } // fetch refuses to read the body when the status code is 204. diff --git a/src/internal/request-options.ts b/src/internal/request-options.ts index ffe01ae..56765e5 100644 --- a/src/internal/request-options.ts +++ b/src/internal/request-options.ts @@ -10,17 +10,70 @@ import { type HeadersLike } from './headers'; export type FinalRequestOptions = RequestOptions & { method: HTTPMethod; path: string }; export type RequestOptions = { + /** + * The HTTP method for the request (e.g., 'get', 'post', 'put', 'delete'). + */ method?: HTTPMethod; + + /** + * The URL path for the request. + * + * @example "/v1/foo" + */ path?: string; + + /** + * Query parameters to include in the request URL. + */ query?: object | undefined | null; + + /** + * The request body. Can be a string, JSON object, FormData, or other supported types. + */ body?: unknown; + + /** + * HTTP headers to include with the request. Can be a Headers object, plain object, or array of tuples. + */ headers?: HeadersLike; + + /** + * The maximum number of times that the client will retry a request in case of a + * temporary failure, like a network error or a 5XX error from the server. + * + * @default 2 + */ maxRetries?: number; + stream?: boolean | undefined; + + /** + * The maximum amount of time (in milliseconds) that the client should wait for a response + * from the server before timing out a single request. + * + * @unit milliseconds + */ timeout?: number; + + /** + * Additional `RequestInit` options to be passed to the underlying `fetch` call. + * These options will be merged with the client's default fetch options. + */ fetchOptions?: MergedRequestInit; + + /** + * An AbortSignal that can be used to cancel the request. + */ signal?: AbortSignal | undefined | null; + + /** + * A unique key for this request to enable idempotency. + */ idempotencyKey?: string; + + /** + * Override the default base URL for this specific request. + */ defaultBaseURL?: string | undefined; __binaryResponse?: boolean | undefined; diff --git a/src/resources/browsers.ts b/src/resources/browsers.ts index 8afcb8c..14398d4 100644 --- a/src/resources/browsers.ts +++ b/src/resources/browsers.ts @@ -84,6 +84,27 @@ export class Browsers extends APIResource { 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, + }); + } } /** @@ -117,6 +138,11 @@ export interface BrowserCreateResponse { * 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 { @@ -140,6 +166,11 @@ export interface BrowserRetrieveResponse { * 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; @@ -166,6 +197,11 @@ export namespace BrowserListResponse { * Optional persistence configuration for the browser session. */ persistence?: BrowsersAPI.BrowserPersistence; + + /** + * Remote URL for viewing the browser session replay if enabled + */ + replay_view_url?: string; } } @@ -186,6 +222,11 @@ export interface BrowserCreateParams { */ 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. diff --git a/src/version.ts b/src/version.ts index d9da9f7..5e85c4b 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.7.0'; // x-release-please-version +export const VERSION = '0.7.1'; // x-release-please-version diff --git a/tests/api-resources/browsers.test.ts b/tests/api-resources/browsers.test.ts index d28bd02..b066fa2 100644 --- a/tests/api-resources/browsers.test.ts +++ b/tests/api-resources/browsers.test.ts @@ -29,6 +29,7 @@ describe('resource browsers', () => { headless: false, invocation_id: 'rr33xuugxj9h0bkf1rdt2bet', persistence: { id: 'my-awesome-browser-for-user-1234' }, + replay: true, stealth: true, }, { path: '/_stainless_unknown_path' },