From fae585874eab32da62025927ed6ee8c63d597172 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 11 Apr 2026 05:23:32 +0000 Subject: [PATCH 1/3] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index ad1b0f2..6b88334 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 111 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-49a1a92e00d1eb87e91e8527275cb0705fce2edea30e70fea745f134dd451fbd.yml +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-7d048a0d07483d4fa8d1094f5ec172d1758f044b4e5ced1f41f92f1de8b47def.yml openapi_spec_hash: 0ffef6a95f9d9b1096180fc5e4c5b39c config_hash: 9818dd634f87b677410eefd013d7a179 From 94b52aeac38b20c8ea60e3c016443e0ccc680451 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 13 Apr 2026 17:23:08 +0000 Subject: [PATCH 2/3] feat: add POST /browsers/{id}/curl and /curl/raw endpoints --- .stats.yml | 8 ++--- api.md | 2 ++ browser.go | 90 +++++++++++++++++++++++++++++++++++++++++++++++++ browser_test.go | 36 ++++++++++++++++++++ 4 files changed, 132 insertions(+), 4 deletions(-) diff --git a/.stats.yml b/.stats.yml index 6b88334..f0ba92f 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 111 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-7d048a0d07483d4fa8d1094f5ec172d1758f044b4e5ced1f41f92f1de8b47def.yml -openapi_spec_hash: 0ffef6a95f9d9b1096180fc5e4c5b39c -config_hash: 9818dd634f87b677410eefd013d7a179 +configured_endpoints: 112 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-930823e8b25b4644b74098ad5479840f64a329321aa236460f8a9562ae9051bf.yml +openapi_spec_hash: 9f868e67df8fd2fec8d8fc3eb5ba0b26 +config_hash: 08d55086449943a8fec212b870061a3f diff --git a/api.md b/api.md index 89832f0..4f475a5 100644 --- a/api.md +++ b/api.md @@ -82,6 +82,7 @@ Response Types: - kernel.BrowserGetResponse - kernel.BrowserUpdateResponse - kernel.BrowserListResponse +- kernel.BrowserCurlResponse Methods: @@ -90,6 +91,7 @@ Methods: - client.Browsers.Update(ctx context.Context, id string, body kernel.BrowserUpdateParams) (\*kernel.BrowserUpdateResponse, error) - client.Browsers.List(ctx context.Context, query kernel.BrowserListParams) (\*pagination.OffsetPagination[kernel.BrowserListResponse], error) - client.Browsers.Delete(ctx context.Context, body kernel.BrowserDeleteParams) error +- client.Browsers.Curl(ctx context.Context, id string, body kernel.BrowserCurlParams) (\*kernel.BrowserCurlResponse, error) - client.Browsers.DeleteByID(ctx context.Context, id string) error - client.Browsers.LoadExtensions(ctx context.Context, id string, body kernel.BrowserLoadExtensionsParams) error diff --git a/browser.go b/browser.go index 6478cdf..4533fc1 100644 --- a/browser.go +++ b/browser.go @@ -133,6 +133,20 @@ func (r *BrowserService) Delete(ctx context.Context, body BrowserDeleteParams, o return err } +// Sends an HTTP request through Chrome's HTTP request stack, inheriting the +// browser's TLS fingerprint, cookies, proxy configuration, and headers. Returns a +// structured JSON response with status, headers, body, and timing. +func (r *BrowserService) Curl(ctx context.Context, id string, body BrowserCurlParams, opts ...option.RequestOption) (res *BrowserCurlResponse, err error) { + opts = slices.Concat(r.Options, opts) + if id == "" { + err = errors.New("missing required id parameter") + return nil, err + } + path := fmt.Sprintf("browsers/%s/curl", id) + err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, body, &res, opts...) + return res, err +} + // Delete a browser session by ID func (r *BrowserService) DeleteByID(ctx context.Context, id string, opts ...option.RequestOption) (err error) { opts = slices.Concat(r.Options, opts) @@ -609,6 +623,33 @@ func (r *BrowserListResponse) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } +// Structured response from the browser curl request. +type BrowserCurlResponse struct { + // Response body (UTF-8 string or base64 depending on request). + Body string `json:"body" api:"required"` + // Total request duration in milliseconds. + DurationMs int64 `json:"duration_ms" api:"required"` + // Response headers (multi-value). + Headers map[string][]string `json:"headers" api:"required"` + // HTTP status code from target. + Status int64 `json:"status" api:"required"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + Body respjson.Field + DurationMs respjson.Field + Headers respjson.Field + Status respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r BrowserCurlResponse) RawJSON() string { return r.JSON.raw } +func (r *BrowserCurlResponse) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + type BrowserNewParams struct { // If true, enables GPU acceleration for the browser session. Requires Start-Up or // Enterprise plan and headless=false. @@ -770,6 +811,55 @@ func (r BrowserDeleteParams) URLQuery() (v url.Values, err error) { }) } +type BrowserCurlParams struct { + // Target URL (must be http or https). + URL string `json:"url" api:"required"` + // Request body (for POST/PUT/PATCH). + Body param.Opt[string] `json:"body,omitzero"` + // Request timeout in milliseconds. + TimeoutMs param.Opt[int64] `json:"timeout_ms,omitzero"` + // Custom headers merged with browser defaults. + Headers map[string]string `json:"headers,omitzero"` + // HTTP method. + // + // Any of "GET", "HEAD", "POST", "PUT", "PATCH", "DELETE", "OPTIONS". + Method BrowserCurlParamsMethod `json:"method,omitzero"` + // Encoding for the response body. Use base64 for binary content. + // + // Any of "utf8", "base64". + ResponseEncoding BrowserCurlParamsResponseEncoding `json:"response_encoding,omitzero"` + paramObj +} + +func (r BrowserCurlParams) MarshalJSON() (data []byte, err error) { + type shadow BrowserCurlParams + return param.MarshalObject(r, (*shadow)(&r)) +} +func (r *BrowserCurlParams) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// HTTP method. +type BrowserCurlParamsMethod string + +const ( + BrowserCurlParamsMethodGet BrowserCurlParamsMethod = "GET" + BrowserCurlParamsMethodHead BrowserCurlParamsMethod = "HEAD" + BrowserCurlParamsMethodPost BrowserCurlParamsMethod = "POST" + BrowserCurlParamsMethodPut BrowserCurlParamsMethod = "PUT" + BrowserCurlParamsMethodPatch BrowserCurlParamsMethod = "PATCH" + BrowserCurlParamsMethodDelete BrowserCurlParamsMethod = "DELETE" + BrowserCurlParamsMethodOptions BrowserCurlParamsMethod = "OPTIONS" +) + +// Encoding for the response body. Use base64 for binary content. +type BrowserCurlParamsResponseEncoding string + +const ( + BrowserCurlParamsResponseEncodingUtf8 BrowserCurlParamsResponseEncoding = "utf8" + BrowserCurlParamsResponseEncodingBase64 BrowserCurlParamsResponseEncoding = "base64" +) + type BrowserLoadExtensionsParams struct { // List of extensions to upload and activate Extensions []BrowserLoadExtensionsParamsExtension `json:"extensions,omitzero" api:"required"` diff --git a/browser_test.go b/browser_test.go index 40b7829..c8681a6 100644 --- a/browser_test.go +++ b/browser_test.go @@ -190,6 +190,42 @@ func TestBrowserDelete(t *testing.T) { } } +func TestBrowserCurlWithOptionalParams(t *testing.T) { + t.Skip("Mock server tests are disabled") + baseURL := "http://localhost:4010" + if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { + baseURL = envURL + } + if !testutil.CheckTestServer(t, baseURL) { + return + } + client := kernel.NewClient( + option.WithBaseURL(baseURL), + option.WithAPIKey("My API Key"), + ) + _, err := client.Browsers.Curl( + context.TODO(), + "id", + kernel.BrowserCurlParams{ + URL: "url", + Body: kernel.String("body"), + Headers: map[string]string{ + "foo": "string", + }, + Method: kernel.BrowserCurlParamsMethodGet, + ResponseEncoding: kernel.BrowserCurlParamsResponseEncodingUtf8, + TimeoutMs: kernel.Int(1000), + }, + ) + if err != nil { + var apierr *kernel.Error + if errors.As(err, &apierr) { + t.Log(string(apierr.DumpRequest(true))) + } + t.Fatalf("err should be nil: %s", err.Error()) + } +} + func TestBrowserDeleteByID(t *testing.T) { t.Skip("Mock server tests are disabled") baseURL := "http://localhost:4010" From 25d8c5a70c6a0a2844c97f0e7de8e23186d04bb0 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 13 Apr 2026 17:23:30 +0000 Subject: [PATCH 3/3] release: 0.50.0 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 8 ++++++++ README.md | 2 +- internal/version.go | 2 +- 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index dd7ced1..26b1ce2 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.49.0" + ".": "0.50.0" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index ee9c27d..a2258a5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## 0.50.0 (2026-04-13) + +Full Changelog: [v0.49.0...v0.50.0](https://github.com/kernel/kernel-go-sdk/compare/v0.49.0...v0.50.0) + +### Features + +* add POST /browsers/{id}/curl and /curl/raw endpoints ([94b52ae](https://github.com/kernel/kernel-go-sdk/commit/94b52aeac38b20c8ea60e3c016443e0ccc680451)) + ## 0.49.0 (2026-04-10) Full Changelog: [v0.48.0...v0.49.0](https://github.com/kernel/kernel-go-sdk/compare/v0.48.0...v0.49.0) diff --git a/README.md b/README.md index f88b778..25c70d8 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ Or to pin the version: ```sh -go get -u 'github.com/kernel/kernel-go-sdk@v0.49.0' +go get -u 'github.com/kernel/kernel-go-sdk@v0.50.0' ``` diff --git a/internal/version.go b/internal/version.go index 845a2d5..9fc0bbd 100644 --- a/internal/version.go +++ b/internal/version.go @@ -2,4 +2,4 @@ package internal -const PackageVersion = "0.49.0" // x-release-please-version +const PackageVersion = "0.50.0" // x-release-please-version