From 197769a17f621a47e1796848a3cc42b7b3c7ef2b Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 8 May 2025 16:32:32 +0000 Subject: [PATCH 001/551] chore: configure new SDK language --- .devcontainer/devcontainer.json | 15 + .github/workflows/ci.yml | 81 + .gitignore | 10 + .prettierignore | 7 + .prettierrc.json | 7 + .stats.yml | 4 + Brewfile | 1 + CONTRIBUTING.md | 93 + LICENSE | 201 ++ README.md | 439 ++- SECURITY.md | 23 + api.md | 23 + bin/publish-npm | 25 + eslint.config.mjs | 42 + examples/.keep | 4 + jest.config.ts | 22 + package.json | 75 + scripts/bootstrap | 18 + scripts/build | 53 + scripts/format | 12 + scripts/lint | 21 + scripts/mock | 41 + scripts/test | 56 + scripts/utils/attw-report.cjs | 24 + scripts/utils/check-is-in-git-install.sh | 9 + scripts/utils/check-version.cjs | 20 + scripts/utils/fix-index-exports.cjs | 17 + scripts/utils/git-swap.sh | 13 + scripts/utils/make-dist-package-json.cjs | 21 + scripts/utils/postprocess-files.cjs | 94 + scripts/utils/upload-artifact.sh | 25 + src/api-promise.ts | 2 + src/client.ts | 720 +++++ src/core/README.md | 3 + src/core/api-promise.ts | 92 + src/core/error.ts | 130 + src/core/resource.ts | 11 + src/core/uploads.ts | 2 + src/error.ts | 2 + src/index.ts | 22 + src/internal/README.md | 3 + src/internal/builtin-types.ts | 93 + src/internal/detect-platform.ts | 196 ++ src/internal/errors.ts | 33 + src/internal/headers.ts | 97 + src/internal/parse.ts | 50 + src/internal/request-options.ts | 37 + src/internal/shim-types.d.ts | 28 + src/internal/shims.ts | 107 + src/internal/to-file.ts | 154 + src/internal/types.ts | 92 + src/internal/uploads.ts | 187 ++ src/internal/utils.ts | 8 + src/internal/utils/base64.ts | 40 + src/internal/utils/bytes.ts | 32 + src/internal/utils/env.ts | 18 + src/internal/utils/log.ts | 126 + src/internal/utils/path.ts | 63 + src/internal/utils/sleep.ts | 3 + src/internal/utils/uuid.ts | 17 + src/internal/utils/values.ts | 102 + src/lib/.keep | 4 + src/resource.ts | 2 + src/resources.ts | 1 + src/resources/apps.ts | 150 + src/resources/browser.ts | 35 + src/resources/index.ts | 11 + src/uploads.ts | 2 + src/version.ts | 1 + tests/api-resources/apps.test.ts | 73 + tests/api-resources/browser.test.ts | 22 + tests/base64.test.ts | 80 + tests/buildHeaders.test.ts | 88 + tests/form.test.ts | 85 + tests/index.test.ts | 700 +++++ tests/path.test.ts | 318 ++ tests/stringifyQuery.test.ts | 29 + tests/uploads.test.ts | 107 + tsc-multi.json | 7 + tsconfig.build.json | 18 + tsconfig.deno.json | 15 + tsconfig.dist-src.json | 11 + tsconfig.json | 38 + yarn.lock | 3506 ++++++++++++++++++++++ 84 files changed, 9268 insertions(+), 1 deletion(-) create mode 100644 .devcontainer/devcontainer.json create mode 100644 .github/workflows/ci.yml create mode 100644 .gitignore create mode 100644 .prettierignore create mode 100644 .prettierrc.json create mode 100644 .stats.yml create mode 100644 Brewfile create mode 100644 CONTRIBUTING.md create mode 100644 LICENSE create mode 100644 SECURITY.md create mode 100644 api.md create mode 100644 bin/publish-npm create mode 100644 eslint.config.mjs create mode 100644 examples/.keep create mode 100644 jest.config.ts create mode 100644 package.json create mode 100755 scripts/bootstrap create mode 100755 scripts/build create mode 100755 scripts/format create mode 100755 scripts/lint create mode 100755 scripts/mock create mode 100755 scripts/test create mode 100644 scripts/utils/attw-report.cjs create mode 100755 scripts/utils/check-is-in-git-install.sh create mode 100644 scripts/utils/check-version.cjs create mode 100644 scripts/utils/fix-index-exports.cjs create mode 100755 scripts/utils/git-swap.sh create mode 100644 scripts/utils/make-dist-package-json.cjs create mode 100644 scripts/utils/postprocess-files.cjs create mode 100755 scripts/utils/upload-artifact.sh create mode 100644 src/api-promise.ts create mode 100644 src/client.ts create mode 100644 src/core/README.md create mode 100644 src/core/api-promise.ts create mode 100644 src/core/error.ts create mode 100644 src/core/resource.ts create mode 100644 src/core/uploads.ts create mode 100644 src/error.ts create mode 100644 src/index.ts create mode 100644 src/internal/README.md create mode 100644 src/internal/builtin-types.ts create mode 100644 src/internal/detect-platform.ts create mode 100644 src/internal/errors.ts create mode 100644 src/internal/headers.ts create mode 100644 src/internal/parse.ts create mode 100644 src/internal/request-options.ts create mode 100644 src/internal/shim-types.d.ts create mode 100644 src/internal/shims.ts create mode 100644 src/internal/to-file.ts create mode 100644 src/internal/types.ts create mode 100644 src/internal/uploads.ts create mode 100644 src/internal/utils.ts create mode 100644 src/internal/utils/base64.ts create mode 100644 src/internal/utils/bytes.ts create mode 100644 src/internal/utils/env.ts create mode 100644 src/internal/utils/log.ts create mode 100644 src/internal/utils/path.ts create mode 100644 src/internal/utils/sleep.ts create mode 100644 src/internal/utils/uuid.ts create mode 100644 src/internal/utils/values.ts create mode 100644 src/lib/.keep create mode 100644 src/resource.ts create mode 100644 src/resources.ts create mode 100644 src/resources/apps.ts create mode 100644 src/resources/browser.ts create mode 100644 src/resources/index.ts create mode 100644 src/uploads.ts create mode 100644 src/version.ts create mode 100644 tests/api-resources/apps.test.ts create mode 100644 tests/api-resources/browser.test.ts create mode 100644 tests/base64.test.ts create mode 100644 tests/buildHeaders.test.ts create mode 100644 tests/form.test.ts create mode 100644 tests/index.test.ts create mode 100644 tests/path.test.ts create mode 100644 tests/stringifyQuery.test.ts create mode 100644 tests/uploads.test.ts create mode 100644 tsc-multi.json create mode 100644 tsconfig.build.json create mode 100644 tsconfig.deno.json create mode 100644 tsconfig.dist-src.json create mode 100644 tsconfig.json create mode 100644 yarn.lock diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 00000000..43fd5a73 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,15 @@ +// For format details, see https://aka.ms/devcontainer.json. For config options, see the +// README at: https://github.com/devcontainers/templates/tree/main/src/debian +{ + "name": "Development", + "image": "mcr.microsoft.com/devcontainers/typescript-node:latest", + "features": { + "ghcr.io/devcontainers/features/node:1": {} + }, + "postCreateCommand": "yarn install", + "customizations": { + "vscode": { + "extensions": ["esbenp.prettier-vscode"] + } + } +} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000..097e5580 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,81 @@ +name: CI +on: + push: + branches-ignore: + - 'generated' + - 'codegen/**' + - 'integrated/**' + - 'stl-preview-head/**' + - 'stl-preview-base/**' + +jobs: + lint: + timeout-minutes: 10 + name: lint + runs-on: ${{ github.repository == 'stainless-sdks/kernel-typescript' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} + steps: + - uses: actions/checkout@v4 + + - name: Set up Node + uses: actions/setup-node@v4 + with: + node-version: '20' + + - name: Bootstrap + run: ./scripts/bootstrap + + - name: Check types + run: ./scripts/lint + + build: + timeout-minutes: 5 + name: build + runs-on: ${{ github.repository == 'stainless-sdks/kernel-typescript' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} + permissions: + contents: read + id-token: write + steps: + - uses: actions/checkout@v4 + + - name: Set up Node + uses: actions/setup-node@v4 + with: + node-version: '20' + + - name: Bootstrap + run: ./scripts/bootstrap + + - name: Check build + run: ./scripts/build + + - name: Get GitHub OIDC Token + if: github.repository == 'stainless-sdks/kernel-typescript' + id: github-oidc + uses: actions/github-script@v6 + with: + script: core.setOutput('github_token', await core.getIDToken()); + + - name: Upload tarball + if: github.repository == 'stainless-sdks/kernel-typescript' + env: + URL: https://pkg.stainless.com/s + AUTH: ${{ steps.github-oidc.outputs.github_token }} + SHA: ${{ github.sha }} + run: ./scripts/utils/upload-artifact.sh + test: + timeout-minutes: 10 + name: test + runs-on: ${{ github.repository == 'stainless-sdks/kernel-typescript' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} + steps: + - uses: actions/checkout@v4 + + - name: Set up Node + uses: actions/setup-node@v4 + with: + node-version: '20' + + - name: Bootstrap + run: ./scripts/bootstrap + + - name: Run tests + run: ./scripts/test diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..d98d51a8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +.prism.log +node_modules +yarn-error.log +codegen.log +Brewfile.lock.json +dist +dist-deno +/*.tgz +.idea/ + diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 00000000..3548c5af --- /dev/null +++ b/.prettierignore @@ -0,0 +1,7 @@ +CHANGELOG.md +/ecosystem-tests/*/** +/node_modules +/deno + +# don't format tsc output, will break source maps +/dist diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 00000000..af75adaf --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,7 @@ +{ + "arrowParens": "always", + "experimentalTernaries": true, + "printWidth": 110, + "singleQuote": true, + "trailingComma": "all" +} diff --git a/.stats.yml b/.stats.yml new file mode 100644 index 00000000..b59ce7c7 --- /dev/null +++ b/.stats.yml @@ -0,0 +1,4 @@ +configured_endpoints: 4 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-2a9a9232d72f52fc9b2404958857a1b744762356421cf1bffb99db2c24045378.yml +openapi_spec_hash: ba3c6823319d99762e7e1c6a624bc2ed +config_hash: e48b09ec26046e2b2ba98ad41ecbaf1c diff --git a/Brewfile b/Brewfile new file mode 100644 index 00000000..e4feee60 --- /dev/null +++ b/Brewfile @@ -0,0 +1 @@ +brew "node" diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..d10d10f1 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,93 @@ +## Setting up the environment + +This repository uses [`yarn@v1`](https://classic.yarnpkg.com/lang/en/docs/install). +Other package managers may work but are not officially supported for development. + +To set up the repository, run: + +```sh +$ yarn +$ yarn build +``` + +This will install all the required dependencies and build output files to `dist/`. + +## Modifying/Adding code + +Most of the SDK is generated code. Modifications to code will be persisted between generations, but may +result in merge conflicts between manual patches and changes from the generator. The generator will never +modify the contents of the `src/lib/` and `examples/` directories. + +## Adding and running examples + +All files in the `examples/` directory are not modified by the generator and can be freely edited or added to. + +```ts +// add an example to examples/.ts + +#!/usr/bin/env -S npm run tsn -T +… +``` + +```sh +$ chmod +x examples/.ts +# run the example against your api +$ yarn tsn -T examples/.ts +``` + +## Using the repository from source + +If you’d like to use the repository from source, you can either install from git or link to a cloned repository: + +To install via git: + +```sh +$ npm install git+ssh://git@github.com:stainless-sdks/kernel-typescript.git +``` + +Alternatively, to link a local copy of the repo: + +```sh +# Clone +$ git clone https://www.github.com/stainless-sdks/kernel-typescript +$ cd kernel-typescript + +# With yarn +$ yarn link +$ cd ../my-package +$ yarn link kernel + +# With pnpm +$ pnpm link --global +$ cd ../my-package +$ pnpm link -—global kernel +``` + +## Running tests + +Most tests require you to [set up a mock server](https://github.com/stoplightio/prism) against the OpenAPI spec to run the tests. + +```sh +$ npx prism mock path/to/your/openapi.yml +``` + +```sh +$ yarn run test +``` + +## Linting and formatting + +This repository uses [prettier](https://www.npmjs.com/package/prettier) and +[eslint](https://www.npmjs.com/package/eslint) to format the code in the repository. + +To lint: + +```sh +$ yarn lint +``` + +To format and fix all lint issues automatically: + +```sh +$ yarn fix +``` diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..b32a077a --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2025 Kernel + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/README.md b/README.md index f1a72f97..475e2681 100644 --- a/README.md +++ b/README.md @@ -1 +1,438 @@ -# kernel-typescript \ No newline at end of file +# Kernel TypeScript API Library + +[![NPM version](https://img.shields.io/npm/v/kernel.svg)](https://npmjs.org/package/kernel) ![npm bundle size](https://img.shields.io/bundlephobia/minzip/kernel) + +This library provides convenient access to the Kernel REST API from server-side TypeScript or JavaScript. + +The full API of this library can be found in [api.md](api.md). + +It is generated with [Stainless](https://www.stainless.com/). + +## Installation + +```sh +npm install git+ssh://git@github.com:stainless-sdks/kernel-typescript.git +``` + +> [!NOTE] +> Once this package is [published to npm](https://app.stainless.com/docs/guides/publish), this will become: `npm install kernel` + +## Usage + +The full API of this library can be found in [api.md](api.md). + + +```js +import Kernel from 'kernel'; + +const client = new Kernel({ + apiKey: process.env['KERNEL_API_KEY'], // This is the default and can be omitted +}); + +async function main() { + const response = await client.apps.deploy({ + appName: 'REPLACE_ME', + file: fs.createReadStream('path/to/file'), + version: 'REPLACE_ME', + }); + + console.log(response.id); +} + +main(); +``` + +### Request & Response types + +This library includes TypeScript definitions for all request params and response fields. You may import and use them like so: + + +```ts +import Kernel from 'kernel'; + +const client = new Kernel({ + apiKey: process.env['KERNEL_API_KEY'], // This is the default and can be omitted +}); + +async function main() { + const params: Kernel.AppDeployParams = { + appName: 'REPLACE_ME', + file: fs.createReadStream('path/to/file'), + version: 'REPLACE_ME', + }; + const response: Kernel.AppDeployResponse = await client.apps.deploy(params); +} + +main(); +``` + +Documentation for each method, request param, and response field are available in docstrings and will appear on hover in most modern editors. + +## File uploads + +Request parameters that correspond to file uploads can be passed in many different forms: + +- `File` (or an object with the same structure) +- a `fetch` `Response` (or an object with the same structure) +- an `fs.ReadStream` +- the return value of our `toFile` helper + +```ts +import fs from 'fs'; +import Kernel, { toFile } from 'kernel'; + +const client = new Kernel(); + +// If you have access to Node `fs` we recommend using `fs.createReadStream()`: +await client.apps.deploy({ + appName: 'my-awesome-app', + file: fs.createReadStream('/path/to/file'), + version: '1.0.0', +}); + +// Or if you have the web `File` API you can pass a `File` instance: +await client.apps.deploy({ + appName: 'my-awesome-app', + file: new File(['my bytes'], 'file'), + version: '1.0.0', +}); + +// You can also pass a `fetch` `Response`: +await client.apps.deploy({ + appName: 'my-awesome-app', + file: await fetch('https://somesite/file'), + version: '1.0.0', +}); + +// Finally, if none of the above are convenient, you can use our `toFile` helper: +await client.apps.deploy({ + appName: 'my-awesome-app', + file: await toFile(Buffer.from('my bytes'), 'file'), + version: '1.0.0', +}); +await client.apps.deploy({ + appName: 'my-awesome-app', + file: await toFile(new Uint8Array([0, 1, 2]), 'file'), + version: '1.0.0', +}); +``` + +## Handling errors + +When the library is unable to connect to the API, +or if the API returns a non-success status code (i.e., 4xx or 5xx response), +a subclass of `APIError` will be thrown: + + +```ts +async function main() { + const response = await client.apps + .deploy({ appName: 'REPLACE_ME', file: fs.createReadStream('path/to/file'), version: 'REPLACE_ME' }) + .catch(async (err) => { + if (err instanceof Kernel.APIError) { + console.log(err.status); // 400 + console.log(err.name); // BadRequestError + console.log(err.headers); // {server: 'nginx', ...} + } else { + throw err; + } + }); +} + +main(); +``` + +Error codes are as follows: + +| Status Code | Error Type | +| ----------- | -------------------------- | +| 400 | `BadRequestError` | +| 401 | `AuthenticationError` | +| 403 | `PermissionDeniedError` | +| 404 | `NotFoundError` | +| 422 | `UnprocessableEntityError` | +| 429 | `RateLimitError` | +| >=500 | `InternalServerError` | +| N/A | `APIConnectionError` | + +### Retries + +Certain errors will be automatically retried 2 times by default, with a short exponential backoff. +Connection errors (for example, due to a network connectivity problem), 408 Request Timeout, 409 Conflict, +429 Rate Limit, and >=500 Internal errors will all be retried by default. + +You can use the `maxRetries` option to configure or disable this: + + +```js +// Configure the default for all requests: +const client = new Kernel({ + maxRetries: 0, // default is 2 +}); + +// Or, configure per-request: +await client.apps.deploy({ appName: 'REPLACE_ME', file: fs.createReadStream('path/to/file'), version: 'REPLACE_ME' }, { + maxRetries: 5, +}); +``` + +### Timeouts + +Requests time out after 1 minute by default. You can configure this with a `timeout` option: + + +```ts +// Configure the default for all requests: +const client = new Kernel({ + timeout: 20 * 1000, // 20 seconds (default is 1 minute) +}); + +// Override per-request: +await client.apps.deploy({ appName: 'REPLACE_ME', file: fs.createReadStream('path/to/file'), version: 'REPLACE_ME' }, { + timeout: 5 * 1000, +}); +``` + +On timeout, an `APIConnectionTimeoutError` is thrown. + +Note that requests which time out will be [retried twice by default](#retries). + +## Advanced Usage + +### Accessing raw Response data (e.g., headers) + +The "raw" `Response` returned by `fetch()` can be accessed through the `.asResponse()` method on the `APIPromise` type that all methods return. +This method returns as soon as the headers for a successful response are received and does not consume the response body, so you are free to write custom parsing or streaming logic. + +You can also use the `.withResponse()` method to get the raw `Response` along with the parsed data. +Unlike `.asResponse()` this method consumes the body, returning once it is parsed. + + +```ts +const client = new Kernel(); + +const response = await client.apps + .deploy({ appName: 'REPLACE_ME', file: fs.createReadStream('path/to/file'), version: 'REPLACE_ME' }) + .asResponse(); +console.log(response.headers.get('X-My-Header')); +console.log(response.statusText); // access the underlying Response object + +const { data: response, response: raw } = await client.apps + .deploy({ appName: 'REPLACE_ME', file: fs.createReadStream('path/to/file'), version: 'REPLACE_ME' }) + .withResponse(); +console.log(raw.headers.get('X-My-Header')); +console.log(response.id); +``` + +### Logging + +> [!IMPORTANT] +> All log messages are intended for debugging only. The format and content of log messages +> may change between releases. + +#### Log levels + +The log level can be configured in two ways: + +1. Via the `KERNEL_LOG` environment variable +2. Using the `logLevel` client option (overrides the environment variable if set) + +```ts +import Kernel from 'kernel'; + +const client = new Kernel({ + logLevel: 'debug', // Show all log messages +}); +``` + +Available log levels, from most to least verbose: + +- `'debug'` - Show debug messages, info, warnings, and errors +- `'info'` - Show info messages, warnings, and errors +- `'warn'` - Show warnings and errors (default) +- `'error'` - Show only errors +- `'off'` - Disable all logging + +At the `'debug'` level, all HTTP requests and responses are logged, including headers and bodies. +Some authentication-related headers are redacted, but sensitive data in request and response bodies +may still be visible. + +#### Custom logger + +By default, this library logs to `globalThis.console`. You can also provide a custom logger. +Most logging libraries are supported, including [pino](https://www.npmjs.com/package/pino), [winston](https://www.npmjs.com/package/winston), [bunyan](https://www.npmjs.com/package/bunyan), [consola](https://www.npmjs.com/package/consola), [signale](https://www.npmjs.com/package/signale), and [@std/log](https://jsr.io/@std/log). If your logger doesn't work, please open an issue. + +When providing a custom logger, the `logLevel` option still controls which messages are emitted, messages +below the configured level will not be sent to your logger. + +```ts +import Kernel from 'kernel'; +import pino from 'pino'; + +const logger = pino(); + +const client = new Kernel({ + logger: logger.child({ name: 'Kernel' }), + logLevel: 'debug', // Send all messages to pino, allowing it to filter +}); +``` + +### Making custom/undocumented requests + +This library is typed for convenient access to the documented API. If you need to access undocumented +endpoints, params, or response properties, the library can still be used. + +#### Undocumented endpoints + +To make requests to undocumented endpoints, you can use `client.get`, `client.post`, and other HTTP verbs. +Options on the client, such as retries, will be respected when making these requests. + +```ts +await client.post('/some/path', { + body: { some_prop: 'foo' }, + query: { some_query_arg: 'bar' }, +}); +``` + +#### Undocumented request params + +To make requests using undocumented parameters, you may use `// @ts-expect-error` on the undocumented +parameter. This library doesn't validate at runtime that the request matches the type, so any extra values you +send will be sent as-is. + +```ts +client.foo.create({ + foo: 'my_param', + bar: 12, + // @ts-expect-error baz is not yet public + baz: 'undocumented option', +}); +``` + +For requests with the `GET` verb, any extra params will be in the query, all other requests will send the +extra param in the body. + +If you want to explicitly send an extra argument, you can do so with the `query`, `body`, and `headers` request +options. + +#### Undocumented response properties + +To access undocumented response properties, you may access the response object with `// @ts-expect-error` on +the response object, or cast the response object to the requisite type. Like the request params, we do not +validate or strip extra properties from the response from the API. + +### Customizing the fetch client + +By default, this library expects a global `fetch` function is defined. + +If you want to use a different `fetch` function, you can either polyfill the global: + +```ts +import fetch from 'my-fetch'; + +globalThis.fetch = fetch; +``` + +Or pass it to the client: + +```ts +import Kernel from 'kernel'; +import fetch from 'my-fetch'; + +const client = new Kernel({ fetch }); +``` + +### Fetch options + +If you want to set custom `fetch` options without overriding the `fetch` function, you can provide a `fetchOptions` object when instantiating the client or making a request. (Request-specific options override client options.) + +```ts +import Kernel from 'kernel'; + +const client = new Kernel({ + fetchOptions: { + // `RequestInit` options + }, +}); +``` + +#### Configuring proxies + +To modify proxy behavior, you can provide custom `fetchOptions` that add runtime-specific proxy +options to requests: + + **Node** [[docs](https://github.com/nodejs/undici/blob/main/docs/docs/api/ProxyAgent.md#example---proxyagent-with-fetch)] + +```ts +import Kernel from 'kernel'; +import * as undici from 'undici'; + +const proxyAgent = new undici.ProxyAgent('http://localhost:8888'); +const client = new Kernel({ + fetchOptions: { + dispatcher: proxyAgent, + }, +}); +``` + + **Bun** [[docs](https://bun.sh/guides/http/proxy)] + +```ts +import Kernel from 'kernel'; + +const client = new Kernel({ + fetchOptions: { + proxy: 'http://localhost:8888', + }, +}); +``` + + **Deno** [[docs](https://docs.deno.com/api/deno/~/Deno.createHttpClient)] + +```ts +import Kernel from 'npm:kernel'; + +const httpClient = Deno.createHttpClient({ proxy: { url: 'http://localhost:8888' } }); +const client = new Kernel({ + fetchOptions: { + client: httpClient, + }, +}); +``` + +## Frequently Asked Questions + +## Semantic versioning + +This package generally follows [SemVer](https://semver.org/spec/v2.0.0.html) conventions, though certain backwards-incompatible changes may be released as minor versions: + +1. Changes that only affect static types, without breaking runtime behavior. +2. Changes to library internals which are technically public but not intended or documented for external use. _(Please open a GitHub issue to let us know if you are relying on such internals.)_ +3. Changes that we do not expect to impact the vast majority of users in practice. + +We take backwards-compatibility seriously and work hard to ensure you can rely on a smooth upgrade experience. + +We are keen for your feedback; please open an [issue](https://www.github.com/stainless-sdks/kernel-typescript/issues) with questions, bugs, or suggestions. + +## Requirements + +TypeScript >= 4.9 is supported. + +The following runtimes are supported: + +- Web browsers (Up-to-date Chrome, Firefox, Safari, Edge, and more) +- Node.js 20 LTS or later ([non-EOL](https://endoflife.date/nodejs)) versions. +- Deno v1.28.0 or higher. +- Bun 1.0 or later. +- Cloudflare Workers. +- Vercel Edge Runtime. +- Jest 28 or greater with the `"node"` environment (`"jsdom"` is not supported at this time). +- Nitro v2.6 or greater. + +Note that React Native is not supported at this time. + +If you are interested in other runtime environments, please open or upvote an issue on GitHub. + +## Contributing + +See [the contributing documentation](./CONTRIBUTING.md). diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 00000000..bd2ba47d --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,23 @@ +# Security Policy + +## Reporting Security Issues + +This SDK is generated by [Stainless Software Inc](http://stainless.com). Stainless takes security seriously, and encourages you to report any security vulnerability promptly so that appropriate action can be taken. + +To report a security issue, please contact the Stainless team at security@stainless.com. + +## Responsible Disclosure + +We appreciate the efforts of security researchers and individuals who help us maintain the security of +SDKs we generate. If you believe you have found a security vulnerability, please adhere to responsible +disclosure practices by allowing us a reasonable amount of time to investigate and address the issue +before making any information public. + +## Reporting Non-SDK Related Security Issues + +If you encounter security issues that are not directly related to SDKs but pertain to the services +or products provided by Kernel please follow the respective company's security reporting guidelines. + +--- + +Thank you for helping us keep the SDKs and systems they interact with secure. diff --git a/api.md b/api.md new file mode 100644 index 00000000..02224e64 --- /dev/null +++ b/api.md @@ -0,0 +1,23 @@ +# Apps + +Types: + +- AppDeployResponse +- AppInvokeResponse +- AppRetrieveInvocationResponse + +Methods: + +- client.apps.deploy({ ...params }) -> AppDeployResponse +- client.apps.invoke({ ...params }) -> AppInvokeResponse +- client.apps.retrieveInvocation(id) -> AppRetrieveInvocationResponse + +# Browser + +Types: + +- BrowserCreateSessionResponse + +Methods: + +- client.browser.createSession() -> BrowserCreateSessionResponse diff --git a/bin/publish-npm b/bin/publish-npm new file mode 100644 index 00000000..4c21181b --- /dev/null +++ b/bin/publish-npm @@ -0,0 +1,25 @@ +#!/usr/bin/env bash + +set -eux + +npm config set '//registry.npmjs.org/:_authToken' "$NPM_TOKEN" + +# Build the project +yarn build + +# Navigate to the dist directory +cd dist + +# Get the version from package.json +VERSION="$(node -p "require('./package.json').version")" + +# Extract the pre-release tag if it exists +if [[ "$VERSION" =~ -([a-zA-Z]+) ]]; then + # Extract the part before any dot in the pre-release identifier + TAG="${BASH_REMATCH[1]}" +else + TAG="latest" +fi + +# Publish with the appropriate tag +yarn publish --access public --tag "$TAG" diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 00000000..0064bc53 --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,42 @@ +// @ts-check +import tseslint from 'typescript-eslint'; +import unusedImports from 'eslint-plugin-unused-imports'; +import prettier from 'eslint-plugin-prettier'; + +export default tseslint.config( + { + languageOptions: { + parser: tseslint.parser, + parserOptions: { sourceType: 'module' }, + }, + files: ['**/*.ts', '**/*.mts', '**/*.cts', '**/*.js', '**/*.mjs', '**/*.cjs'], + ignores: ['dist/**'], + plugins: { + '@typescript-eslint': tseslint.plugin, + 'unused-imports': unusedImports, + prettier, + }, + rules: { + 'no-unused-vars': 'off', + 'prettier/prettier': 'error', + 'unused-imports/no-unused-imports': 'error', + 'no-restricted-imports': [ + 'error', + { + patterns: [ + { + regex: '^kernel(/.*)?', + message: 'Use a relative import, not a package import.', + }, + ], + }, + ], + }, + }, + { + files: ['tests/**', 'examples/**'], + rules: { + 'no-restricted-imports': 'off', + }, + }, +); diff --git a/examples/.keep b/examples/.keep new file mode 100644 index 00000000..0651c89c --- /dev/null +++ b/examples/.keep @@ -0,0 +1,4 @@ +File generated from our OpenAPI spec by Stainless. + +This directory can be used to store example files demonstrating usage of this SDK. +It is ignored by Stainless code generation and its content (other than this keep file) won't be touched. diff --git a/jest.config.ts b/jest.config.ts new file mode 100644 index 00000000..5c1b4bd6 --- /dev/null +++ b/jest.config.ts @@ -0,0 +1,22 @@ +import type { JestConfigWithTsJest } from 'ts-jest'; + +const config: JestConfigWithTsJest = { + preset: 'ts-jest/presets/default-esm', + testEnvironment: 'node', + transform: { + '^.+\\.(t|j)sx?$': ['@swc/jest', { sourceMaps: 'inline' }], + }, + moduleNameMapper: { + '^kernel$': '/src/index.ts', + '^kernel/(.*)$': '/src/$1', + }, + modulePathIgnorePatterns: [ + '/ecosystem-tests/', + '/dist/', + '/deno/', + '/deno_tests/', + ], + testPathIgnorePatterns: ['scripts'], +}; + +export default config; diff --git a/package.json b/package.json new file mode 100644 index 00000000..51640651 --- /dev/null +++ b/package.json @@ -0,0 +1,75 @@ +{ + "name": "kernel", + "version": "0.0.1-alpha.0", + "description": "The official TypeScript library for the Kernel API", + "author": "Kernel <>", + "types": "dist/index.d.ts", + "main": "dist/index.js", + "type": "commonjs", + "repository": "github:stainless-sdks/kernel-typescript", + "license": "Apache-2.0", + "packageManager": "yarn@1.22.22", + "files": [ + "**/*" + ], + "private": false, + "scripts": { + "test": "./scripts/test", + "build": "./scripts/build", + "prepublishOnly": "echo 'to publish, run yarn build && (cd dist; yarn publish)' && exit 1", + "format": "./scripts/format", + "prepare": "if ./scripts/utils/check-is-in-git-install.sh; then ./scripts/build && ./scripts/utils/git-swap.sh; fi", + "tsn": "ts-node -r tsconfig-paths/register", + "lint": "./scripts/lint", + "fix": "./scripts/format" + }, + "dependencies": {}, + "devDependencies": { + "@arethetypeswrong/cli": "^0.17.0", + "@swc/core": "^1.3.102", + "@swc/jest": "^0.2.29", + "@types/jest": "^29.4.0", + "@types/node": "^20.17.6", + "typescript-eslint": "8.31.1", + "@typescript-eslint/eslint-plugin": "8.31.1", + "@typescript-eslint/parser": "8.31.1", + "eslint": "^9.20.1", + "eslint-plugin-prettier": "^5.2.3", + "eslint-plugin-unused-imports": "^4.1.4", + "iconv-lite": "^0.6.3", + "jest": "^29.4.0", + "prettier": "^3.0.0", + "publint": "^0.2.12", + "ts-jest": "^29.1.0", + "ts-node": "^10.5.0", + "tsc-multi": "https://github.com/stainless-api/tsc-multi/releases/download/v1.1.4/tsc-multi-1.1.4.tgz", + "tsconfig-paths": "^4.0.0", + "typescript": "5.8.3" + }, + "resolutions": { + "synckit": "0.8.8" + }, + "imports": { + "kernel": ".", + "kernel/*": "./src/*" + }, + "exports": { + ".": { + "import": "./dist/index.mjs", + "require": "./dist/index.js" + }, + "./*.mjs": { + "default": "./dist/*.mjs" + }, + "./*.js": { + "default": "./dist/*.js" + }, + "./*": { + "import": "./dist/*.mjs", + "require": "./dist/*.js" + } + }, + "engines": { + "node": ">= 20" + } +} diff --git a/scripts/bootstrap b/scripts/bootstrap new file mode 100755 index 00000000..0af58e25 --- /dev/null +++ b/scripts/bootstrap @@ -0,0 +1,18 @@ +#!/usr/bin/env bash + +set -e + +cd "$(dirname "$0")/.." + +if [ -f "Brewfile" ] && [ "$(uname -s)" = "Darwin" ] && [ "$SKIP_BREW" != "1" ]; then + brew bundle check >/dev/null 2>&1 || { + echo "==> Installing Homebrew dependencies…" + brew bundle + } +fi + +echo "==> Installing Node dependencies…" + +PACKAGE_MANAGER=$(command -v yarn >/dev/null 2>&1 && echo "yarn" || echo "npm") + +$PACKAGE_MANAGER install diff --git a/scripts/build b/scripts/build new file mode 100755 index 00000000..4513a5f1 --- /dev/null +++ b/scripts/build @@ -0,0 +1,53 @@ +#!/usr/bin/env bash + +set -exuo pipefail + +cd "$(dirname "$0")/.." + +node scripts/utils/check-version.cjs + +# Build into dist and will publish the package from there, +# so that src/resources/foo.ts becomes /resources/foo.js +# This way importing from `"kernel/resources/foo"` works +# even with `"moduleResolution": "node"` + +rm -rf dist; mkdir dist +# Copy src to dist/src and build from dist/src into dist, so that +# the source map for index.js.map will refer to ./src/index.ts etc +cp -rp src README.md dist +for file in LICENSE CHANGELOG.md; do + if [ -e "${file}" ]; then cp "${file}" dist; fi +done +if [ -e "bin/cli" ]; then + mkdir -p dist/bin + cp -p "bin/cli" dist/bin/; +fi +if [ -e "bin/migration-config.json" ]; then + mkdir -p dist/bin + cp -p "bin/migration-config.json" dist/bin/; +fi +# this converts the export map paths for the dist directory +# and does a few other minor things +node scripts/utils/make-dist-package-json.cjs > dist/package.json + +# build to .js/.mjs/.d.ts files +npm exec tsc-multi +# we need to patch index.js so that `new module.exports()` works for cjs backwards +# compat. No way to get that from index.ts because it would cause compile errors +# when building .mjs +node scripts/utils/fix-index-exports.cjs +cp tsconfig.dist-src.json dist/src/tsconfig.json +cp src/internal/shim-types.d.ts dist/internal/shim-types.d.ts +cp src/internal/shim-types.d.ts dist/internal/shim-types.d.mts + +node scripts/utils/postprocess-files.cjs + +# make sure that nothing crashes when we require the output CJS or +# import the output ESM +(cd dist && node -e 'require("kernel")') +(cd dist && node -e 'import("kernel")' --input-type=module) + +if [ -e ./scripts/build-deno ] +then + ./scripts/build-deno +fi diff --git a/scripts/format b/scripts/format new file mode 100755 index 00000000..7a756401 --- /dev/null +++ b/scripts/format @@ -0,0 +1,12 @@ +#!/usr/bin/env bash + +set -e + +cd "$(dirname "$0")/.." + +echo "==> Running eslint --fix" +./node_modules/.bin/eslint --fix . + +echo "==> Running prettier --write" +# format things eslint didn't +./node_modules/.bin/prettier --write --cache --cache-strategy metadata . '!**/dist' '!**/*.ts' '!**/*.mts' '!**/*.cts' '!**/*.js' '!**/*.mjs' '!**/*.cjs' diff --git a/scripts/lint b/scripts/lint new file mode 100755 index 00000000..3ffb78a6 --- /dev/null +++ b/scripts/lint @@ -0,0 +1,21 @@ +#!/usr/bin/env bash + +set -e + +cd "$(dirname "$0")/.." + +echo "==> Running eslint" +./node_modules/.bin/eslint . + +echo "==> Building" +./scripts/build + +echo "==> Checking types" +./node_modules/typescript/bin/tsc + +echo "==> Running Are The Types Wrong?" +./node_modules/.bin/attw --pack dist -f json >.attw.json || true +node scripts/utils/attw-report.cjs + +echo "==> Running publint" +./node_modules/.bin/publint dist diff --git a/scripts/mock b/scripts/mock new file mode 100755 index 00000000..d2814ae6 --- /dev/null +++ b/scripts/mock @@ -0,0 +1,41 @@ +#!/usr/bin/env bash + +set -e + +cd "$(dirname "$0")/.." + +if [[ -n "$1" && "$1" != '--'* ]]; then + URL="$1" + shift +else + URL="$(grep 'openapi_spec_url' .stats.yml | cut -d' ' -f2)" +fi + +# Check if the URL is empty +if [ -z "$URL" ]; then + echo "Error: No OpenAPI spec path/url provided or found in .stats.yml" + exit 1 +fi + +echo "==> Starting mock server with URL ${URL}" + +# Run prism mock on the given spec +if [ "$1" == "--daemon" ]; then + npm exec --package=@stainless-api/prism-cli@5.8.5 -- prism mock "$URL" &> .prism.log & + + # Wait for server to come online + echo -n "Waiting for server" + while ! grep -q "✖ fatal\|Prism is listening" ".prism.log" ; do + echo -n "." + sleep 0.1 + done + + if grep -q "✖ fatal" ".prism.log"; then + cat .prism.log + exit 1 + fi + + echo +else + npm exec --package=@stainless-api/prism-cli@5.8.5 -- prism mock "$URL" +fi diff --git a/scripts/test b/scripts/test new file mode 100755 index 00000000..2049e31b --- /dev/null +++ b/scripts/test @@ -0,0 +1,56 @@ +#!/usr/bin/env bash + +set -e + +cd "$(dirname "$0")/.." + +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[0;33m' +NC='\033[0m' # No Color + +function prism_is_running() { + curl --silent "http://localhost:4010" >/dev/null 2>&1 +} + +kill_server_on_port() { + pids=$(lsof -t -i tcp:"$1" || echo "") + if [ "$pids" != "" ]; then + kill "$pids" + echo "Stopped $pids." + fi +} + +function is_overriding_api_base_url() { + [ -n "$TEST_API_BASE_URL" ] +} + +if ! is_overriding_api_base_url && ! prism_is_running ; then + # When we exit this script, make sure to kill the background mock server process + trap 'kill_server_on_port 4010' EXIT + + # Start the dev server + ./scripts/mock --daemon +fi + +if is_overriding_api_base_url ; then + echo -e "${GREEN}✔ Running tests against ${TEST_API_BASE_URL}${NC}" + echo +elif ! prism_is_running ; then + echo -e "${RED}ERROR:${NC} The test suite will not run without a mock Prism server" + echo -e "running against your OpenAPI spec." + echo + echo -e "To run the server, pass in the path or url of your OpenAPI" + echo -e "spec to the prism command:" + echo + echo -e " \$ ${YELLOW}npm exec --package=@stoplight/prism-cli@~5.3.2 -- prism mock path/to/your.openapi.yml${NC}" + echo + + exit 1 +else + echo -e "${GREEN}✔ Mock prism server is running with your OpenAPI spec${NC}" + echo +fi + +echo "==> Running tests" +./node_modules/.bin/jest "$@" diff --git a/scripts/utils/attw-report.cjs b/scripts/utils/attw-report.cjs new file mode 100644 index 00000000..b3477c0e --- /dev/null +++ b/scripts/utils/attw-report.cjs @@ -0,0 +1,24 @@ +const fs = require('fs'); +const problems = Object.values(JSON.parse(fs.readFileSync('.attw.json', 'utf-8')).problems) + .flat() + .filter( + (problem) => + !( + // This is intentional, if the user specifies .mjs they get ESM. + ( + (problem.kind === 'CJSResolvesToESM' && problem.entrypoint.endsWith('.mjs')) || + // This is intentional for backwards compat reasons. + (problem.kind === 'MissingExportEquals' && problem.implementationFileName.endsWith('/index.js')) || + // this is intentional, we deliberately attempt to import types that may not exist from parent node_modules + // folders to better support various runtimes without triggering automatic type acquisition. + (problem.kind === 'InternalResolutionError' && problem.moduleSpecifier.includes('node_modules')) + ) + ), + ); +fs.unlinkSync('.attw.json'); +if (problems.length) { + process.stdout.write('The types are wrong!\n' + JSON.stringify(problems, null, 2) + '\n'); + process.exitCode = 1; +} else { + process.stdout.write('Types ok!\n'); +} diff --git a/scripts/utils/check-is-in-git-install.sh b/scripts/utils/check-is-in-git-install.sh new file mode 100755 index 00000000..1354eb43 --- /dev/null +++ b/scripts/utils/check-is-in-git-install.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash +# Check if you happen to call prepare for a repository that's already in node_modules. +[ "$(basename "$(dirname "$PWD")")" = 'node_modules' ] || +# The name of the containing directory that 'npm` uses, which looks like +# $HOME/.npm/_cacache/git-cloneXXXXXX +[ "$(basename "$(dirname "$PWD")")" = 'tmp' ] || +# The name of the containing directory that 'yarn` uses, which looks like +# $(yarn cache dir)/.tmp/XXXXX +[ "$(basename "$(dirname "$PWD")")" = '.tmp' ] diff --git a/scripts/utils/check-version.cjs b/scripts/utils/check-version.cjs new file mode 100644 index 00000000..86c56dfd --- /dev/null +++ b/scripts/utils/check-version.cjs @@ -0,0 +1,20 @@ +const fs = require('fs'); +const path = require('path'); + +const main = () => { + const pkg = require('../../package.json'); + const version = pkg['version']; + if (!version) throw 'The version property is not set in the package.json file'; + if (typeof version !== 'string') { + throw `Unexpected type for the package.json version field; got ${typeof version}, expected string`; + } + + const versionFile = path.resolve(__dirname, '..', '..', 'src', 'version.ts'); + const contents = fs.readFileSync(versionFile, 'utf8'); + const output = contents.replace(/(export const VERSION = ')(.*)(')/g, `$1${version}$3`); + fs.writeFileSync(versionFile, output); +}; + +if (require.main === module) { + main(); +} diff --git a/scripts/utils/fix-index-exports.cjs b/scripts/utils/fix-index-exports.cjs new file mode 100644 index 00000000..e5e10b3e --- /dev/null +++ b/scripts/utils/fix-index-exports.cjs @@ -0,0 +1,17 @@ +const fs = require('fs'); +const path = require('path'); + +const indexJs = + process.env['DIST_PATH'] ? + path.resolve(process.env['DIST_PATH'], 'index.js') + : path.resolve(__dirname, '..', '..', 'dist', 'index.js'); + +let before = fs.readFileSync(indexJs, 'utf8'); +let after = before.replace( + /^(\s*Object\.defineProperty\s*\(exports,\s*["']__esModule["'].+)$/m, + `exports = module.exports = function (...args) { + return new exports.default(...args) + } + $1`.replace(/^ /gm, ''), +); +fs.writeFileSync(indexJs, after, 'utf8'); diff --git a/scripts/utils/git-swap.sh b/scripts/utils/git-swap.sh new file mode 100755 index 00000000..79d1888e --- /dev/null +++ b/scripts/utils/git-swap.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash +set -exuo pipefail +# the package is published to NPM from ./dist +# we want the final file structure for git installs to match the npm installs, so we + +# delete everything except ./dist and ./node_modules +find . -maxdepth 1 -mindepth 1 ! -name 'dist' ! -name 'node_modules' -exec rm -rf '{}' + + +# move everything from ./dist to . +mv dist/* . + +# delete the now-empty ./dist +rmdir dist diff --git a/scripts/utils/make-dist-package-json.cjs b/scripts/utils/make-dist-package-json.cjs new file mode 100644 index 00000000..7c24f56e --- /dev/null +++ b/scripts/utils/make-dist-package-json.cjs @@ -0,0 +1,21 @@ +const pkgJson = require(process.env['PKG_JSON_PATH'] || '../../package.json'); + +function processExportMap(m) { + for (const key in m) { + const value = m[key]; + if (typeof value === 'string') m[key] = value.replace(/^\.\/dist\//, './'); + else processExportMap(value); + } +} +processExportMap(pkgJson.exports); + +for (const key of ['types', 'main', 'module']) { + if (typeof pkgJson[key] === 'string') pkgJson[key] = pkgJson[key].replace(/^(\.\/)?dist\//, './'); +} + +delete pkgJson.devDependencies; +delete pkgJson.scripts.prepack; +delete pkgJson.scripts.prepublishOnly; +delete pkgJson.scripts.prepare; + +console.log(JSON.stringify(pkgJson, null, 2)); diff --git a/scripts/utils/postprocess-files.cjs b/scripts/utils/postprocess-files.cjs new file mode 100644 index 00000000..deae575e --- /dev/null +++ b/scripts/utils/postprocess-files.cjs @@ -0,0 +1,94 @@ +// @ts-check +const fs = require('fs'); +const path = require('path'); + +const distDir = + process.env['DIST_PATH'] ? + path.resolve(process.env['DIST_PATH']) + : path.resolve(__dirname, '..', '..', 'dist'); + +async function* walk(dir) { + for await (const d of await fs.promises.opendir(dir)) { + const entry = path.join(dir, d.name); + if (d.isDirectory()) yield* walk(entry); + else if (d.isFile()) yield entry; + } +} + +async function postprocess() { + for await (const file of walk(distDir)) { + if (!/(\.d)?[cm]?ts$/.test(file)) continue; + + const code = await fs.promises.readFile(file, 'utf8'); + + // strip out lib="dom", types="node", and types="react" references; these + // are needed at build time, but would pollute the user's TS environment + const transformed = code.replace( + /^ *\/\/\/ * ' '.repeat(match.length - 1) + '\n', + ); + + if (transformed !== code) { + console.error(`wrote ${path.relative(process.cwd(), file)}`); + await fs.promises.writeFile(file, transformed, 'utf8'); + } + } + + const newExports = { + '.': { + require: { + types: './index.d.ts', + default: './index.js', + }, + types: './index.d.mts', + default: './index.mjs', + }, + }; + + for (const entry of await fs.promises.readdir(distDir, { withFileTypes: true })) { + if (entry.isDirectory() && entry.name !== 'src' && entry.name !== 'internal' && entry.name !== 'bin') { + const subpath = './' + entry.name; + newExports[subpath + '/*.mjs'] = { + default: subpath + '/*.mjs', + }; + newExports[subpath + '/*.js'] = { + default: subpath + '/*.js', + }; + newExports[subpath + '/*'] = { + import: subpath + '/*.mjs', + require: subpath + '/*.js', + }; + } else if (entry.isFile() && /\.[cm]?js$/.test(entry.name)) { + const { name, ext } = path.parse(entry.name); + const subpathWithoutExt = './' + name; + const subpath = './' + entry.name; + newExports[subpathWithoutExt] ||= { import: undefined, require: undefined }; + const isModule = ext[1] === 'm'; + if (isModule) { + newExports[subpathWithoutExt].import = subpath; + } else { + newExports[subpathWithoutExt].require = subpath; + } + newExports[subpath] = { + default: subpath, + }; + } + } + await fs.promises.writeFile( + 'dist/package.json', + JSON.stringify( + Object.assign( + /** @type {Record} */ ( + JSON.parse(await fs.promises.readFile('dist/package.json', 'utf-8')) + ), + { + exports: newExports, + }, + ), + null, + 2, + ), + ); +} +postprocess(); diff --git a/scripts/utils/upload-artifact.sh b/scripts/utils/upload-artifact.sh new file mode 100755 index 00000000..5580c062 --- /dev/null +++ b/scripts/utils/upload-artifact.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash +set -exuo pipefail + +RESPONSE=$(curl -X POST "$URL" \ + -H "Authorization: Bearer $AUTH" \ + -H "Content-Type: application/json") + +SIGNED_URL=$(echo "$RESPONSE" | jq -r '.url') + +if [[ "$SIGNED_URL" == "null" ]]; then + echo -e "\033[31mFailed to get signed URL.\033[0m" + exit 1 +fi + +UPLOAD_RESPONSE=$(tar -cz dist | curl -v -X PUT \ + -H "Content-Type: application/gzip" \ + --data-binary @- "$SIGNED_URL" 2>&1) + +if echo "$UPLOAD_RESPONSE" | grep -q "HTTP/[0-9.]* 200"; then + echo -e "\033[32mUploaded build to Stainless storage.\033[0m" + echo -e "\033[32mInstallation: npm install 'https://pkg.stainless.com/s/kernel-typescript/$SHA'\033[0m" +else + echo -e "\033[31mFailed to upload artifact.\033[0m" + exit 1 +fi diff --git a/src/api-promise.ts b/src/api-promise.ts new file mode 100644 index 00000000..8c775ee6 --- /dev/null +++ b/src/api-promise.ts @@ -0,0 +1,2 @@ +/** @deprecated Import from ./core/api-promise instead */ +export * from './core/api-promise'; diff --git a/src/client.ts b/src/client.ts new file mode 100644 index 00000000..0e2dbad7 --- /dev/null +++ b/src/client.ts @@ -0,0 +1,720 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import type { RequestInit, RequestInfo, BodyInit } from './internal/builtin-types'; +import type { HTTPMethod, PromiseOrValue, MergedRequestInit, FinalizedRequestInit } from './internal/types'; +import { uuid4 } from './internal/utils/uuid'; +import { validatePositiveInteger, isAbsoluteURL, safeJSON } from './internal/utils/values'; +import { sleep } from './internal/utils/sleep'; +import { type Logger, type LogLevel, parseLogLevel } from './internal/utils/log'; +export type { Logger, LogLevel } from './internal/utils/log'; +import { castToError, isAbortError } from './internal/errors'; +import type { APIResponseProps } from './internal/parse'; +import { getPlatformHeaders } from './internal/detect-platform'; +import * as Shims from './internal/shims'; +import * as Opts from './internal/request-options'; +import { VERSION } from './version'; +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 { type Fetch } from './internal/builtin-types'; +import { HeadersLike, NullableHeaders, buildHeaders } from './internal/headers'; +import { FinalRequestOptions, RequestOptions } from './internal/request-options'; +import { + AppDeployParams, + AppDeployResponse, + AppInvokeParams, + AppInvokeResponse, + AppRetrieveInvocationResponse, + Apps, +} from './resources/apps'; +import { Browser, BrowserCreateSessionResponse } from './resources/browser'; +import { readEnv } from './internal/utils/env'; +import { formatRequestDetails, loggerFor } from './internal/utils/log'; +import { isEmptyObj } from './internal/utils/values'; + +export interface ClientOptions { + /** + * Defaults to process.env['KERNEL_API_KEY']. + */ + apiKey?: string | undefined; + + /** + * Override the default base URL for the API, e.g., "https://api.example.com/v2/" + * + * Defaults to process.env['KERNEL_BASE_URL']. + */ + baseURL?: string | null | 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. + * + * 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. + */ + timeout?: number | undefined; + /** + * Additional `RequestInit` options to be passed to `fetch` calls. + * Properties will be overridden by per-request `fetchOptions`. + */ + fetchOptions?: MergedRequestInit | undefined; + + /** + * Specify a custom `fetch` function implementation. + * + * If not provided, we expect that `fetch` is defined globally. + */ + fetch?: Fetch | undefined; + + /** + * 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 | undefined; + + /** + * Default headers to include with every request to the API. + * + * These can be removed in individual requests by explicitly setting the + * header to `null` in request options. + */ + defaultHeaders?: HeadersLike | undefined; + + /** + * Default query parameters to include with every request to the API. + * + * These can be removed in individual requests by explicitly setting the + * param to `undefined` in request options. + */ + defaultQuery?: Record | undefined; + + /** + * Set the log level. + * + * Defaults to process.env['KERNEL_LOG'] or 'warn' if it isn't set. + */ + logLevel?: LogLevel | undefined; + + /** + * Set the logger. + * + * Defaults to globalThis.console. + */ + logger?: Logger | undefined; +} + +/** + * API Client for interfacing with the Kernel API. + */ +export class Kernel { + apiKey: string; + + baseURL: string; + maxRetries: number; + timeout: number; + logger: Logger | undefined; + logLevel: LogLevel | undefined; + fetchOptions: MergedRequestInit | undefined; + + private fetch: Fetch; + #encoder: Opts.RequestEncoder; + protected idempotencyHeader?: string; + private _options: ClientOptions; + + /** + * API Client for interfacing with the Kernel API. + * + * @param {string | undefined} [opts.apiKey=process.env['KERNEL_API_KEY'] ?? undefined] + * @param {string} [opts.baseURL=process.env['KERNEL_BASE_URL'] ?? http://localhost:3001] - Override the default base URL for the API. + * @param {number} [opts.timeout=1 minute] - The maximum amount of time (in milliseconds) the client will wait for a response before timing out. + * @param {MergedRequestInit} [opts.fetchOptions] - Additional `RequestInit` options to be passed to `fetch` calls. + * @param {Fetch} [opts.fetch] - Specify a custom `fetch` function implementation. + * @param {number} [opts.maxRetries=2] - The maximum number of times the client will retry a request. + * @param {HeadersLike} opts.defaultHeaders - Default headers to include with every request to the API. + * @param {Record} opts.defaultQuery - Default query parameters to include with every request to the API. + */ + constructor({ + baseURL = readEnv('KERNEL_BASE_URL'), + apiKey = readEnv('KERNEL_API_KEY'), + ...opts + }: ClientOptions = {}) { + if (apiKey === undefined) { + throw new Errors.KernelError( + "The KERNEL_API_KEY environment variable is missing or empty; either provide it, or instantiate the Kernel client with an apiKey option, like new Kernel({ apiKey: 'My API Key' }).", + ); + } + + const options: ClientOptions = { + apiKey, + ...opts, + baseURL: baseURL || `http://localhost:3001`, + }; + + this.baseURL = options.baseURL!; + this.timeout = options.timeout ?? Kernel.DEFAULT_TIMEOUT /* 1 minute */; + this.logger = options.logger ?? console; + const defaultLogLevel = 'warn'; + // Set default logLevel early so that we can log a warning in parseLogLevel. + this.logLevel = defaultLogLevel; + this.logLevel = + parseLogLevel(options.logLevel, 'ClientOptions.logLevel', this) ?? + parseLogLevel(readEnv('KERNEL_LOG'), "process.env['KERNEL_LOG']", this) ?? + defaultLogLevel; + this.fetchOptions = options.fetchOptions; + this.maxRetries = options.maxRetries ?? 2; + this.fetch = options.fetch ?? Shims.getDefaultFetch(); + this.#encoder = Opts.FallbackEncoder; + + this._options = options; + + this.apiKey = apiKey; + } + + /** + * 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)({ + ...this._options, + baseURL: this.baseURL, + maxRetries: this.maxRetries, + timeout: this.timeout, + logger: this.logger, + logLevel: this.logLevel, + fetchOptions: this.fetchOptions, + apiKey: this.apiKey, + ...options, + }); + } + + protected defaultQuery(): Record | undefined { + return this._options.defaultQuery; + } + + protected validateHeaders({ values, nulls }: NullableHeaders) { + return; + } + + protected authHeaders(opts: FinalRequestOptions): NullableHeaders | undefined { + return buildHeaders([{ Authorization: `Bearer ${this.apiKey}` }]); + } + + /** + * Basic re-implementation of `qs.stringify` for primitive types. + */ + protected stringifyQuery(query: Record): string { + return Object.entries(query) + .filter(([_, value]) => typeof value !== 'undefined') + .map(([key, value]) => { + if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') { + return `${encodeURIComponent(key)}=${encodeURIComponent(value)}`; + } + if (value === null) { + return `${encodeURIComponent(key)}=`; + } + throw new Errors.KernelError( + `Cannot stringify type ${typeof value}; Expected string, number, boolean, or null. If you need to pass nested query parameters, you can manually encode them, e.g. { query: { 'foo[key1]': value1, 'foo[key2]': value2 } }, and please open a GitHub issue requesting better support for your use case.`, + ); + }) + .join('&'); + } + + private getUserAgent(): string { + return `${this.constructor.name}/JS ${VERSION}`; + } + + protected defaultIdempotencyKey(): string { + return `stainless-node-retry-${uuid4()}`; + } + + protected makeStatusError( + status: number, + error: Object, + message: string | undefined, + headers: Headers, + ): Errors.APIError { + return Errors.APIError.generate(status, error, message, headers); + } + + buildURL(path: string, query: Record | null | undefined): string { + const url = + isAbsoluteURL(path) ? + new URL(path) + : new URL(this.baseURL + (this.baseURL.endsWith('/') && path.startsWith('/') ? path.slice(1) : path)); + + const defaultQuery = this.defaultQuery(); + if (!isEmptyObj(defaultQuery)) { + query = { ...defaultQuery, ...query }; + } + + if (typeof query === 'object' && query && !Array.isArray(query)) { + url.search = this.stringifyQuery(query as Record); + } + + return url.toString(); + } + + /** + * Used as a callback for mutating the given `FinalRequestOptions` object. + */ + protected async prepareOptions(options: FinalRequestOptions): Promise {} + + /** + * Used as a callback for mutating the given `RequestInit` object. + * + * This is useful for cases where you want to add certain headers based off of + * the request properties, e.g. `method` or `url`. + */ + protected async prepareRequest( + request: RequestInit, + { url, options }: { url: string; options: FinalRequestOptions }, + ): Promise {} + + get(path: string, opts?: PromiseOrValue): APIPromise { + return this.methodRequest('get', path, opts); + } + + post(path: string, opts?: PromiseOrValue): APIPromise { + return this.methodRequest('post', path, opts); + } + + patch(path: string, opts?: PromiseOrValue): APIPromise { + return this.methodRequest('patch', path, opts); + } + + put(path: string, opts?: PromiseOrValue): APIPromise { + return this.methodRequest('put', path, opts); + } + + delete(path: string, opts?: PromiseOrValue): APIPromise { + return this.methodRequest('delete', path, opts); + } + + private methodRequest( + method: HTTPMethod, + path: string, + opts?: PromiseOrValue, + ): APIPromise { + return this.request( + Promise.resolve(opts).then((opts) => { + return { method, path, ...opts }; + }), + ); + } + + request( + options: PromiseOrValue, + remainingRetries: number | null = null, + ): APIPromise { + return new APIPromise(this, this.makeRequest(options, remainingRetries, undefined)); + } + + private async makeRequest( + optionsInput: PromiseOrValue, + retriesRemaining: number | null, + retryOfRequestLogID: string | undefined, + ): Promise { + const options = await optionsInput; + const maxRetries = options.maxRetries ?? this.maxRetries; + if (retriesRemaining == null) { + retriesRemaining = maxRetries; + } + + await this.prepareOptions(options); + + const { req, url, timeout } = this.buildRequest(options, { retryCount: maxRetries - retriesRemaining }); + + await this.prepareRequest(req, { url, options }); + + /** Not an API request ID, just for correlating local log entries. */ + const requestLogID = 'log_' + ((Math.random() * (1 << 24)) | 0).toString(16).padStart(6, '0'); + const retryLogStr = retryOfRequestLogID === undefined ? '' : `, retryOf: ${retryOfRequestLogID}`; + const startTime = Date.now(); + + loggerFor(this).debug( + `[${requestLogID}] sending request`, + formatRequestDetails({ + retryOfRequestLogID, + method: options.method, + url, + options, + headers: req.headers, + }), + ); + + if (options.signal?.aborted) { + throw new Errors.APIUserAbortError(); + } + + const controller = new AbortController(); + const response = await this.fetchWithTimeout(url, req, timeout, controller).catch(castToError); + const headersTime = Date.now(); + + if (response instanceof Error) { + const retryMessage = `retrying, ${retriesRemaining} attempts remaining`; + if (options.signal?.aborted) { + throw new Errors.APIUserAbortError(); + } + // detect native connection timeout errors + // deno throws "TypeError: error sending request for url (https://example/): client error (Connect): tcp connect error: Operation timed out (os error 60): Operation timed out (os error 60)" + // undici throws "TypeError: fetch failed" with cause "ConnectTimeoutError: Connect Timeout Error (attempted address: example:443, timeout: 1ms)" + // others do not provide enough information to distinguish timeouts from other connection errors + const isTimeout = + isAbortError(response) || + /timed? ?out/i.test(String(response) + ('cause' in response ? String(response.cause) : '')); + if (retriesRemaining) { + loggerFor(this).info( + `[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} - ${retryMessage}`, + ); + loggerFor(this).debug( + `[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} (${retryMessage})`, + formatRequestDetails({ + retryOfRequestLogID, + url, + durationMs: headersTime - startTime, + message: response.message, + }), + ); + return this.retryRequest(options, retriesRemaining, retryOfRequestLogID ?? requestLogID); + } + loggerFor(this).info( + `[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} - error; no more retries left`, + ); + loggerFor(this).debug( + `[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} (error; no more retries left)`, + formatRequestDetails({ + retryOfRequestLogID, + url, + durationMs: headersTime - startTime, + message: response.message, + }), + ); + if (isTimeout) { + throw new Errors.APIConnectionTimeoutError(); + } + throw new Errors.APIConnectionError({ cause: response }); + } + + const responseInfo = `[${requestLogID}${retryLogStr}] ${req.method} ${url} ${ + response.ok ? 'succeeded' : 'failed' + } with status ${response.status} in ${headersTime - startTime}ms`; + + if (!response.ok) { + const shouldRetry = this.shouldRetry(response); + if (retriesRemaining && shouldRetry) { + const retryMessage = `retrying, ${retriesRemaining} attempts remaining`; + + // We don't need the body of this response. + await Shims.CancelReadableStream(response.body); + loggerFor(this).info(`${responseInfo} - ${retryMessage}`); + loggerFor(this).debug( + `[${requestLogID}] response error (${retryMessage})`, + formatRequestDetails({ + retryOfRequestLogID, + url: response.url, + status: response.status, + headers: response.headers, + durationMs: headersTime - startTime, + }), + ); + return this.retryRequest( + options, + retriesRemaining, + retryOfRequestLogID ?? requestLogID, + response.headers, + ); + } + + const retryMessage = shouldRetry ? `error; no more retries left` : `error; not retryable`; + + loggerFor(this).info(`${responseInfo} - ${retryMessage}`); + + const errText = await response.text().catch((err: any) => castToError(err).message); + const errJSON = safeJSON(errText); + const errMessage = errJSON ? undefined : errText; + + loggerFor(this).debug( + `[${requestLogID}] response error (${retryMessage})`, + formatRequestDetails({ + retryOfRequestLogID, + url: response.url, + status: response.status, + headers: response.headers, + message: errMessage, + durationMs: Date.now() - startTime, + }), + ); + + const err = this.makeStatusError(response.status, errJSON, errMessage, response.headers); + throw err; + } + + loggerFor(this).info(responseInfo); + loggerFor(this).debug( + `[${requestLogID}] response start`, + formatRequestDetails({ + retryOfRequestLogID, + url: response.url, + status: response.status, + headers: response.headers, + durationMs: headersTime - startTime, + }), + ); + + return { response, options, controller, requestLogID, retryOfRequestLogID, startTime }; + } + + async fetchWithTimeout( + url: RequestInfo, + init: RequestInit | undefined, + ms: number, + controller: AbortController, + ): Promise { + const { signal, method, ...options } = init || {}; + if (signal) signal.addEventListener('abort', () => controller.abort()); + + const timeout = setTimeout(() => controller.abort(), ms); + + const isReadableBody = + ((globalThis as any).ReadableStream && options.body instanceof (globalThis as any).ReadableStream) || + (typeof options.body === 'object' && options.body !== null && Symbol.asyncIterator in options.body); + + const fetchOptions: RequestInit = { + signal: controller.signal as any, + ...(isReadableBody ? { duplex: 'half' } : {}), + method: 'GET', + ...options, + }; + if (method) { + // Custom methods like 'patch' need to be uppercased + // See https://github.com/nodejs/undici/issues/2294 + fetchOptions.method = method.toUpperCase(); + } + + try { + // use undefined this binding; fetch errors if bound to something else in browser/cloudflare + return await this.fetch.call(undefined, url, fetchOptions); + } finally { + clearTimeout(timeout); + } + } + + private shouldRetry(response: Response): boolean { + // Note this is not a standard header. + const shouldRetryHeader = response.headers.get('x-should-retry'); + + // If the server explicitly says whether or not to retry, obey. + if (shouldRetryHeader === 'true') return true; + if (shouldRetryHeader === 'false') return false; + + // Retry on request timeouts. + if (response.status === 408) return true; + + // Retry on lock timeouts. + if (response.status === 409) return true; + + // Retry on rate limits. + if (response.status === 429) return true; + + // Retry internal errors. + if (response.status >= 500) return true; + + return false; + } + + private async retryRequest( + options: FinalRequestOptions, + retriesRemaining: number, + requestLogID: string, + responseHeaders?: Headers | undefined, + ): Promise { + let timeoutMillis: number | undefined; + + // Note the `retry-after-ms` header may not be standard, but is a good idea and we'd like proactive support for it. + const retryAfterMillisHeader = responseHeaders?.get('retry-after-ms'); + if (retryAfterMillisHeader) { + const timeoutMs = parseFloat(retryAfterMillisHeader); + if (!Number.isNaN(timeoutMs)) { + timeoutMillis = timeoutMs; + } + } + + // About the Retry-After header: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After + const retryAfterHeader = responseHeaders?.get('retry-after'); + if (retryAfterHeader && !timeoutMillis) { + const timeoutSeconds = parseFloat(retryAfterHeader); + if (!Number.isNaN(timeoutSeconds)) { + timeoutMillis = timeoutSeconds * 1000; + } else { + timeoutMillis = Date.parse(retryAfterHeader) - Date.now(); + } + } + + // If the API asks us to wait a certain amount of time (and it's a reasonable amount), + // just do what it says, but otherwise calculate a default + if (!(timeoutMillis && 0 <= timeoutMillis && timeoutMillis < 60 * 1000)) { + const maxRetries = options.maxRetries ?? this.maxRetries; + timeoutMillis = this.calculateDefaultRetryTimeoutMillis(retriesRemaining, maxRetries); + } + await sleep(timeoutMillis); + + return this.makeRequest(options, retriesRemaining - 1, requestLogID); + } + + private calculateDefaultRetryTimeoutMillis(retriesRemaining: number, maxRetries: number): number { + const initialRetryDelay = 0.5; + const maxRetryDelay = 8.0; + + const numRetries = maxRetries - retriesRemaining; + + // Apply exponential backoff, but not more than the max. + const sleepSeconds = Math.min(initialRetryDelay * Math.pow(2, numRetries), maxRetryDelay); + + // Apply some jitter, take up to at most 25 percent of the retry time. + const jitter = 1 - Math.random() * 0.25; + + return sleepSeconds * jitter * 1000; + } + + buildRequest( + inputOptions: FinalRequestOptions, + { retryCount = 0 }: { retryCount?: number } = {}, + ): { req: FinalizedRequestInit; url: string; timeout: number } { + const options = { ...inputOptions }; + const { method, path, query } = options; + + const url = this.buildURL(path!, query as Record); + 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 req: FinalizedRequestInit = { + method, + headers: reqHeaders, + ...(options.signal && { signal: options.signal }), + ...((globalThis as any).ReadableStream && + body instanceof (globalThis as any).ReadableStream && { duplex: 'half' }), + ...(body && { body }), + ...((this.fetchOptions as any) ?? {}), + ...((options.fetchOptions as any) ?? {}), + }; + + return { req, url, timeout: options.timeout }; + } + + private buildHeaders({ + options, + method, + bodyHeaders, + retryCount, + }: { + options: FinalRequestOptions; + method: HTTPMethod; + bodyHeaders: HeadersLike; + retryCount: number; + }): Headers { + let idempotencyHeaders: HeadersLike = {}; + if (this.idempotencyHeader && method !== 'get') { + if (!options.idempotencyKey) options.idempotencyKey = this.defaultIdempotencyKey(); + idempotencyHeaders[this.idempotencyHeader] = options.idempotencyKey; + } + + const headers = buildHeaders([ + idempotencyHeaders, + { + Accept: 'application/json', + 'User-Agent': this.getUserAgent(), + 'X-Stainless-Retry-Count': String(retryCount), + ...(options.timeout ? { 'X-Stainless-Timeout': String(Math.trunc(options.timeout / 1000)) } : {}), + ...getPlatformHeaders(), + }, + this.authHeaders(options), + this._options.defaultHeaders, + bodyHeaders, + options.headers, + ]); + + this.validateHeaders(headers); + + return headers.values; + } + + private buildBody({ options: { body, headers: rawHeaders } }: { options: FinalRequestOptions }): { + bodyHeaders: HeadersLike; + body: BodyInit | undefined; + } { + if (!body) { + return { bodyHeaders: undefined, body: undefined }; + } + const headers = buildHeaders([rawHeaders]); + if ( + // Pass raw type verbatim + ArrayBuffer.isView(body) || + body instanceof ArrayBuffer || + body instanceof DataView || + (typeof body === 'string' && + // Preserve legacy string encoding behavior for now + headers.values.has('content-type')) || + // `Blob` is superset of `File` + body instanceof Blob || + // `FormData` -> `multipart/form-data` + body instanceof FormData || + // `URLSearchParams` -> `application/x-www-form-urlencoded` + body instanceof URLSearchParams || + // Send chunked stream (each chunk has own `length`) + ((globalThis as any).ReadableStream && body instanceof (globalThis as any).ReadableStream) + ) { + return { bodyHeaders: undefined, body: body as BodyInit }; + } else if ( + typeof body === 'object' && + (Symbol.asyncIterator in body || + (Symbol.iterator in body && 'next' in body && typeof body.next === 'function')) + ) { + return { bodyHeaders: undefined, body: Shims.ReadableStreamFrom(body as AsyncIterable) }; + } else { + return this.#encoder({ body, headers }); + } + } + + static Kernel = this; + static DEFAULT_TIMEOUT = 60000; // 1 minute + + static KernelError = Errors.KernelError; + static APIError = Errors.APIError; + static APIConnectionError = Errors.APIConnectionError; + static APIConnectionTimeoutError = Errors.APIConnectionTimeoutError; + static APIUserAbortError = Errors.APIUserAbortError; + static NotFoundError = Errors.NotFoundError; + static ConflictError = Errors.ConflictError; + static RateLimitError = Errors.RateLimitError; + static BadRequestError = Errors.BadRequestError; + static AuthenticationError = Errors.AuthenticationError; + static InternalServerError = Errors.InternalServerError; + static PermissionDeniedError = Errors.PermissionDeniedError; + static UnprocessableEntityError = Errors.UnprocessableEntityError; + + static toFile = Uploads.toFile; + + apps: API.Apps = new API.Apps(this); + browser: API.Browser = new API.Browser(this); +} +Kernel.Apps = Apps; +Kernel.Browser = Browser; +export declare namespace Kernel { + export type RequestOptions = Opts.RequestOptions; + + export { + Apps as Apps, + type AppDeployResponse as AppDeployResponse, + type AppInvokeResponse as AppInvokeResponse, + type AppRetrieveInvocationResponse as AppRetrieveInvocationResponse, + type AppDeployParams as AppDeployParams, + type AppInvokeParams as AppInvokeParams, + }; + + export { Browser as Browser, type BrowserCreateSessionResponse as BrowserCreateSessionResponse }; +} diff --git a/src/core/README.md b/src/core/README.md new file mode 100644 index 00000000..485fce86 --- /dev/null +++ b/src/core/README.md @@ -0,0 +1,3 @@ +# `core` + +This directory holds public modules implementing non-resource-specific SDK functionality. diff --git a/src/core/api-promise.ts b/src/core/api-promise.ts new file mode 100644 index 00000000..26c290e1 --- /dev/null +++ b/src/core/api-promise.ts @@ -0,0 +1,92 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { type Kernel } from '../client'; + +import { type PromiseOrValue } from '../internal/types'; +import { APIResponseProps, defaultParseResponse } from '../internal/parse'; + +/** + * A subclass of `Promise` providing additional helper methods + * for interacting with the SDK. + */ +export class APIPromise extends Promise { + private parsedPromise: Promise | undefined; + #client: Kernel; + + constructor( + client: Kernel, + private responsePromise: Promise, + private parseResponse: ( + client: Kernel, + props: APIResponseProps, + ) => PromiseOrValue = defaultParseResponse, + ) { + super((resolve) => { + // this is maybe a bit weird but this has to be a no-op to not implicitly + // parse the response body; instead .then, .catch, .finally are overridden + // to parse the response + resolve(null as any); + }); + this.#client = client; + } + + _thenUnwrap(transform: (data: T, props: APIResponseProps) => U): APIPromise { + return new APIPromise(this.#client, this.responsePromise, async (client, props) => + transform(await this.parseResponse(client, props), props), + ); + } + + /** + * Gets the raw `Response` instance instead of parsing the response + * data. + * + * If you want to parse the response body but still get the `Response` + * instance, you can use {@link withResponse()}. + * + * 👋 Getting the wrong TypeScript type for `Response`? + * Try setting `"moduleResolution": "NodeNext"` or add `"lib": ["DOM"]` + * to your `tsconfig.json`. + */ + asResponse(): Promise { + return this.responsePromise.then((p) => p.response); + } + + /** + * Gets the parsed response data and the raw `Response` instance. + * + * If you just want to get the raw `Response` instance without parsing it, + * you can use {@link asResponse()}. + * + * 👋 Getting the wrong TypeScript type for `Response`? + * Try setting `"moduleResolution": "NodeNext"` or add `"lib": ["DOM"]` + * to your `tsconfig.json`. + */ + async withResponse(): Promise<{ data: T; response: Response }> { + const [data, response] = await Promise.all([this.parse(), this.asResponse()]); + return { data, response }; + } + + private parse(): Promise { + if (!this.parsedPromise) { + this.parsedPromise = this.responsePromise.then((data) => this.parseResponse(this.#client, data)); + } + return this.parsedPromise; + } + + override then( + onfulfilled?: ((value: T) => TResult1 | PromiseLike) | undefined | null, + onrejected?: ((reason: any) => TResult2 | PromiseLike) | undefined | null, + ): Promise { + return this.parse().then(onfulfilled, onrejected); + } + + override catch( + onrejected?: ((reason: any) => TResult | PromiseLike) | undefined | null, + ): Promise { + return this.parse().catch(onrejected); + } + + override finally(onfinally?: (() => void) | undefined | null): Promise { + return this.parse().finally(onfinally); + } +} diff --git a/src/core/error.ts b/src/core/error.ts new file mode 100644 index 00000000..6bf61d5d --- /dev/null +++ b/src/core/error.ts @@ -0,0 +1,130 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { castToError } from '../internal/errors'; + +export class KernelError extends Error {} + +export class APIError< + TStatus extends number | undefined = number | undefined, + THeaders extends Headers | undefined = Headers | undefined, + TError extends Object | undefined = Object | undefined, +> extends KernelError { + /** HTTP status for the response that caused the error */ + readonly status: TStatus; + /** HTTP headers for the response that caused the error */ + readonly headers: THeaders; + /** JSON body of the response that caused the error */ + readonly error: TError; + + constructor(status: TStatus, error: TError, message: string | undefined, headers: THeaders) { + super(`${APIError.makeMessage(status, error, message)}`); + this.status = status; + this.headers = headers; + this.error = error; + } + + private static makeMessage(status: number | undefined, error: any, message: string | undefined) { + const msg = + error?.message ? + typeof error.message === 'string' ? + error.message + : JSON.stringify(error.message) + : error ? JSON.stringify(error) + : message; + + if (status && msg) { + return `${status} ${msg}`; + } + if (status) { + return `${status} status code (no body)`; + } + if (msg) { + return msg; + } + return '(no status code or body)'; + } + + static generate( + status: number | undefined, + errorResponse: Object | undefined, + message: string | undefined, + headers: Headers | undefined, + ): APIError { + if (!status || !headers) { + return new APIConnectionError({ message, cause: castToError(errorResponse) }); + } + + const error = errorResponse as Record; + + if (status === 400) { + return new BadRequestError(status, error, message, headers); + } + + if (status === 401) { + return new AuthenticationError(status, error, message, headers); + } + + if (status === 403) { + return new PermissionDeniedError(status, error, message, headers); + } + + if (status === 404) { + return new NotFoundError(status, error, message, headers); + } + + if (status === 409) { + return new ConflictError(status, error, message, headers); + } + + if (status === 422) { + return new UnprocessableEntityError(status, error, message, headers); + } + + if (status === 429) { + return new RateLimitError(status, error, message, headers); + } + + if (status >= 500) { + return new InternalServerError(status, error, message, headers); + } + + return new APIError(status, error, message, headers); + } +} + +export class APIUserAbortError extends APIError { + constructor({ message }: { message?: string } = {}) { + super(undefined, undefined, message || 'Request was aborted.', undefined); + } +} + +export class APIConnectionError extends APIError { + constructor({ message, cause }: { message?: string | undefined; cause?: Error | undefined }) { + super(undefined, undefined, message || 'Connection error.', undefined); + // in some environments the 'cause' property is already declared + // @ts-ignore + if (cause) this.cause = cause; + } +} + +export class APIConnectionTimeoutError extends APIConnectionError { + constructor({ message }: { message?: string } = {}) { + super({ message: message ?? 'Request timed out.' }); + } +} + +export class BadRequestError extends APIError<400, Headers> {} + +export class AuthenticationError extends APIError<401, Headers> {} + +export class PermissionDeniedError extends APIError<403, Headers> {} + +export class NotFoundError extends APIError<404, Headers> {} + +export class ConflictError extends APIError<409, Headers> {} + +export class UnprocessableEntityError extends APIError<422, Headers> {} + +export class RateLimitError extends APIError<429, Headers> {} + +export class InternalServerError extends APIError {} diff --git a/src/core/resource.ts b/src/core/resource.ts new file mode 100644 index 00000000..b8cfaddc --- /dev/null +++ b/src/core/resource.ts @@ -0,0 +1,11 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import type { Kernel } from '../client'; + +export class APIResource { + protected _client: Kernel; + + constructor(client: Kernel) { + this._client = client; + } +} diff --git a/src/core/uploads.ts b/src/core/uploads.ts new file mode 100644 index 00000000..2882ca6d --- /dev/null +++ b/src/core/uploads.ts @@ -0,0 +1,2 @@ +export { type Uploadable } from '../internal/uploads'; +export { toFile, type ToFileInput } from '../internal/to-file'; diff --git a/src/error.ts b/src/error.ts new file mode 100644 index 00000000..fc55f46c --- /dev/null +++ b/src/error.ts @@ -0,0 +1,2 @@ +/** @deprecated Import from ./core/error instead */ +export * from './core/error'; diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 00000000..114bf2c3 --- /dev/null +++ b/src/index.ts @@ -0,0 +1,22 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export { Kernel as default } from './client'; + +export { type Uploadable, toFile } from './core/uploads'; +export { APIPromise } from './core/api-promise'; +export { Kernel, type ClientOptions } from './client'; +export { + KernelError, + APIError, + APIConnectionError, + APIConnectionTimeoutError, + APIUserAbortError, + NotFoundError, + ConflictError, + RateLimitError, + BadRequestError, + AuthenticationError, + InternalServerError, + PermissionDeniedError, + UnprocessableEntityError, +} from './core/error'; diff --git a/src/internal/README.md b/src/internal/README.md new file mode 100644 index 00000000..3ef5a25b --- /dev/null +++ b/src/internal/README.md @@ -0,0 +1,3 @@ +# `internal` + +The modules in this directory are not importable outside this package and will change between releases. diff --git a/src/internal/builtin-types.ts b/src/internal/builtin-types.ts new file mode 100644 index 00000000..c23d3bde --- /dev/null +++ b/src/internal/builtin-types.ts @@ -0,0 +1,93 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export type Fetch = (input: string | URL | Request, init?: RequestInit) => Promise; + +/** + * An alias to the builtin `RequestInit` type so we can + * easily alias it in import statements if there are name clashes. + * + * https://developer.mozilla.org/docs/Web/API/RequestInit + */ +type _RequestInit = RequestInit; + +/** + * An alias to the builtin `Response` type so we can + * easily alias it in import statements if there are name clashes. + * + * https://developer.mozilla.org/docs/Web/API/Response + */ +type _Response = Response; + +/** + * The type for the first argument to `fetch`. + * + * https://developer.mozilla.org/docs/Web/API/Window/fetch#resource + */ +type _RequestInfo = Request | URL | string; + +/** + * The type for constructing `RequestInit` Headers. + * + * https://developer.mozilla.org/docs/Web/API/RequestInit#setting_headers + */ +type _HeadersInit = RequestInit['headers']; + +/** + * The type for constructing `RequestInit` body. + * + * https://developer.mozilla.org/docs/Web/API/RequestInit#body + */ +type _BodyInit = RequestInit['body']; + +/** + * An alias to the builtin `Array` type so we can + * easily alias it in import statements if there are name clashes. + */ +type _Array = Array; + +/** + * An alias to the builtin `Record` type so we can + * easily alias it in import statements if there are name clashes. + */ +type _Record = Record; + +export type { + _Array as Array, + _BodyInit as BodyInit, + _HeadersInit as HeadersInit, + _Record as Record, + _RequestInfo as RequestInfo, + _RequestInit as RequestInit, + _Response as Response, +}; + +/** + * A copy of the builtin `EndingType` type as it isn't fully supported in certain + * environments and attempting to reference the global version will error. + * + * https://github.com/microsoft/TypeScript/blob/49ad1a3917a0ea57f5ff248159256e12bb1cb705/src/lib/dom.generated.d.ts#L27941 + */ +type EndingType = 'native' | 'transparent'; + +/** + * A copy of the builtin `BlobPropertyBag` type as it isn't fully supported in certain + * environments and attempting to reference the global version will error. + * + * https://github.com/microsoft/TypeScript/blob/49ad1a3917a0ea57f5ff248159256e12bb1cb705/src/lib/dom.generated.d.ts#L154 + * https://developer.mozilla.org/en-US/docs/Web/API/Blob/Blob#options + */ +export interface BlobPropertyBag { + endings?: EndingType; + type?: string; +} + +/** + * A copy of the builtin `FilePropertyBag` type as it isn't fully supported in certain + * environments and attempting to reference the global version will error. + * + * https://github.com/microsoft/TypeScript/blob/49ad1a3917a0ea57f5ff248159256e12bb1cb705/src/lib/dom.generated.d.ts#L503 + * https://developer.mozilla.org/en-US/docs/Web/API/File/File#options + */ +export interface FilePropertyBag extends BlobPropertyBag { + lastModified?: number; +} diff --git a/src/internal/detect-platform.ts b/src/internal/detect-platform.ts new file mode 100644 index 00000000..c5e273b9 --- /dev/null +++ b/src/internal/detect-platform.ts @@ -0,0 +1,196 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { VERSION } from '../version'; + +export const isRunningInBrowser = () => { + return ( + // @ts-ignore + typeof window !== 'undefined' && + // @ts-ignore + typeof window.document !== 'undefined' && + // @ts-ignore + typeof navigator !== 'undefined' + ); +}; + +type DetectedPlatform = 'deno' | 'node' | 'edge' | 'unknown'; + +/** + * Note this does not detect 'browser'; for that, use getBrowserInfo(). + */ +function getDetectedPlatform(): DetectedPlatform { + if (typeof Deno !== 'undefined' && Deno.build != null) { + return 'deno'; + } + if (typeof EdgeRuntime !== 'undefined') { + return 'edge'; + } + if ( + Object.prototype.toString.call( + typeof (globalThis as any).process !== 'undefined' ? (globalThis as any).process : 0, + ) === '[object process]' + ) { + return 'node'; + } + return 'unknown'; +} + +declare const Deno: any; +declare const EdgeRuntime: any; +type Arch = 'x32' | 'x64' | 'arm' | 'arm64' | `other:${string}` | 'unknown'; +type PlatformName = + | 'MacOS' + | 'Linux' + | 'Windows' + | 'FreeBSD' + | 'OpenBSD' + | 'iOS' + | 'Android' + | `Other:${string}` + | 'Unknown'; +type Browser = 'ie' | 'edge' | 'chrome' | 'firefox' | 'safari'; +type PlatformProperties = { + 'X-Stainless-Lang': 'js'; + 'X-Stainless-Package-Version': string; + 'X-Stainless-OS': PlatformName; + 'X-Stainless-Arch': Arch; + 'X-Stainless-Runtime': 'node' | 'deno' | 'edge' | `browser:${Browser}` | 'unknown'; + 'X-Stainless-Runtime-Version': string; +}; +const getPlatformProperties = (): PlatformProperties => { + const detectedPlatform = getDetectedPlatform(); + if (detectedPlatform === 'deno') { + return { + 'X-Stainless-Lang': 'js', + 'X-Stainless-Package-Version': VERSION, + 'X-Stainless-OS': normalizePlatform(Deno.build.os), + 'X-Stainless-Arch': normalizeArch(Deno.build.arch), + 'X-Stainless-Runtime': 'deno', + 'X-Stainless-Runtime-Version': + typeof Deno.version === 'string' ? Deno.version : Deno.version?.deno ?? 'unknown', + }; + } + if (typeof EdgeRuntime !== 'undefined') { + return { + 'X-Stainless-Lang': 'js', + 'X-Stainless-Package-Version': VERSION, + 'X-Stainless-OS': 'Unknown', + 'X-Stainless-Arch': `other:${EdgeRuntime}`, + 'X-Stainless-Runtime': 'edge', + 'X-Stainless-Runtime-Version': (globalThis as any).process.version, + }; + } + // Check if Node.js + if (detectedPlatform === 'node') { + return { + 'X-Stainless-Lang': 'js', + 'X-Stainless-Package-Version': VERSION, + 'X-Stainless-OS': normalizePlatform((globalThis as any).process.platform), + 'X-Stainless-Arch': normalizeArch((globalThis as any).process.arch), + 'X-Stainless-Runtime': 'node', + 'X-Stainless-Runtime-Version': (globalThis as any).process.version, + }; + } + + const browserInfo = getBrowserInfo(); + if (browserInfo) { + return { + 'X-Stainless-Lang': 'js', + 'X-Stainless-Package-Version': VERSION, + 'X-Stainless-OS': 'Unknown', + 'X-Stainless-Arch': 'unknown', + 'X-Stainless-Runtime': `browser:${browserInfo.browser}`, + 'X-Stainless-Runtime-Version': browserInfo.version, + }; + } + + // TODO add support for Cloudflare workers, etc. + return { + 'X-Stainless-Lang': 'js', + 'X-Stainless-Package-Version': VERSION, + 'X-Stainless-OS': 'Unknown', + 'X-Stainless-Arch': 'unknown', + 'X-Stainless-Runtime': 'unknown', + 'X-Stainless-Runtime-Version': 'unknown', + }; +}; + +type BrowserInfo = { + browser: Browser; + version: string; +}; + +declare const navigator: { userAgent: string } | undefined; + +// Note: modified from https://github.com/JS-DevTools/host-environment/blob/b1ab79ecde37db5d6e163c050e54fe7d287d7c92/src/isomorphic.browser.ts +function getBrowserInfo(): BrowserInfo | null { + if (typeof navigator === 'undefined' || !navigator) { + return null; + } + + // NOTE: The order matters here! + const browserPatterns = [ + { key: 'edge' as const, pattern: /Edge(?:\W+(\d+)\.(\d+)(?:\.(\d+))?)?/ }, + { key: 'ie' as const, pattern: /MSIE(?:\W+(\d+)\.(\d+)(?:\.(\d+))?)?/ }, + { key: 'ie' as const, pattern: /Trident(?:.*rv\:(\d+)\.(\d+)(?:\.(\d+))?)?/ }, + { key: 'chrome' as const, pattern: /Chrome(?:\W+(\d+)\.(\d+)(?:\.(\d+))?)?/ }, + { key: 'firefox' as const, pattern: /Firefox(?:\W+(\d+)\.(\d+)(?:\.(\d+))?)?/ }, + { key: 'safari' as const, pattern: /(?:Version\W+(\d+)\.(\d+)(?:\.(\d+))?)?(?:\W+Mobile\S*)?\W+Safari/ }, + ]; + + // Find the FIRST matching browser + for (const { key, pattern } of browserPatterns) { + const match = pattern.exec(navigator.userAgent); + if (match) { + const major = match[1] || 0; + const minor = match[2] || 0; + const patch = match[3] || 0; + + return { browser: key, version: `${major}.${minor}.${patch}` }; + } + } + + return null; +} + +const normalizeArch = (arch: string): Arch => { + // Node docs: + // - https://nodejs.org/api/process.html#processarch + // Deno docs: + // - https://doc.deno.land/deno/stable/~/Deno.build + if (arch === 'x32') return 'x32'; + if (arch === 'x86_64' || arch === 'x64') return 'x64'; + if (arch === 'arm') return 'arm'; + if (arch === 'aarch64' || arch === 'arm64') return 'arm64'; + if (arch) return `other:${arch}`; + return 'unknown'; +}; + +const normalizePlatform = (platform: string): PlatformName => { + // Node platforms: + // - https://nodejs.org/api/process.html#processplatform + // Deno platforms: + // - https://doc.deno.land/deno/stable/~/Deno.build + // - https://github.com/denoland/deno/issues/14799 + + platform = platform.toLowerCase(); + + // NOTE: this iOS check is untested and may not work + // Node does not work natively on IOS, there is a fork at + // https://github.com/nodejs-mobile/nodejs-mobile + // however it is unknown at the time of writing how to detect if it is running + if (platform.includes('ios')) return 'iOS'; + if (platform === 'android') return 'Android'; + if (platform === 'darwin') return 'MacOS'; + if (platform === 'win32') return 'Windows'; + if (platform === 'freebsd') return 'FreeBSD'; + if (platform === 'openbsd') return 'OpenBSD'; + if (platform === 'linux') return 'Linux'; + if (platform) return `Other:${platform}`; + return 'Unknown'; +}; + +let _platformHeaders: PlatformProperties; +export const getPlatformHeaders = () => { + return (_platformHeaders ??= getPlatformProperties()); +}; diff --git a/src/internal/errors.ts b/src/internal/errors.ts new file mode 100644 index 00000000..82c7b14d --- /dev/null +++ b/src/internal/errors.ts @@ -0,0 +1,33 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export function isAbortError(err: unknown) { + return ( + typeof err === 'object' && + err !== null && + // Spec-compliant fetch implementations + (('name' in err && (err as any).name === 'AbortError') || + // Expo fetch + ('message' in err && String((err as any).message).includes('FetchRequestCanceledException'))) + ); +} + +export const castToError = (err: any): Error => { + if (err instanceof Error) return err; + if (typeof err === 'object' && err !== null) { + try { + if (Object.prototype.toString.call(err) === '[object Error]') { + // @ts-ignore - not all envs have native support for cause yet + const error = new Error(err.message, err.cause ? { cause: err.cause } : {}); + if (err.stack) error.stack = err.stack; + // @ts-ignore - not all envs have native support for cause yet + if (err.cause && !error.cause) error.cause = err.cause; + if (err.name) error.name = err.name; + return error; + } + } catch {} + try { + return new Error(JSON.stringify(err)); + } catch {} + } + return new Error(err); +}; diff --git a/src/internal/headers.ts b/src/internal/headers.ts new file mode 100644 index 00000000..8659ddea --- /dev/null +++ b/src/internal/headers.ts @@ -0,0 +1,97 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +type HeaderValue = string | undefined | null; +export type HeadersLike = + | Headers + | readonly HeaderValue[][] + | Record + | undefined + | null + | NullableHeaders; + +const brand_privateNullableHeaders = Symbol('brand.privateNullableHeaders'); + +/** + * @internal + * Users can pass explicit nulls to unset default headers. When we parse them + * into a standard headers type we need to preserve that information. + */ +export type NullableHeaders = { + /** Brand check, prevent users from creating a NullableHeaders. */ + [brand_privateNullableHeaders]: true; + /** Parsed headers. */ + values: Headers; + /** Set of lowercase header names explicitly set to null. */ + nulls: Set; +}; + +const isArray = Array.isArray as (val: unknown) => val is readonly unknown[]; + +function* iterateHeaders(headers: HeadersLike): IterableIterator { + if (!headers) return; + + if (brand_privateNullableHeaders in headers) { + const { values, nulls } = headers; + yield* values.entries(); + for (const name of nulls) { + yield [name, null]; + } + return; + } + + let shouldClear = false; + let iter: Iterable; + if (headers instanceof Headers) { + iter = headers.entries(); + } else if (isArray(headers)) { + iter = headers; + } else { + shouldClear = true; + iter = Object.entries(headers ?? {}); + } + for (let row of iter) { + const name = row[0]; + if (typeof name !== 'string') throw new TypeError('expected header name to be a string'); + const values = isArray(row[1]) ? row[1] : [row[1]]; + let didClear = false; + for (const value of values) { + if (value === undefined) continue; + + // Objects keys always overwrite older headers, they never append. + // Yield a null to clear the header before adding the new values. + if (shouldClear && !didClear) { + didClear = true; + yield [name, null]; + } + yield [name, value]; + } + } +} + +export const buildHeaders = (newHeaders: HeadersLike[]): NullableHeaders => { + const targetHeaders = new Headers(); + const nullHeaders = new Set(); + const seenHeaders = new Set(); + for (const headers of newHeaders) { + for (const [name, value] of iterateHeaders(headers)) { + const lowerName = name.toLowerCase(); + if (!seenHeaders.has(lowerName)) { + targetHeaders.delete(name); + seenHeaders.add(lowerName); + } + if (value === null) { + targetHeaders.delete(name); + nullHeaders.add(lowerName); + } else { + targetHeaders.append(name, value); + nullHeaders.delete(lowerName); + } + } + } + return { [brand_privateNullableHeaders]: true, values: targetHeaders, nulls: nullHeaders }; +}; + +export const isEmptyHeaders = (headers: HeadersLike) => { + for (const _ of iterateHeaders(headers)) return false; + return true; +}; diff --git a/src/internal/parse.ts b/src/internal/parse.ts new file mode 100644 index 00000000..53d4b80c --- /dev/null +++ b/src/internal/parse.ts @@ -0,0 +1,50 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import type { FinalRequestOptions } from './request-options'; +import { type Kernel } from '../client'; +import { formatRequestDetails, loggerFor } from './utils/log'; + +export type APIResponseProps = { + response: Response; + options: FinalRequestOptions; + controller: AbortController; + requestLogID: string; + retryOfRequestLogID: string | undefined; + startTime: number; +}; + +export async function defaultParseResponse(client: Kernel, props: APIResponseProps): Promise { + const { response, requestLogID, retryOfRequestLogID, startTime } = props; + const body = await (async () => { + // fetch refuses to read the body when the status code is 204. + if (response.status === 204) { + return null as T; + } + + if (props.options.__binaryResponse) { + return response as unknown as T; + } + + const contentType = response.headers.get('content-type'); + const mediaType = contentType?.split(';')[0]?.trim(); + const isJSON = mediaType?.includes('application/json') || mediaType?.endsWith('+json'); + if (isJSON) { + const json = await response.json(); + return json as T; + } + + const text = await response.text(); + return text as unknown as T; + })(); + loggerFor(client).debug( + `[${requestLogID}] response parsed`, + formatRequestDetails({ + retryOfRequestLogID, + url: response.url, + status: response.status, + body, + durationMs: Date.now() - startTime, + }), + ); + return body; +} diff --git a/src/internal/request-options.ts b/src/internal/request-options.ts new file mode 100644 index 00000000..d2ade9ec --- /dev/null +++ b/src/internal/request-options.ts @@ -0,0 +1,37 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { NullableHeaders } from './headers'; + +import type { BodyInit } from './builtin-types'; +import type { HTTPMethod, MergedRequestInit } from './types'; +import { type HeadersLike } from './headers'; + +export type FinalRequestOptions = RequestOptions & { method: HTTPMethod; path: string }; + +export type RequestOptions = { + method?: HTTPMethod; + path?: string; + query?: object | undefined | null; + body?: unknown; + headers?: HeadersLike; + maxRetries?: number; + stream?: boolean | undefined; + timeout?: number; + fetchOptions?: MergedRequestInit; + signal?: AbortSignal | undefined | null; + idempotencyKey?: string; + + __binaryResponse?: boolean | undefined; +}; + +export type EncodedContent = { bodyHeaders: HeadersLike; body: BodyInit }; +export type RequestEncoder = (request: { headers: NullableHeaders; body: unknown }) => EncodedContent; + +export const FallbackEncoder: RequestEncoder = ({ headers, body }) => { + return { + bodyHeaders: { + 'content-type': 'application/json', + }, + body: JSON.stringify(body), + }; +}; diff --git a/src/internal/shim-types.d.ts b/src/internal/shim-types.d.ts new file mode 100644 index 00000000..fe48144f --- /dev/null +++ b/src/internal/shim-types.d.ts @@ -0,0 +1,28 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +/** + * Shims for types that we can't always rely on being available globally. + * + * Note: these only exist at the type-level, there is no corresponding runtime + * version for any of these symbols. + */ + +/** + * In order to properly access the global `NodeJS` type, if it's available, we + * need to make use of declaration shadowing. Without this, any checks for the + * presence of `NodeJS.ReadableStream` will fail. + */ +declare namespace NodeJS { + interface ReadableStream {} +} + +type HasProperties = keyof T extends never ? false : true; + +// @ts-ignore +type _ReadableStream = + // @ts-ignore + HasProperties extends true ? NodeJS.ReadableStream : ReadableStream; + +// @ts-ignore +declare const _ReadableStream: unknown extends typeof ReadableStream ? never : typeof ReadableStream; +export { _ReadableStream as ReadableStream }; diff --git a/src/internal/shims.ts b/src/internal/shims.ts new file mode 100644 index 00000000..9b04cd93 --- /dev/null +++ b/src/internal/shims.ts @@ -0,0 +1,107 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +/** + * This module provides internal shims and utility functions for environments where certain Node.js or global types may not be available. + * + * These are used to ensure we can provide a consistent behaviour between different JavaScript environments and good error + * messages in cases where an environment isn't fully supported. + */ + +import { type Fetch } from './builtin-types'; +import { type ReadableStream } from './shim-types'; + +export function getDefaultFetch(): Fetch { + if (typeof fetch !== 'undefined') { + return fetch as any; + } + + throw new Error( + '`fetch` is not defined as a global; Either pass `fetch` to the client, `new Kernel({ fetch })` or polyfill the global, `globalThis.fetch = fetch`', + ); +} + +type ReadableStreamArgs = ConstructorParameters; + +export function makeReadableStream(...args: ReadableStreamArgs): ReadableStream { + const ReadableStream = (globalThis as any).ReadableStream; + if (typeof ReadableStream === 'undefined') { + // Note: All of the platforms / runtimes we officially support already define + // `ReadableStream` as a global, so this should only ever be hit on unsupported runtimes. + throw new Error( + '`ReadableStream` is not defined as a global; You will need to polyfill it, `globalThis.ReadableStream = ReadableStream`', + ); + } + + return new ReadableStream(...args); +} + +export function ReadableStreamFrom(iterable: Iterable | AsyncIterable): ReadableStream { + let iter: AsyncIterator | Iterator = + Symbol.asyncIterator in iterable ? iterable[Symbol.asyncIterator]() : iterable[Symbol.iterator](); + + return makeReadableStream({ + start() {}, + async pull(controller: any) { + const { done, value } = await iter.next(); + if (done) { + controller.close(); + } else { + controller.enqueue(value); + } + }, + async cancel() { + await iter.return?.(); + }, + }); +} + +/** + * Most browsers don't yet have async iterable support for ReadableStream, + * and Node has a very different way of reading bytes from its "ReadableStream". + * + * This polyfill was pulled from https://github.com/MattiasBuelens/web-streams-polyfill/pull/122#issuecomment-1627354490 + */ +export function ReadableStreamToAsyncIterable(stream: any): AsyncIterableIterator { + if (stream[Symbol.asyncIterator]) return stream; + + const reader = stream.getReader(); + return { + async next() { + try { + const result = await reader.read(); + if (result?.done) reader.releaseLock(); // release lock when stream becomes closed + return result; + } catch (e) { + reader.releaseLock(); // release lock when stream becomes errored + throw e; + } + }, + async return() { + const cancelPromise = reader.cancel(); + reader.releaseLock(); + await cancelPromise; + return { done: true, value: undefined }; + }, + [Symbol.asyncIterator]() { + return this; + }, + }; +} + +/** + * Cancels a ReadableStream we don't need to consume. + * See https://undici.nodejs.org/#/?id=garbage-collection + */ +export async function CancelReadableStream(stream: any): Promise { + if (stream === null || typeof stream !== 'object') return; + + if (stream[Symbol.asyncIterator]) { + await stream[Symbol.asyncIterator]().return?.(); + return; + } + + const reader = stream.getReader(); + const cancelPromise = reader.cancel(); + reader.releaseLock(); + await cancelPromise; +} diff --git a/src/internal/to-file.ts b/src/internal/to-file.ts new file mode 100644 index 00000000..245e8493 --- /dev/null +++ b/src/internal/to-file.ts @@ -0,0 +1,154 @@ +import { BlobPart, getName, makeFile, isAsyncIterable } from './uploads'; +import type { FilePropertyBag } from './builtin-types'; +import { checkFileSupport } from './uploads'; + +type BlobLikePart = string | ArrayBuffer | ArrayBufferView | BlobLike | DataView; + +/** + * Intended to match DOM Blob, node-fetch Blob, node:buffer Blob, etc. + * Don't add arrayBuffer here, node-fetch doesn't have it + */ +interface BlobLike { + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Blob/size) */ + readonly size: number; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Blob/type) */ + readonly type: string; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Blob/text) */ + text(): Promise; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Blob/slice) */ + slice(start?: number, end?: number): BlobLike; +} + +/** + * This check adds the arrayBuffer() method type because it is available and used at runtime + */ +const isBlobLike = (value: any): value is BlobLike & { arrayBuffer(): Promise } => + value != null && + typeof value === 'object' && + typeof value.size === 'number' && + typeof value.type === 'string' && + typeof value.text === 'function' && + typeof value.slice === 'function' && + typeof value.arrayBuffer === 'function'; + +/** + * Intended to match DOM File, node:buffer File, undici File, etc. + */ +interface FileLike extends BlobLike { + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/File/lastModified) */ + readonly lastModified: number; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/File/name) */ + readonly name?: string | undefined; +} + +/** + * This check adds the arrayBuffer() method type because it is available and used at runtime + */ +const isFileLike = (value: any): value is FileLike & { arrayBuffer(): Promise } => + value != null && + typeof value === 'object' && + typeof value.name === 'string' && + typeof value.lastModified === 'number' && + isBlobLike(value); + +/** + * Intended to match DOM Response, node-fetch Response, undici Response, etc. + */ +export interface ResponseLike { + url: string; + blob(): Promise; +} + +const isResponseLike = (value: any): value is ResponseLike => + value != null && + typeof value === 'object' && + typeof value.url === 'string' && + typeof value.blob === 'function'; + +export type ToFileInput = + | FileLike + | ResponseLike + | Exclude + | AsyncIterable; + +/** + * Helper for creating a {@link File} to pass to an SDK upload method from a variety of different data formats + * @param value the raw content of the file. Can be an {@link Uploadable}, {@link BlobLikePart}, or {@link AsyncIterable} of {@link BlobLikePart}s + * @param {string=} name the name of the file. If omitted, toFile will try to determine a file name from bits if possible + * @param {Object=} options additional properties + * @param {string=} options.type the MIME type of the content + * @param {number=} options.lastModified the last modified timestamp + * @returns a {@link File} with the given properties + */ +export async function toFile( + value: ToFileInput | PromiseLike, + name?: string | null | undefined, + options?: FilePropertyBag | undefined, +): Promise { + checkFileSupport(); + + // If it's a promise, resolve it. + value = await value; + + // If we've been given a `File` we don't need to do anything + if (isFileLike(value)) { + if (value instanceof File) { + return value; + } + return makeFile([await value.arrayBuffer()], value.name); + } + + if (isResponseLike(value)) { + const blob = await value.blob(); + name ||= new URL(value.url).pathname.split(/[\\/]/).pop(); + + return makeFile(await getBytes(blob), name, options); + } + + const parts = await getBytes(value); + + name ||= getName(value); + + if (!options?.type) { + const type = parts.find((part) => typeof part === 'object' && 'type' in part && part.type); + if (typeof type === 'string') { + options = { ...options, type }; + } + } + + return makeFile(parts, name, options); +} + +async function getBytes(value: BlobLikePart | AsyncIterable): Promise> { + let parts: Array = []; + if ( + typeof value === 'string' || + ArrayBuffer.isView(value) || // includes Uint8Array, Buffer, etc. + value instanceof ArrayBuffer + ) { + parts.push(value); + } else if (isBlobLike(value)) { + parts.push(value instanceof Blob ? value : await value.arrayBuffer()); + } else if ( + isAsyncIterable(value) // includes Readable, ReadableStream, etc. + ) { + for await (const chunk of value) { + parts.push(...(await getBytes(chunk as BlobLikePart))); // TODO, consider validating? + } + } else { + const constructor = value?.constructor?.name; + throw new Error( + `Unexpected data type: ${typeof value}${ + constructor ? `; constructor: ${constructor}` : '' + }${propsForError(value)}`, + ); + } + + return parts; +} + +function propsForError(value: unknown): string { + if (typeof value !== 'object' || value === null) return ''; + const props = Object.getOwnPropertyNames(value); + return `; props: [${props.map((p) => `"${p}"`).join(', ')}]`; +} diff --git a/src/internal/types.ts b/src/internal/types.ts new file mode 100644 index 00000000..d7928cd3 --- /dev/null +++ b/src/internal/types.ts @@ -0,0 +1,92 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export type PromiseOrValue = T | Promise; +export type HTTPMethod = 'get' | 'post' | 'put' | 'patch' | 'delete'; + +export type KeysEnum = { [P in keyof Required]: true }; + +export type FinalizedRequestInit = RequestInit & { headers: Headers }; + +type NotAny = [unknown] extends [T] ? never : T; + +/** + * Some environments overload the global fetch function, and Parameters only gets the last signature. + */ +type OverloadedParameters = + T extends ( + { + (...args: infer A): unknown; + (...args: infer B): unknown; + (...args: infer C): unknown; + (...args: infer D): unknown; + } + ) ? + A | B | C | D + : T extends ( + { + (...args: infer A): unknown; + (...args: infer B): unknown; + (...args: infer C): unknown; + } + ) ? + A | B | C + : T extends ( + { + (...args: infer A): unknown; + (...args: infer B): unknown; + } + ) ? + A | B + : T extends (...args: infer A) => unknown ? A + : never; + +/* eslint-disable */ +/** + * These imports attempt to get types from a parent package's dependencies. + * Unresolved bare specifiers can trigger [automatic type acquisition][1] in some projects, which + * would cause typescript to show types not present at runtime. To avoid this, we import + * directly from parent node_modules folders. + * + * We need to check multiple levels because we don't know what directory structure we'll be in. + * For example, pnpm generates directories like this: + * ``` + * node_modules + * ├── .pnpm + * │ └── pkg@1.0.0 + * │ └── node_modules + * │ └── pkg + * │ └── internal + * │ └── types.d.ts + * ├── pkg -> .pnpm/pkg@1.0.0/node_modules/pkg + * └── undici + * ``` + * + * [1]: https://www.typescriptlang.org/tsconfig/#typeAcquisition + */ +/** @ts-ignore For users with \@types/node */ +type UndiciTypesRequestInit = NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny; +/** @ts-ignore For users with undici */ +type UndiciRequestInit = NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny; +/** @ts-ignore For users with \@types/bun */ +type BunRequestInit = globalThis.FetchRequestInit; +/** @ts-ignore For users with node-fetch */ +type NodeFetchRequestInit = NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny; +/** @ts-ignore For users who use Deno */ +type FetchRequestInit = NonNullable[1]>; +/* eslint-enable */ + +type RequestInits = + | NotAny + | NotAny + | NotAny + | NotAny + | NotAny + | NotAny; + +/** + * This type contains `RequestInit` options that may be available on the current runtime, + * including per-platform extensions like `dispatcher`, `agent`, `client`, etc. + */ +export type MergedRequestInit = RequestInits & + /** We don't include these in the types as they'll be overridden for every request. */ + Partial>; diff --git a/src/internal/uploads.ts b/src/internal/uploads.ts new file mode 100644 index 00000000..a708afa3 --- /dev/null +++ b/src/internal/uploads.ts @@ -0,0 +1,187 @@ +import { type RequestOptions } from './request-options'; +import type { FilePropertyBag, Fetch } from './builtin-types'; +import type { Kernel } from '../client'; +import { ReadableStreamFrom } from './shims'; + +export type BlobPart = string | ArrayBuffer | ArrayBufferView | Blob | DataView; +type FsReadStream = AsyncIterable & { path: string | { toString(): string } }; + +// https://github.com/oven-sh/bun/issues/5980 +interface BunFile extends Blob { + readonly name?: string | undefined; +} + +export const checkFileSupport = () => { + if (typeof File === 'undefined') { + const { process } = globalThis as any; + const isOldNode = + typeof process?.versions?.node === 'string' && parseInt(process.versions.node.split('.')) < 20; + throw new Error( + '`File` is not defined as a global, which is required for file uploads.' + + (isOldNode ? + " Update to Node 20 LTS or newer, or set `globalThis.File` to `import('node:buffer').File`." + : ''), + ); + } +}; + +/** + * Typically, this is a native "File" class. + * + * We provide the {@link toFile} utility to convert a variety of objects + * into the File class. + * + * For convenience, you can also pass a fetch Response, or in Node, + * the result of fs.createReadStream(). + */ +export type Uploadable = File | Response | FsReadStream | BunFile; + +/** + * Construct a `File` instance. This is used to ensure a helpful error is thrown + * for environments that don't define a global `File` yet. + */ +export function makeFile( + fileBits: BlobPart[], + fileName: string | undefined, + options?: FilePropertyBag, +): File { + checkFileSupport(); + return new File(fileBits as any, fileName ?? 'unknown_file', options); +} + +export function getName(value: any): string | undefined { + return ( + ( + (typeof value === 'object' && + value !== null && + (('name' in value && value.name && String(value.name)) || + ('url' in value && value.url && String(value.url)) || + ('filename' in value && value.filename && String(value.filename)) || + ('path' in value && value.path && String(value.path)))) || + '' + ) + .split(/[\\/]/) + .pop() || undefined + ); +} + +export const isAsyncIterable = (value: any): value is AsyncIterable => + value != null && typeof value === 'object' && typeof value[Symbol.asyncIterator] === 'function'; + +/** + * Returns a multipart/form-data request if any part of the given request body contains a File / Blob value. + * Otherwise returns the request as is. + */ +export const maybeMultipartFormRequestOptions = async ( + opts: RequestOptions, + fetch: Kernel | Fetch, +): Promise => { + if (!hasUploadableValue(opts.body)) return opts; + + return { ...opts, body: await createForm(opts.body, fetch) }; +}; + +type MultipartFormRequestOptions = Omit & { body: unknown }; + +export const multipartFormRequestOptions = async ( + opts: MultipartFormRequestOptions, + fetch: Kernel | Fetch, +): Promise => { + return { ...opts, body: await createForm(opts.body, fetch) }; +}; + +const supportsFormDataMap = new WeakMap>(); + +/** + * node-fetch doesn't support the global FormData object in recent node versions. Instead of sending + * properly-encoded form data, it just stringifies the object, resulting in a request body of "[object FormData]". + * This function detects if the fetch function provided supports the global FormData object to avoid + * confusing error messages later on. + */ +function supportsFormData(fetchObject: Kernel | Fetch): Promise { + const fetch: Fetch = typeof fetchObject === 'function' ? fetchObject : (fetchObject as any).fetch; + const cached = supportsFormDataMap.get(fetch); + if (cached) return cached; + const promise = (async () => { + try { + const FetchResponse = ( + 'Response' in fetch ? + fetch.Response + : (await fetch('data:,')).constructor) as typeof Response; + const data = new FormData(); + if (data.toString() === (await new FetchResponse(data).text())) { + return false; + } + return true; + } catch { + // avoid false negatives + return true; + } + })(); + supportsFormDataMap.set(fetch, promise); + return promise; +} + +export const createForm = async >( + body: T | undefined, + fetch: Kernel | Fetch, +): Promise => { + if (!(await supportsFormData(fetch))) { + throw new TypeError( + 'The provided fetch function does not support file uploads with the current global FormData class.', + ); + } + const form = new FormData(); + await Promise.all(Object.entries(body || {}).map(([key, value]) => addFormValue(form, key, value))); + return form; +}; + +// We check for Blob not File because Bun.File doesn't inherit from File, +// but they both inherit from Blob and have a `name` property at runtime. +const isNamedBlob = (value: object) => value instanceof Blob && 'name' in value; + +const isUploadable = (value: unknown) => + typeof value === 'object' && + value !== null && + (value instanceof Response || isAsyncIterable(value) || isNamedBlob(value)); + +const hasUploadableValue = (value: unknown): boolean => { + if (isUploadable(value)) return true; + if (Array.isArray(value)) return value.some(hasUploadableValue); + if (value && typeof value === 'object') { + for (const k in value) { + if (hasUploadableValue((value as any)[k])) return true; + } + } + return false; +}; + +const addFormValue = async (form: FormData, key: string, value: unknown): Promise => { + if (value === undefined) return; + if (value == null) { + throw new TypeError( + `Received null for "${key}"; to pass null in FormData, you must use the string 'null'`, + ); + } + + // TODO: make nested formats configurable + if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') { + form.append(key, String(value)); + } else if (value instanceof Response) { + form.append(key, makeFile([await value.blob()], getName(value))); + } else if (isAsyncIterable(value)) { + form.append(key, makeFile([await new Response(ReadableStreamFrom(value)).blob()], getName(value))); + } else if (isNamedBlob(value)) { + form.append(key, value, getName(value)); + } else if (Array.isArray(value)) { + await Promise.all(value.map((entry) => addFormValue(form, key + '[]', entry))); + } else if (typeof value === 'object') { + await Promise.all( + Object.entries(value).map(([name, prop]) => addFormValue(form, `${key}[${name}]`, prop)), + ); + } else { + throw new TypeError( + `Invalid value given to form, expected a string, number, boolean, object, Array, File or Blob but got ${value} instead`, + ); + } +}; diff --git a/src/internal/utils.ts b/src/internal/utils.ts new file mode 100644 index 00000000..3cbfacce --- /dev/null +++ b/src/internal/utils.ts @@ -0,0 +1,8 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export * from './utils/values'; +export * from './utils/base64'; +export * from './utils/env'; +export * from './utils/log'; +export * from './utils/uuid'; +export * from './utils/sleep'; diff --git a/src/internal/utils/base64.ts b/src/internal/utils/base64.ts new file mode 100644 index 00000000..21ed0090 --- /dev/null +++ b/src/internal/utils/base64.ts @@ -0,0 +1,40 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { KernelError } from '../../core/error'; +import { encodeUTF8 } from './bytes'; + +export const toBase64 = (data: string | Uint8Array | null | undefined): string => { + if (!data) return ''; + + if (typeof (globalThis as any).Buffer !== 'undefined') { + return (globalThis as any).Buffer.from(data).toString('base64'); + } + + if (typeof data === 'string') { + data = encodeUTF8(data); + } + + if (typeof btoa !== 'undefined') { + return btoa(String.fromCharCode.apply(null, data as any)); + } + + throw new KernelError('Cannot generate base64 string; Expected `Buffer` or `btoa` to be defined'); +}; + +export const fromBase64 = (str: string): Uint8Array => { + if (typeof (globalThis as any).Buffer !== 'undefined') { + const buf = (globalThis as any).Buffer.from(str, 'base64'); + return new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength); + } + + if (typeof atob !== 'undefined') { + const bstr = atob(str); + const buf = new Uint8Array(bstr.length); + for (let i = 0; i < bstr.length; i++) { + buf[i] = bstr.charCodeAt(i); + } + return buf; + } + + throw new KernelError('Cannot decode base64 string; Expected `Buffer` or `atob` to be defined'); +}; diff --git a/src/internal/utils/bytes.ts b/src/internal/utils/bytes.ts new file mode 100644 index 00000000..8da627ab --- /dev/null +++ b/src/internal/utils/bytes.ts @@ -0,0 +1,32 @@ +export function concatBytes(buffers: Uint8Array[]): Uint8Array { + let length = 0; + for (const buffer of buffers) { + length += buffer.length; + } + const output = new Uint8Array(length); + let index = 0; + for (const buffer of buffers) { + output.set(buffer, index); + index += buffer.length; + } + + return output; +} + +let encodeUTF8_: (str: string) => Uint8Array; +export function encodeUTF8(str: string) { + let encoder; + return ( + encodeUTF8_ ?? + ((encoder = new (globalThis as any).TextEncoder()), (encodeUTF8_ = encoder.encode.bind(encoder))) + )(str); +} + +let decodeUTF8_: (bytes: Uint8Array) => string; +export function decodeUTF8(bytes: Uint8Array) { + let decoder; + return ( + decodeUTF8_ ?? + ((decoder = new (globalThis as any).TextDecoder()), (decodeUTF8_ = decoder.decode.bind(decoder))) + )(bytes); +} diff --git a/src/internal/utils/env.ts b/src/internal/utils/env.ts new file mode 100644 index 00000000..2d848007 --- /dev/null +++ b/src/internal/utils/env.ts @@ -0,0 +1,18 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +/** + * Read an environment variable. + * + * Trims beginning and trailing whitespace. + * + * Will return undefined if the environment variable doesn't exist or cannot be accessed. + */ +export const readEnv = (env: string): string | undefined => { + if (typeof (globalThis as any).process !== 'undefined') { + return (globalThis as any).process.env?.[env]?.trim() ?? undefined; + } + if (typeof (globalThis as any).Deno !== 'undefined') { + return (globalThis as any).Deno.env?.get?.(env)?.trim(); + } + return undefined; +}; diff --git a/src/internal/utils/log.ts b/src/internal/utils/log.ts new file mode 100644 index 00000000..48652621 --- /dev/null +++ b/src/internal/utils/log.ts @@ -0,0 +1,126 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { hasOwn } from './values'; +import { type Kernel } from '../../client'; +import { RequestOptions } from '../request-options'; + +type LogFn = (message: string, ...rest: unknown[]) => void; +export type Logger = { + error: LogFn; + warn: LogFn; + info: LogFn; + debug: LogFn; +}; +export type LogLevel = 'off' | 'error' | 'warn' | 'info' | 'debug'; + +const levelNumbers = { + off: 0, + error: 200, + warn: 300, + info: 400, + debug: 500, +}; + +export const parseLogLevel = ( + maybeLevel: string | undefined, + sourceName: string, + client: Kernel, +): LogLevel | undefined => { + if (!maybeLevel) { + return undefined; + } + if (hasOwn(levelNumbers, maybeLevel)) { + return maybeLevel; + } + loggerFor(client).warn( + `${sourceName} was set to ${JSON.stringify(maybeLevel)}, expected one of ${JSON.stringify( + Object.keys(levelNumbers), + )}`, + ); + return undefined; +}; + +function noop() {} + +function makeLogFn(fnLevel: keyof Logger, logger: Logger | undefined, logLevel: LogLevel) { + if (!logger || levelNumbers[fnLevel] > levelNumbers[logLevel]) { + return noop; + } else { + // Don't wrap logger functions, we want the stacktrace intact! + return logger[fnLevel].bind(logger); + } +} + +const noopLogger = { + error: noop, + warn: noop, + info: noop, + debug: noop, +}; + +let cachedLoggers = new WeakMap(); + +export function loggerFor(client: Kernel): Logger { + const logger = client.logger; + const logLevel = client.logLevel ?? 'off'; + if (!logger) { + return noopLogger; + } + + const cachedLogger = cachedLoggers.get(logger); + if (cachedLogger && cachedLogger[0] === logLevel) { + return cachedLogger[1]; + } + + const levelLogger = { + error: makeLogFn('error', logger, logLevel), + warn: makeLogFn('warn', logger, logLevel), + info: makeLogFn('info', logger, logLevel), + debug: makeLogFn('debug', logger, logLevel), + }; + + cachedLoggers.set(logger, [logLevel, levelLogger]); + + return levelLogger; +} + +export const formatRequestDetails = (details: { + options?: RequestOptions | undefined; + headers?: Headers | Record | undefined; + retryOfRequestLogID?: string | undefined; + retryOf?: string | undefined; + url?: string | undefined; + status?: number | undefined; + method?: string | undefined; + durationMs?: number | undefined; + message?: unknown; + body?: unknown; +}) => { + if (details.options) { + details.options = { ...details.options }; + delete details.options['headers']; // redundant + leaks internals + } + if (details.headers) { + details.headers = Object.fromEntries( + (details.headers instanceof Headers ? [...details.headers] : Object.entries(details.headers)).map( + ([name, value]) => [ + name, + ( + name.toLowerCase() === 'authorization' || + name.toLowerCase() === 'cookie' || + name.toLowerCase() === 'set-cookie' + ) ? + '***' + : value, + ], + ), + ); + } + if ('retryOfRequestLogID' in details) { + if (details.retryOfRequestLogID) { + details.retryOf = details.retryOfRequestLogID; + } + delete details.retryOfRequestLogID; + } + return details; +}; diff --git a/src/internal/utils/path.ts b/src/internal/utils/path.ts new file mode 100644 index 00000000..e9bcaf52 --- /dev/null +++ b/src/internal/utils/path.ts @@ -0,0 +1,63 @@ +import { KernelError } from '../../core/error'; + +/** + * Percent-encode everything that isn't safe to have in a path without encoding safe chars. + * + * Taken from https://datatracker.ietf.org/doc/html/rfc3986#section-3.3: + * > unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" + * > sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "=" + * > pchar = unreserved / pct-encoded / sub-delims / ":" / "@" + */ +export function encodeURIPath(str: string) { + return str.replace(/[^A-Za-z0-9\-._~!$&'()*+,;=:@]+/g, encodeURIComponent); +} + +export const createPathTagFunction = (pathEncoder = encodeURIPath) => + function path(statics: readonly string[], ...params: readonly unknown[]): string { + // If there are no params, no processing is needed. + if (statics.length === 1) return statics[0]!; + + let postPath = false; + const path = statics.reduce((previousValue, currentValue, index) => { + if (/[?#]/.test(currentValue)) { + postPath = true; + } + return ( + previousValue + + currentValue + + (index === params.length ? '' : (postPath ? encodeURIComponent : pathEncoder)(String(params[index]))) + ); + }, ''); + + const pathOnly = path.split(/[?#]/, 1)[0]!; + const invalidSegments = []; + const invalidSegmentPattern = /(?<=^|\/)(?:\.|%2e){1,2}(?=\/|$)/gi; + let match; + + // Find all invalid segments + while ((match = invalidSegmentPattern.exec(pathOnly)) !== null) { + invalidSegments.push({ + start: match.index, + length: match[0].length, + }); + } + + if (invalidSegments.length > 0) { + let lastEnd = 0; + const underline = invalidSegments.reduce((acc, segment) => { + const spaces = ' '.repeat(segment.start - lastEnd); + const arrows = '^'.repeat(segment.length); + lastEnd = segment.start + segment.length; + return acc + spaces + arrows; + }, ''); + + throw new KernelError(`Path parameters result in path with invalid segments:\n${path}\n${underline}`); + } + + return path; + }; + +/** + * URI-encodes path params and ensures no unsafe /./ or /../ path segments are introduced. + */ +export const path = createPathTagFunction(encodeURIPath); diff --git a/src/internal/utils/sleep.ts b/src/internal/utils/sleep.ts new file mode 100644 index 00000000..65e52962 --- /dev/null +++ b/src/internal/utils/sleep.ts @@ -0,0 +1,3 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)); diff --git a/src/internal/utils/uuid.ts b/src/internal/utils/uuid.ts new file mode 100644 index 00000000..b0e53aaf --- /dev/null +++ b/src/internal/utils/uuid.ts @@ -0,0 +1,17 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +/** + * https://stackoverflow.com/a/2117523 + */ +export let uuid4 = function () { + const { crypto } = globalThis as any; + if (crypto?.randomUUID) { + uuid4 = crypto.randomUUID.bind(crypto); + return crypto.randomUUID(); + } + const u8 = new Uint8Array(1); + const randomByte = crypto ? () => crypto.getRandomValues(u8)[0]! : () => (Math.random() * 0xff) & 0xff; + return '10000000-1000-4000-8000-100000000000'.replace(/[018]/g, (c) => + (+c ^ (randomByte() & (15 >> (+c / 4)))).toString(16), + ); +}; diff --git a/src/internal/utils/values.ts b/src/internal/utils/values.ts new file mode 100644 index 00000000..0953aeae --- /dev/null +++ b/src/internal/utils/values.ts @@ -0,0 +1,102 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { KernelError } from '../../core/error'; + +// https://url.spec.whatwg.org/#url-scheme-string +const startsWithSchemeRegexp = /^[a-z][a-z0-9+.-]*:/i; + +export const isAbsoluteURL = (url: string): boolean => { + return startsWithSchemeRegexp.test(url); +}; + +/** Returns an object if the given value isn't an object, otherwise returns as-is */ +export function maybeObj(x: unknown): object { + if (typeof x !== 'object') { + return {}; + } + + return x ?? {}; +} + +// https://stackoverflow.com/a/34491287 +export function isEmptyObj(obj: Object | null | undefined): boolean { + if (!obj) return true; + for (const _k in obj) return false; + return true; +} + +// https://eslint.org/docs/latest/rules/no-prototype-builtins +export function hasOwn(obj: T, key: PropertyKey): key is keyof T { + return Object.prototype.hasOwnProperty.call(obj, key); +} + +export function isObj(obj: unknown): obj is Record { + return obj != null && typeof obj === 'object' && !Array.isArray(obj); +} + +export const ensurePresent = (value: T | null | undefined): T => { + if (value == null) { + throw new KernelError(`Expected a value to be given but received ${value} instead.`); + } + + return value; +}; + +export const validatePositiveInteger = (name: string, n: unknown): number => { + if (typeof n !== 'number' || !Number.isInteger(n)) { + throw new KernelError(`${name} must be an integer`); + } + if (n < 0) { + throw new KernelError(`${name} must be a positive integer`); + } + return n; +}; + +export const coerceInteger = (value: unknown): number => { + if (typeof value === 'number') return Math.round(value); + if (typeof value === 'string') return parseInt(value, 10); + + throw new KernelError(`Could not coerce ${value} (type: ${typeof value}) into a number`); +}; + +export const coerceFloat = (value: unknown): number => { + if (typeof value === 'number') return value; + if (typeof value === 'string') return parseFloat(value); + + throw new KernelError(`Could not coerce ${value} (type: ${typeof value}) into a number`); +}; + +export const coerceBoolean = (value: unknown): boolean => { + if (typeof value === 'boolean') return value; + if (typeof value === 'string') return value === 'true'; + return Boolean(value); +}; + +export const maybeCoerceInteger = (value: unknown): number | undefined => { + if (value === undefined) { + return undefined; + } + return coerceInteger(value); +}; + +export const maybeCoerceFloat = (value: unknown): number | undefined => { + if (value === undefined) { + return undefined; + } + return coerceFloat(value); +}; + +export const maybeCoerceBoolean = (value: unknown): boolean | undefined => { + if (value === undefined) { + return undefined; + } + return coerceBoolean(value); +}; + +export const safeJSON = (text: string) => { + try { + return JSON.parse(text); + } catch (err) { + return undefined; + } +}; diff --git a/src/lib/.keep b/src/lib/.keep new file mode 100644 index 00000000..7554f8b2 --- /dev/null +++ b/src/lib/.keep @@ -0,0 +1,4 @@ +File generated from our OpenAPI spec by Stainless. + +This directory can be used to store custom files to expand the SDK. +It is ignored by Stainless code generation and its content (other than this keep file) won't be touched. diff --git a/src/resource.ts b/src/resource.ts new file mode 100644 index 00000000..363e3516 --- /dev/null +++ b/src/resource.ts @@ -0,0 +1,2 @@ +/** @deprecated Import from ./core/resource instead */ +export * from './core/resource'; diff --git a/src/resources.ts b/src/resources.ts new file mode 100644 index 00000000..b283d578 --- /dev/null +++ b/src/resources.ts @@ -0,0 +1 @@ +export * from './resources/index'; diff --git a/src/resources/apps.ts b/src/resources/apps.ts new file mode 100644 index 00000000..c2e4a953 --- /dev/null +++ b/src/resources/apps.ts @@ -0,0 +1,150 @@ +// 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 { type Uploadable } from '../core/uploads'; +import { RequestOptions } from '../internal/request-options'; +import { multipartFormRequestOptions } from '../internal/uploads'; +import { path } from '../internal/utils/path'; + +export class Apps extends APIResource { + /** + * Deploy a new application + * + * @example + * ```ts + * const response = await client.apps.deploy({ + * appName: 'my-awesome-app', + * file: fs.createReadStream('path/to/file'), + * version: '1.0.0', + * }); + * ``` + */ + deploy(body: AppDeployParams, options?: RequestOptions): APIPromise { + return this._client.post('/apps/deploy', multipartFormRequestOptions({ body, ...options }, this._client)); + } + + /** + * Invoke an application + * + * @example + * ```ts + * const response = await client.apps.invoke({ + * appName: 'my-awesome-app', + * payload: '{ "data": "example input" }', + * version: '1.0.0', + * }); + * ``` + */ + invoke(body: AppInvokeParams, options?: RequestOptions): APIPromise { + return this._client.post('/apps/invoke', { body, ...options }); + } + + /** + * Get an app invocation by id + * + * @example + * ```ts + * const response = await client.apps.retrieveInvocation( + * 'ckqwer3o20000jb9s7abcdef', + * ); + * ``` + */ + retrieveInvocation(id: string, options?: RequestOptions): APIPromise { + return this._client.get(path`/apps/invocations/${id}`, options); + } +} + +export interface AppDeployResponse { + /** + * ID of the deployed app version + */ + id: string; + + /** + * Success message + */ + message: string; + + /** + * Status of the deployment + */ + success: boolean; +} + +export interface AppInvokeResponse { + /** + * ID of the invocation + */ + id: string; + + /** + * Status of the invocation + */ + status: string; +} + +export interface AppRetrieveInvocationResponse { + id: string; + + appName: string; + + finishedAt: string | null; + + input: string; + + output: string; + + startedAt: string; + + status: string; +} + +export interface AppDeployParams { + /** + * Name of the application + */ + appName: string; + + /** + * ZIP file containing the application + */ + file: Uploadable; + + /** + * Version of the application + */ + version: string; + + /** + * AWS region for deployment (e.g. "aws.us-east-1a") + */ + region?: string; +} + +export interface AppInvokeParams { + /** + * Name of the application + */ + appName: string; + + /** + * Input data for the application + */ + payload: unknown; + + /** + * Version of the application + */ + version: string; +} + +export declare namespace Apps { + export { + type AppDeployResponse as AppDeployResponse, + type AppInvokeResponse as AppInvokeResponse, + type AppRetrieveInvocationResponse as AppRetrieveInvocationResponse, + type AppDeployParams as AppDeployParams, + type AppInvokeParams as AppInvokeParams, + }; +} diff --git a/src/resources/browser.ts b/src/resources/browser.ts new file mode 100644 index 00000000..3ab78702 --- /dev/null +++ b/src/resources/browser.ts @@ -0,0 +1,35 @@ +// 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 { RequestOptions } from '../internal/request-options'; + +export class Browser extends APIResource { + /** + * Create Browser Session + */ + createSession(options?: RequestOptions): APIPromise { + return this._client.post('/browser', options); + } +} + +export interface BrowserCreateSessionResponse { + /** + * Websocket URL for Chrome DevTools Protocol connections to the browser session + */ + cdp_ws_url: string; + + /** + * Remote URL for live viewing the browser session + */ + remote_url: string; + + /** + * Unique identifier for the browser session + */ + sessionId: string; +} + +export declare namespace Browser { + export { type BrowserCreateSessionResponse as BrowserCreateSessionResponse }; +} diff --git a/src/resources/index.ts b/src/resources/index.ts new file mode 100644 index 00000000..b324da12 --- /dev/null +++ b/src/resources/index.ts @@ -0,0 +1,11 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export { + Apps, + type AppDeployResponse, + type AppInvokeResponse, + type AppRetrieveInvocationResponse, + type AppDeployParams, + type AppInvokeParams, +} from './apps'; +export { Browser, type BrowserCreateSessionResponse } from './browser'; diff --git a/src/uploads.ts b/src/uploads.ts new file mode 100644 index 00000000..b2ef6471 --- /dev/null +++ b/src/uploads.ts @@ -0,0 +1,2 @@ +/** @deprecated Import from ./core/uploads instead */ +export * from './core/uploads'; diff --git a/src/version.ts b/src/version.ts new file mode 100644 index 00000000..55a1a527 --- /dev/null +++ b/src/version.ts @@ -0,0 +1 @@ +export const VERSION = '0.0.1-alpha.0'; diff --git a/tests/api-resources/apps.test.ts b/tests/api-resources/apps.test.ts new file mode 100644 index 00000000..67b47bad --- /dev/null +++ b/tests/api-resources/apps.test.ts @@ -0,0 +1,73 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import Kernel, { toFile } from 'kernel'; + +const client = new Kernel({ + apiKey: 'My API Key', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +describe('resource apps', () => { + // skipped: tests are disabled for the time being + test.skip('deploy: only required params', async () => { + const responsePromise = client.apps.deploy({ + appName: 'my-awesome-app', + file: await toFile(Buffer.from('# my file contents'), 'README.md'), + version: '1.0.0', + }); + 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('deploy: required and optional params', async () => { + const response = await client.apps.deploy({ + appName: 'my-awesome-app', + file: await toFile(Buffer.from('# my file contents'), 'README.md'), + version: '1.0.0', + region: 'aws.us-east-1a', + }); + }); + + // skipped: tests are disabled for the time being + test.skip('invoke: only required params', async () => { + const responsePromise = client.apps.invoke({ + appName: 'my-awesome-app', + payload: '{ "data": "example input" }', + version: '1.0.0', + }); + 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('invoke: required and optional params', async () => { + const response = await client.apps.invoke({ + appName: 'my-awesome-app', + payload: '{ "data": "example input" }', + version: '1.0.0', + }); + }); + + // skipped: tests are disabled for the time being + test.skip('retrieveInvocation', async () => { + const responsePromise = client.apps.retrieveInvocation('ckqwer3o20000jb9s7abcdef'); + 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); + }); +}); diff --git a/tests/api-resources/browser.test.ts b/tests/api-resources/browser.test.ts new file mode 100644 index 00000000..c7f40d73 --- /dev/null +++ b/tests/api-resources/browser.test.ts @@ -0,0 +1,22 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import Kernel from 'kernel'; + +const client = new Kernel({ + apiKey: 'My API Key', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +describe('resource browser', () => { + // skipped: tests are disabled for the time being + test.skip('createSession', async () => { + const responsePromise = client.browser.createSession(); + 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); + }); +}); diff --git a/tests/base64.test.ts b/tests/base64.test.ts new file mode 100644 index 00000000..6a9cf51e --- /dev/null +++ b/tests/base64.test.ts @@ -0,0 +1,80 @@ +import { fromBase64, toBase64 } from 'kernel/internal/utils/base64'; + +describe.each(['Buffer', 'atob'])('with %s', (mode) => { + let originalBuffer: BufferConstructor; + beforeAll(() => { + if (mode === 'atob') { + originalBuffer = globalThis.Buffer; + // @ts-expect-error Can't assign undefined to BufferConstructor + delete globalThis.Buffer; + } + }); + afterAll(() => { + if (mode === 'atob') { + globalThis.Buffer = originalBuffer; + } + }); + test('toBase64', () => { + const testCases = [ + { + input: 'hello world', + expected: 'aGVsbG8gd29ybGQ=', + }, + { + input: new Uint8Array([104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100]), + expected: 'aGVsbG8gd29ybGQ=', + }, + { + input: undefined, + expected: '', + }, + { + input: new Uint8Array([ + 229, 102, 215, 230, 65, 22, 46, 87, 243, 176, 99, 99, 31, 174, 8, 242, 83, 142, 169, 64, 122, 123, + 193, 71, + ]), + expected: '5WbX5kEWLlfzsGNjH64I8lOOqUB6e8FH', + }, + { + input: '✓', + expected: '4pyT', + }, + { + input: new Uint8Array([226, 156, 147]), + expected: '4pyT', + }, + ]; + + testCases.forEach(({ input, expected }) => { + expect(toBase64(input)).toBe(expected); + }); + }); + + test('fromBase64', () => { + const testCases = [ + { + input: 'aGVsbG8gd29ybGQ=', + expected: new Uint8Array([104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100]), + }, + { + input: '', + expected: new Uint8Array([]), + }, + { + input: '5WbX5kEWLlfzsGNjH64I8lOOqUB6e8FH', + expected: new Uint8Array([ + 229, 102, 215, 230, 65, 22, 46, 87, 243, 176, 99, 99, 31, 174, 8, 242, 83, 142, 169, 64, 122, 123, + 193, 71, + ]), + }, + { + input: '4pyT', + expected: new Uint8Array([226, 156, 147]), + }, + ]; + + testCases.forEach(({ input, expected }) => { + expect(fromBase64(input)).toEqual(expected); + }); + }); +}); diff --git a/tests/buildHeaders.test.ts b/tests/buildHeaders.test.ts new file mode 100644 index 00000000..62e52f61 --- /dev/null +++ b/tests/buildHeaders.test.ts @@ -0,0 +1,88 @@ +import { inspect } from 'node:util'; +import { buildHeaders, type HeadersLike, type NullableHeaders } from 'kernel/internal/headers'; + +function inspectNullableHeaders(headers: NullableHeaders) { + return `NullableHeaders {${[ + ...[...headers.values.entries()].map(([name, value]) => ` ${inspect(name)}: ${inspect(value)}`), + ...[...headers.nulls].map((name) => ` ${inspect(name)}: null`), + ].join(', ')} }`; +} + +describe('buildHeaders', () => { + const cases: [HeadersLike[], string][] = [ + [[new Headers({ 'content-type': 'text/plain' })], `NullableHeaders { 'content-type': 'text/plain' }`], + [ + [ + { + 'content-type': 'text/plain', + }, + { + 'Content-Type': undefined, + }, + ], + `NullableHeaders { 'content-type': 'text/plain' }`, + ], + [ + [ + { + 'content-type': 'text/plain', + }, + { + 'Content-Type': null, + }, + ], + `NullableHeaders { 'content-type': null }`, + ], + [ + [ + { + cookie: 'name1=value1', + Cookie: 'name2=value2', + }, + ], + `NullableHeaders { 'cookie': 'name2=value2' }`, + ], + [ + [ + { + cookie: 'name1=value1', + Cookie: undefined, + }, + ], + `NullableHeaders { 'cookie': 'name1=value1' }`, + ], + [ + [ + { + cookie: ['name1=value1', 'name2=value2'], + }, + ], + `NullableHeaders { 'cookie': 'name1=value1; name2=value2' }`, + ], + [ + [ + { + 'x-foo': ['name1=value1', 'name2=value2'], + }, + ], + `NullableHeaders { 'x-foo': 'name1=value1, name2=value2' }`, + ], + [ + [ + [ + ['cookie', 'name1=value1'], + ['cookie', 'name2=value2'], + ['Cookie', 'name3=value3'], + ], + ], + `NullableHeaders { 'cookie': 'name1=value1; name2=value2; name3=value3' }`, + ], + [[undefined], `NullableHeaders { }`], + [[null], `NullableHeaders { }`], + ]; + for (const [input, expected] of cases) { + test(expected, () => { + expect(inspectNullableHeaders(buildHeaders(input))).toEqual(expected); + }); + } +}); diff --git a/tests/form.test.ts b/tests/form.test.ts new file mode 100644 index 00000000..c5e1be22 --- /dev/null +++ b/tests/form.test.ts @@ -0,0 +1,85 @@ +import { multipartFormRequestOptions, createForm } from 'kernel/internal/uploads'; +import { toFile } from 'kernel/core/uploads'; + +describe('form data validation', () => { + test('valid values do not error', async () => { + await multipartFormRequestOptions( + { + body: { + foo: 'foo', + string: 1, + bool: true, + file: await toFile(Buffer.from('some-content')), + blob: new Blob(['Some content'], { type: 'text/plain' }), + }, + }, + fetch, + ); + }); + + test('null', async () => { + await expect(() => + multipartFormRequestOptions( + { + body: { + null: null, + }, + }, + fetch, + ), + ).rejects.toThrow(TypeError); + }); + + test('undefined is stripped', async () => { + const form = await createForm( + { + foo: undefined, + bar: 'baz', + }, + fetch, + ); + expect(form.has('foo')).toBe(false); + expect(form.get('bar')).toBe('baz'); + }); + + test('nested undefined property is stripped', async () => { + const form = await createForm( + { + bar: { + baz: undefined, + }, + }, + fetch, + ); + expect(Array.from(form.entries())).toEqual([]); + + const form2 = await createForm( + { + bar: { + foo: 'string', + baz: undefined, + }, + }, + fetch, + ); + expect(Array.from(form2.entries())).toEqual([['bar[foo]', 'string']]); + }); + + test('nested undefined array item is stripped', async () => { + const form = await createForm( + { + bar: [undefined, undefined], + }, + fetch, + ); + expect(Array.from(form.entries())).toEqual([]); + + const form2 = await createForm( + { + bar: [undefined, 'foo'], + }, + fetch, + ); + expect(Array.from(form2.entries())).toEqual([['bar[]', 'foo']]); + }); +}); diff --git a/tests/index.test.ts b/tests/index.test.ts new file mode 100644 index 00000000..589c1cd0 --- /dev/null +++ b/tests/index.test.ts @@ -0,0 +1,700 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIPromise } from 'kernel/core/api-promise'; + +import util from 'node:util'; +import Kernel from 'kernel'; +import { APIUserAbortError } from 'kernel'; +const defaultFetch = fetch; + +describe('instantiate client', () => { + const env = process.env; + + beforeEach(() => { + jest.resetModules(); + process.env = { ...env }; + }); + + afterEach(() => { + process.env = env; + }); + + describe('defaultHeaders', () => { + const client = new Kernel({ + baseURL: 'http://localhost:5000/', + defaultHeaders: { 'X-My-Default-Header': '2' }, + apiKey: 'My API Key', + }); + + test('they are used in the request', () => { + const { req } = 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({ + path: '/foo', + method: 'post', + headers: { 'X-My-Default-Header': undefined }, + }); + expect(req.headers.get('x-my-default-header')).toEqual('2'); + }); + + test('can be removed with `null`', () => { + const { req } = client.buildRequest({ + path: '/foo', + method: 'post', + headers: { 'X-My-Default-Header': null }, + }); + expect(req.headers.has('x-my-default-header')).toBe(false); + }); + }); + describe('logging', () => { + const env = process.env; + + beforeEach(() => { + process.env = { ...env }; + process.env['KERNEL_LOG'] = undefined; + }); + + afterEach(() => { + process.env = env; + }); + + const forceAPIResponseForClient = async (client: Kernel) => { + await new APIPromise( + client, + Promise.resolve({ + response: new Response(), + controller: new AbortController(), + requestLogID: 'log_000000', + retryOfRequestLogID: undefined, + startTime: Date.now(), + options: { + method: 'get', + path: '/', + }, + }), + ); + }; + + test('debug logs when log level is debug', async () => { + const debugMock = jest.fn(); + const logger = { + debug: debugMock, + info: jest.fn(), + warn: jest.fn(), + error: jest.fn(), + }; + + const client = new Kernel({ logger: logger, logLevel: 'debug', apiKey: 'My API Key' }); + + await forceAPIResponseForClient(client); + expect(debugMock).toHaveBeenCalled(); + }); + + test('default logLevel is warn', async () => { + const client = new Kernel({ apiKey: 'My API Key' }); + expect(client.logLevel).toBe('warn'); + }); + + test('debug logs are skipped when log level is info', async () => { + const debugMock = jest.fn(); + const logger = { + debug: debugMock, + info: jest.fn(), + warn: jest.fn(), + error: jest.fn(), + }; + + const client = new Kernel({ logger: logger, logLevel: 'info', apiKey: 'My API Key' }); + + await forceAPIResponseForClient(client); + expect(debugMock).not.toHaveBeenCalled(); + }); + + test('debug logs happen with debug env var', async () => { + const debugMock = jest.fn(); + const logger = { + debug: debugMock, + info: jest.fn(), + warn: jest.fn(), + error: jest.fn(), + }; + + process.env['KERNEL_LOG'] = 'debug'; + const client = new Kernel({ logger: logger, apiKey: 'My API Key' }); + expect(client.logLevel).toBe('debug'); + + await forceAPIResponseForClient(client); + expect(debugMock).toHaveBeenCalled(); + }); + + test('warn when env var level is invalid', async () => { + const warnMock = jest.fn(); + const logger = { + debug: jest.fn(), + info: jest.fn(), + warn: warnMock, + error: jest.fn(), + }; + + process.env['KERNEL_LOG'] = 'not a log level'; + const client = new Kernel({ logger: logger, apiKey: 'My API Key' }); + expect(client.logLevel).toBe('warn'); + expect(warnMock).toHaveBeenCalledWith( + 'process.env[\'KERNEL_LOG\'] was set to "not a log level", expected one of ["off","error","warn","info","debug"]', + ); + }); + + test('client log level overrides env var', async () => { + const debugMock = jest.fn(); + const logger = { + debug: debugMock, + info: jest.fn(), + warn: jest.fn(), + error: jest.fn(), + }; + + process.env['KERNEL_LOG'] = 'debug'; + const client = new Kernel({ logger: logger, logLevel: 'off', apiKey: 'My API Key' }); + + await forceAPIResponseForClient(client); + expect(debugMock).not.toHaveBeenCalled(); + }); + + test('no warning logged for invalid env var level + valid client level', async () => { + const warnMock = jest.fn(); + const logger = { + debug: jest.fn(), + info: jest.fn(), + warn: warnMock, + error: jest.fn(), + }; + + process.env['KERNEL_LOG'] = 'not a log level'; + const client = new Kernel({ logger: logger, logLevel: 'debug', apiKey: 'My API Key' }); + expect(client.logLevel).toBe('debug'); + expect(warnMock).not.toHaveBeenCalled(); + }); + }); + + describe('defaultQuery', () => { + test('with null query params given', () => { + const client = new Kernel({ + baseURL: 'http://localhost:5000/', + defaultQuery: { apiVersion: 'foo' }, + apiKey: 'My API Key', + }); + expect(client.buildURL('/foo', null)).toEqual('http://localhost:5000/foo?apiVersion=foo'); + }); + + test('multiple default query params', () => { + const client = new Kernel({ + baseURL: 'http://localhost:5000/', + defaultQuery: { apiVersion: 'foo', hello: 'world' }, + apiKey: 'My API Key', + }); + expect(client.buildURL('/foo', null)).toEqual('http://localhost:5000/foo?apiVersion=foo&hello=world'); + }); + + test('overriding with `undefined`', () => { + const client = new Kernel({ + baseURL: 'http://localhost:5000/', + defaultQuery: { hello: 'world' }, + apiKey: 'My API Key', + }); + expect(client.buildURL('/foo', { hello: undefined })).toEqual('http://localhost:5000/foo'); + }); + }); + + test('custom fetch', async () => { + const client = new Kernel({ + baseURL: 'http://localhost:5000/', + apiKey: 'My API Key', + fetch: (url) => { + return Promise.resolve( + new Response(JSON.stringify({ url, custom: true }), { + headers: { 'Content-Type': 'application/json' }, + }), + ); + }, + }); + + const response = await client.get('/foo'); + expect(response).toEqual({ url: 'http://localhost:5000/foo', custom: true }); + }); + + test('explicit global fetch', async () => { + // make sure the global fetch type is assignable to our Fetch type + const client = new Kernel({ + baseURL: 'http://localhost:5000/', + apiKey: 'My API Key', + fetch: defaultFetch, + }); + }); + + test('custom signal', async () => { + const client = new Kernel({ + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', + apiKey: 'My API Key', + fetch: (...args) => { + return new Promise((resolve, reject) => + setTimeout( + () => + defaultFetch(...args) + .then(resolve) + .catch(reject), + 300, + ), + ); + }, + }); + + const controller = new AbortController(); + setTimeout(() => controller.abort(), 200); + + const spy = jest.spyOn(client, 'request'); + + await expect(client.get('/foo', { signal: controller.signal })).rejects.toThrowError(APIUserAbortError); + expect(spy).toHaveBeenCalledTimes(1); + }); + + test('normalized method', async () => { + let capturedRequest: RequestInit | undefined; + const testFetch = async (url: string | URL | Request, init: RequestInit = {}): Promise => { + capturedRequest = init; + return new Response(JSON.stringify({}), { headers: { 'Content-Type': 'application/json' } }); + }; + + const client = new Kernel({ baseURL: 'http://localhost:5000/', apiKey: 'My API Key', fetch: testFetch }); + + await client.patch('/foo'); + expect(capturedRequest?.method).toEqual('PATCH'); + }); + + describe('baseUrl', () => { + test('trailing slash', () => { + const client = new Kernel({ baseURL: 'http://localhost:5000/custom/path/', apiKey: 'My API Key' }); + expect(client.buildURL('/foo', null)).toEqual('http://localhost:5000/custom/path/foo'); + }); + + test('no trailing slash', () => { + const client = new Kernel({ baseURL: 'http://localhost:5000/custom/path', apiKey: 'My API Key' }); + expect(client.buildURL('/foo', null)).toEqual('http://localhost:5000/custom/path/foo'); + }); + + afterEach(() => { + process.env['KERNEL_BASE_URL'] = undefined; + }); + + test('explicit option', () => { + const client = new Kernel({ baseURL: 'https://example.com', apiKey: 'My API Key' }); + expect(client.baseURL).toEqual('https://example.com'); + }); + + test('env variable', () => { + process.env['KERNEL_BASE_URL'] = 'https://example.com/from_env'; + const client = new Kernel({ apiKey: 'My API Key' }); + expect(client.baseURL).toEqual('https://example.com/from_env'); + }); + + test('empty env variable', () => { + process.env['KERNEL_BASE_URL'] = ''; // empty + const client = new Kernel({ apiKey: 'My API Key' }); + expect(client.baseURL).toEqual('http://localhost:3001'); + }); + + test('blank env variable', () => { + process.env['KERNEL_BASE_URL'] = ' '; // blank + const client = new Kernel({ apiKey: 'My API Key' }); + expect(client.baseURL).toEqual('http://localhost:3001'); + }); + }); + + test('maxRetries option is correctly set', () => { + const client = new Kernel({ maxRetries: 4, apiKey: 'My API Key' }); + expect(client.maxRetries).toEqual(4); + + // default + const client2 = new Kernel({ apiKey: 'My API Key' }); + expect(client2.maxRetries).toEqual(2); + }); + + describe('withOptions', () => { + test('creates a new client with overridden options', () => { + const client = new Kernel({ baseURL: 'http://localhost:5000/', maxRetries: 3, apiKey: 'My API Key' }); + + const newClient = client.withOptions({ + maxRetries: 5, + baseURL: 'http://localhost:5001/', + }); + + // Verify the new client has updated options + expect(newClient.maxRetries).toEqual(5); + expect(newClient.baseURL).toEqual('http://localhost:5001/'); + + // Verify the original client is unchanged + expect(client.maxRetries).toEqual(3); + expect(client.baseURL).toEqual('http://localhost:5000/'); + + // Verify it's a different instance + expect(newClient).not.toBe(client); + expect(newClient.constructor).toBe(client.constructor); + }); + + test('inherits options from the parent client', () => { + const client = new Kernel({ + baseURL: 'http://localhost:5000/', + defaultHeaders: { 'X-Test-Header': 'test-value' }, + defaultQuery: { 'test-param': 'test-value' }, + apiKey: 'My API Key', + }); + + const newClient = client.withOptions({ + baseURL: 'http://localhost:5001/', + }); + + // 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' }); + expect(req.headers.get('x-test-header')).toEqual('test-value'); + }); + + test('respects runtime property changes when creating new client', () => { + const client = new Kernel({ baseURL: 'http://localhost:5000/', timeout: 1000, apiKey: 'My API Key' }); + + // Modify the client properties directly after creation + client.baseURL = 'http://localhost:6000/'; + client.timeout = 2000; + + // Create a new client with withOptions + const newClient = client.withOptions({ + maxRetries: 10, + }); + + // Verify the new client uses the updated properties, not the original ones + expect(newClient.baseURL).toEqual('http://localhost:6000/'); + expect(newClient.timeout).toEqual(2000); + expect(newClient.maxRetries).toEqual(10); + + // Original client should still have its modified properties + expect(client.baseURL).toEqual('http://localhost:6000/'); + expect(client.timeout).toEqual(2000); + expect(client.maxRetries).not.toEqual(10); + + // Verify URL building uses the updated baseURL + expect(newClient.buildURL('/bar', null)).toEqual('http://localhost:6000/bar'); + }); + }); + + test('with environment variable arguments', () => { + // set options via env var + process.env['KERNEL_API_KEY'] = 'My API Key'; + const client = new Kernel(); + expect(client.apiKey).toBe('My API Key'); + }); + + test('with overridden environment variable arguments', () => { + // set options via env var + process.env['KERNEL_API_KEY'] = 'another My API Key'; + const client = new Kernel({ apiKey: 'My API Key' }); + expect(client.apiKey).toBe('My API Key'); + }); +}); + +describe('request building', () => { + const client = new Kernel({ apiKey: 'My API Key' }); + + describe('custom headers', () => { + test('handles undefined', () => { + const { req } = client.buildRequest({ + path: '/foo', + method: 'post', + body: { value: 'hello' }, + headers: { 'X-Foo': 'baz', 'x-foo': 'bar', 'x-Foo': undefined, 'x-baz': 'bam', 'X-Baz': null }, + }); + expect(req.headers.get('x-foo')).toEqual('bar'); + expect(req.headers.get('x-Foo')).toEqual('bar'); + expect(req.headers.get('X-Foo')).toEqual('bar'); + expect(req.headers.get('x-baz')).toEqual(null); + }); + }); +}); + +describe('default encoder', () => { + const client = new Kernel({ apiKey: 'My API Key' }); + + class Serializable { + toJSON() { + return { $type: 'Serializable' }; + } + } + class Collection { + #things: T[]; + constructor(things: T[]) { + this.#things = Array.from(things); + } + toJSON() { + return Array.from(this.#things); + } + [Symbol.iterator]() { + return this.#things[Symbol.iterator]; + } + } + for (const jsonValue of [{}, [], { __proto__: null }, new Serializable(), new Collection(['item'])]) { + test(`serializes ${util.inspect(jsonValue)} as json`, () => { + const { req } = client.buildRequest({ + path: '/foo', + method: 'post', + body: jsonValue, + }); + expect(req.headers).toBeInstanceOf(Headers); + expect(req.headers.get('content-type')).toEqual('application/json'); + expect(req.body).toBe(JSON.stringify(jsonValue)); + }); + } + + const encoder = new TextEncoder(); + const asyncIterable = (async function* () { + yield encoder.encode('a\n'); + yield encoder.encode('b\n'); + yield encoder.encode('c\n'); + })(); + for (const streamValue of [ + [encoder.encode('a\nb\nc\n')][Symbol.iterator](), + new Response('a\nb\nc\n').body, + asyncIterable, + ]) { + test(`converts ${util.inspect(streamValue)} to ReadableStream`, async () => { + const { req } = client.buildRequest({ + path: '/foo', + method: 'post', + body: streamValue, + }); + expect(req.headers).toBeInstanceOf(Headers); + expect(req.headers.get('content-type')).toEqual(null); + expect(req.body).toBeInstanceOf(ReadableStream); + expect(await new Response(req.body).text()).toBe('a\nb\nc\n'); + }); + } + + test(`can set content-type for ReadableStream`, async () => { + const { req } = client.buildRequest({ + path: '/foo', + method: 'post', + body: new Response('a\nb\nc\n').body, + headers: { 'Content-Type': 'text/plain' }, + }); + expect(req.headers).toBeInstanceOf(Headers); + expect(req.headers.get('content-type')).toEqual('text/plain'); + expect(req.body).toBeInstanceOf(ReadableStream); + expect(await new Response(req.body).text()).toBe('a\nb\nc\n'); + }); +}); + +describe('retries', () => { + test('retry on timeout', async () => { + let count = 0; + const testFetch = async ( + url: string | URL | Request, + { signal }: RequestInit = {}, + ): Promise => { + if (count++ === 0) { + return new Promise( + (resolve, reject) => signal?.addEventListener('abort', () => reject(new Error('timed out'))), + ); + } + return new Response(JSON.stringify({ a: 1 }), { headers: { 'Content-Type': 'application/json' } }); + }; + + const client = new Kernel({ apiKey: 'My API Key', timeout: 10, fetch: testFetch }); + + expect(await client.request({ path: '/foo', method: 'get' })).toEqual({ a: 1 }); + expect(count).toEqual(2); + expect( + await client + .request({ path: '/foo', method: 'get' }) + .asResponse() + .then((r) => r.text()), + ).toEqual(JSON.stringify({ a: 1 })); + expect(count).toEqual(3); + }); + + test('retry count header', async () => { + let count = 0; + let capturedRequest: RequestInit | undefined; + const testFetch = async (url: string | URL | Request, init: RequestInit = {}): Promise => { + count++; + if (count <= 2) { + return new Response(undefined, { + status: 429, + headers: { + 'Retry-After': '0.1', + }, + }); + } + capturedRequest = init; + return new Response(JSON.stringify({ a: 1 }), { headers: { 'Content-Type': 'application/json' } }); + }; + + const client = new Kernel({ apiKey: 'My API Key', fetch: testFetch, maxRetries: 4 }); + + expect(await client.request({ path: '/foo', method: 'get' })).toEqual({ a: 1 }); + + expect((capturedRequest!.headers as Headers).get('x-stainless-retry-count')).toEqual('2'); + expect(count).toEqual(3); + }); + + test('omit retry count header', async () => { + let count = 0; + let capturedRequest: RequestInit | undefined; + const testFetch = async (url: string | URL | Request, init: RequestInit = {}): Promise => { + count++; + if (count <= 2) { + return new Response(undefined, { + status: 429, + headers: { + 'Retry-After': '0.1', + }, + }); + } + capturedRequest = init; + return new Response(JSON.stringify({ a: 1 }), { headers: { 'Content-Type': 'application/json' } }); + }; + const client = new Kernel({ apiKey: 'My API Key', fetch: testFetch, maxRetries: 4 }); + + expect( + await client.request({ + path: '/foo', + method: 'get', + headers: { 'X-Stainless-Retry-Count': null }, + }), + ).toEqual({ a: 1 }); + + expect((capturedRequest!.headers as Headers).has('x-stainless-retry-count')).toBe(false); + }); + + test('omit retry count header by default', async () => { + let count = 0; + let capturedRequest: RequestInit | undefined; + const testFetch = async (url: string | URL | Request, init: RequestInit = {}): Promise => { + count++; + if (count <= 2) { + return new Response(undefined, { + status: 429, + headers: { + 'Retry-After': '0.1', + }, + }); + } + capturedRequest = init; + return new Response(JSON.stringify({ a: 1 }), { headers: { 'Content-Type': 'application/json' } }); + }; + const client = new Kernel({ + apiKey: 'My API Key', + fetch: testFetch, + maxRetries: 4, + defaultHeaders: { 'X-Stainless-Retry-Count': null }, + }); + + expect( + await client.request({ + path: '/foo', + method: 'get', + }), + ).toEqual({ a: 1 }); + + expect(capturedRequest!.headers as Headers).not.toHaveProperty('x-stainless-retry-count'); + }); + + test('overwrite retry count header', async () => { + let count = 0; + let capturedRequest: RequestInit | undefined; + const testFetch = async (url: string | URL | Request, init: RequestInit = {}): Promise => { + count++; + if (count <= 2) { + return new Response(undefined, { + status: 429, + headers: { + 'Retry-After': '0.1', + }, + }); + } + capturedRequest = init; + return new Response(JSON.stringify({ a: 1 }), { headers: { 'Content-Type': 'application/json' } }); + }; + const client = new Kernel({ apiKey: 'My API Key', fetch: testFetch, maxRetries: 4 }); + + expect( + await client.request({ + path: '/foo', + method: 'get', + headers: { 'X-Stainless-Retry-Count': '42' }, + }), + ).toEqual({ a: 1 }); + + expect((capturedRequest!.headers as Headers).get('x-stainless-retry-count')).toEqual('42'); + }); + + test('retry on 429 with retry-after', async () => { + let count = 0; + const testFetch = async ( + url: string | URL | Request, + { signal }: RequestInit = {}, + ): Promise => { + if (count++ === 0) { + return new Response(undefined, { + status: 429, + headers: { + 'Retry-After': '0.1', + }, + }); + } + return new Response(JSON.stringify({ a: 1 }), { headers: { 'Content-Type': 'application/json' } }); + }; + + const client = new Kernel({ apiKey: 'My API Key', fetch: testFetch }); + + expect(await client.request({ path: '/foo', method: 'get' })).toEqual({ a: 1 }); + expect(count).toEqual(2); + expect( + await client + .request({ path: '/foo', method: 'get' }) + .asResponse() + .then((r) => r.text()), + ).toEqual(JSON.stringify({ a: 1 })); + expect(count).toEqual(3); + }); + + test('retry on 429 with retry-after-ms', async () => { + let count = 0; + const testFetch = async ( + url: string | URL | Request, + { signal }: RequestInit = {}, + ): Promise => { + if (count++ === 0) { + return new Response(undefined, { + status: 429, + headers: { + 'Retry-After-Ms': '10', + }, + }); + } + return new Response(JSON.stringify({ a: 1 }), { headers: { 'Content-Type': 'application/json' } }); + }; + + const client = new Kernel({ apiKey: 'My API Key', fetch: testFetch }); + + expect(await client.request({ path: '/foo', method: 'get' })).toEqual({ a: 1 }); + expect(count).toEqual(2); + expect( + await client + .request({ path: '/foo', method: 'get' }) + .asResponse() + .then((r) => r.text()), + ).toEqual(JSON.stringify({ a: 1 })); + expect(count).toEqual(3); + }); +}); diff --git a/tests/path.test.ts b/tests/path.test.ts new file mode 100644 index 00000000..c581f275 --- /dev/null +++ b/tests/path.test.ts @@ -0,0 +1,318 @@ +import { createPathTagFunction, encodeURIPath } from 'kernel/internal/utils/path'; +import { inspect } from 'node:util'; + +describe('path template tag function', () => { + test('validates input', () => { + const testParams = ['', '.', '..', 'x', '%2e', '%2E', '%2e%2e', '%2E%2e', '%2e%2E', '%2E%2E']; + const testCases = [ + ['/path_params/', '/a'], + ['/path_params/', '/'], + ['/path_params/', ''], + ['', '/a'], + ['', '/'], + ['', ''], + ['a'], + [''], + ['/path_params/', ':initiate'], + ['/path_params/', '.json'], + ['/path_params/', '?beta=true'], + ['/path_params/', '.?beta=true'], + ['/path_params/', '/', '/download'], + ['/path_params/', '-', '/download'], + ['/path_params/', '', '/download'], + ['/path_params/', '.', '/download'], + ['/path_params/', '..', '/download'], + ['/plain/path'], + ]; + + function paramPermutations(len: number): string[][] { + if (len === 0) return []; + if (len === 1) return testParams.map((e) => [e]); + const rest = paramPermutations(len - 1); + return testParams.flatMap((e) => rest.map((r) => [e, ...r])); + } + + // we need to test how %2E is handled so we use a custom encoder that does no escaping + const rawPath = createPathTagFunction((s) => s); + + const results: { + [pathParts: string]: { + [params: string]: { valid: boolean; result?: string; error?: string }; + }; + } = {}; + + for (const pathParts of testCases) { + const pathResults: Record = {}; + results[JSON.stringify(pathParts)] = pathResults; + for (const params of paramPermutations(pathParts.length - 1)) { + const stringRaw = String.raw({ raw: pathParts }, ...params); + const plainString = String.raw( + { raw: pathParts.map((e) => e.replace(/\./g, 'x')) }, + ...params.map((e) => 'X'.repeat(e.length)), + ); + const normalizedStringRaw = new URL(stringRaw, 'https://example.com').href; + const normalizedPlainString = new URL(plainString, 'https://example.com').href; + const pathResultsKey = JSON.stringify(params); + try { + const result = rawPath(pathParts, ...params); + expect(result).toBe(stringRaw); + // there are no special segments, so the length of the normalized path is + // equal to the length of the normalized plain path. + expect(normalizedStringRaw.length).toBe(normalizedPlainString.length); + pathResults[pathResultsKey] = { + valid: true, + result, + }; + } catch (e) { + const error = String(e); + expect(error).toMatch(/Path parameters result in path with invalid segment/); + // there are special segments, so the length of the normalized path is + // different than the length of the normalized plain path. + expect(normalizedStringRaw.length).not.toBe(normalizedPlainString.length); + pathResults[pathResultsKey] = { + valid: false, + error, + }; + } + } + } + + expect(results).toMatchObject({ + '["/path_params/","/a"]': { + '["x"]': { valid: true, result: '/path_params/x/a' }, + '[""]': { valid: true, result: '/path_params//a' }, + '["%2E%2e"]': { + valid: false, + error: + 'Error: Path parameters result in path with invalid segments:\n' + + '/path_params/%2E%2e/a\n' + + ' ^^^^^^', + }, + '["%2E"]': { + valid: false, + error: + 'Error: Path parameters result in path with invalid segments:\n' + + '/path_params/%2E/a\n' + + ' ^^^', + }, + }, + '["/path_params/","/"]': { + '["x"]': { valid: true, result: '/path_params/x/' }, + '[""]': { valid: true, result: '/path_params//' }, + '["%2e%2E"]': { + valid: false, + error: + 'Error: Path parameters result in path with invalid segments:\n' + + '/path_params/%2e%2E/\n' + + ' ^^^^^^', + }, + '["%2e"]': { + valid: false, + error: + 'Error: Path parameters result in path with invalid segments:\n' + + '/path_params/%2e/\n' + + ' ^^^', + }, + }, + '["/path_params/",""]': { + '[""]': { valid: true, result: '/path_params/' }, + '["x"]': { valid: true, result: '/path_params/x' }, + '["%2E"]': { + valid: false, + error: + 'Error: Path parameters result in path with invalid segments:\n' + + '/path_params/%2E\n' + + ' ^^^', + }, + '["%2E%2e"]': { + valid: false, + error: + 'Error: Path parameters result in path with invalid segments:\n' + + '/path_params/%2E%2e\n' + + ' ^^^^^^', + }, + }, + '["","/a"]': { + '[""]': { valid: true, result: '/a' }, + '["x"]': { valid: true, result: 'x/a' }, + '["%2E"]': { + valid: false, + error: 'Error: Path parameters result in path with invalid segments:\n%2E/a\n^^^', + }, + '["%2e%2E"]': { + valid: false, + error: 'Error: Path parameters result in path with invalid segments:\n' + '%2e%2E/a\n' + '^^^^^^', + }, + }, + '["","/"]': { + '["x"]': { valid: true, result: 'x/' }, + '[""]': { valid: true, result: '/' }, + '["%2E%2e"]': { + valid: false, + error: 'Error: Path parameters result in path with invalid segments:\n' + '%2E%2e/\n' + '^^^^^^', + }, + '["."]': { + valid: false, + error: 'Error: Path parameters result in path with invalid segments:\n./\n^', + }, + }, + '["",""]': { + '[""]': { valid: true, result: '' }, + '["x"]': { valid: true, result: 'x' }, + '[".."]': { + valid: false, + error: 'Error: Path parameters result in path with invalid segments:\n..\n^^', + }, + '["."]': { + valid: false, + error: 'Error: Path parameters result in path with invalid segments:\n.\n^', + }, + }, + '["a"]': {}, + '[""]': {}, + '["/path_params/",":initiate"]': { + '[""]': { valid: true, result: '/path_params/:initiate' }, + '["."]': { valid: true, result: '/path_params/.:initiate' }, + }, + '["/path_params/",".json"]': { + '["x"]': { valid: true, result: '/path_params/x.json' }, + '["."]': { valid: true, result: '/path_params/..json' }, + }, + '["/path_params/","?beta=true"]': { + '["x"]': { valid: true, result: '/path_params/x?beta=true' }, + '[""]': { valid: true, result: '/path_params/?beta=true' }, + '["%2E%2E"]': { + valid: false, + error: + 'Error: Path parameters result in path with invalid segments:\n' + + '/path_params/%2E%2E?beta=true\n' + + ' ^^^^^^', + }, + '["%2e%2E"]': { + valid: false, + error: + 'Error: Path parameters result in path with invalid segments:\n' + + '/path_params/%2e%2E?beta=true\n' + + ' ^^^^^^', + }, + }, + '["/path_params/",".?beta=true"]': { + '[".."]': { valid: true, result: '/path_params/...?beta=true' }, + '["x"]': { valid: true, result: '/path_params/x.?beta=true' }, + '[""]': { + valid: false, + error: + 'Error: Path parameters result in path with invalid segments:\n' + + '/path_params/.?beta=true\n' + + ' ^', + }, + '["%2e"]': { + valid: false, + error: + 'Error: Path parameters result in path with invalid segments:\n' + + '/path_params/%2e.?beta=true\n' + + ' ^^^^', + }, + }, + '["/path_params/","/","/download"]': { + '["",""]': { valid: true, result: '/path_params///download' }, + '["","x"]': { valid: true, result: '/path_params//x/download' }, + '[".","%2e"]': { + valid: false, + error: + 'Error: Path parameters result in path with invalid segments:\n' + + '/path_params/./%2e/download\n' + + ' ^ ^^^', + }, + '["%2E%2e","%2e"]': { + valid: false, + error: + 'Error: Path parameters result in path with invalid segments:\n' + + '/path_params/%2E%2e/%2e/download\n' + + ' ^^^^^^ ^^^', + }, + }, + '["/path_params/","-","/download"]': { + '["","%2e"]': { valid: true, result: '/path_params/-%2e/download' }, + '["%2E",".."]': { valid: true, result: '/path_params/%2E-../download' }, + }, + '["/path_params/","","/download"]': { + '["%2E%2e","%2e%2E"]': { valid: true, result: '/path_params/%2E%2e%2e%2E/download' }, + '["%2E",".."]': { valid: true, result: '/path_params/%2E../download' }, + '["","%2E"]': { + valid: false, + error: + 'Error: Path parameters result in path with invalid segments:\n' + + '/path_params/%2E/download\n' + + ' ^^^', + }, + '["%2E","."]': { + valid: false, + error: + 'Error: Path parameters result in path with invalid segments:\n' + + '/path_params/%2E./download\n' + + ' ^^^^', + }, + }, + '["/path_params/",".","/download"]': { + '["%2e%2e",""]': { valid: true, result: '/path_params/%2e%2e./download' }, + '["","%2e%2e"]': { valid: true, result: '/path_params/.%2e%2e/download' }, + '["",""]': { + valid: false, + error: + 'Error: Path parameters result in path with invalid segments:\n' + + '/path_params/./download\n' + + ' ^', + }, + '["","."]': { + valid: false, + error: + 'Error: Path parameters result in path with invalid segments:\n' + + '/path_params/../download\n' + + ' ^^', + }, + }, + '["/path_params/","..","/download"]': { + '["","%2E"]': { valid: true, result: '/path_params/..%2E/download' }, + '["","x"]': { valid: true, result: '/path_params/..x/download' }, + '["",""]': { + valid: false, + error: + 'Error: Path parameters result in path with invalid segments:\n' + + '/path_params/../download\n' + + ' ^^', + }, + }, + }); + }); +}); + +describe('encodeURIPath', () => { + const testCases: string[] = [ + '', + // Every ASCII character + ...Array.from({ length: 0x7f }, (_, i) => String.fromCharCode(i)), + // Unicode BMP codepoint + 'å', + // Unicode supplementary codepoint + '😃', + ]; + + for (const param of testCases) { + test('properly encodes ' + inspect(param), () => { + const encoded = encodeURIPath(param); + const naiveEncoded = encodeURIComponent(param); + // we should never encode more characters than encodeURIComponent + expect(naiveEncoded.length).toBeGreaterThanOrEqual(encoded.length); + expect(decodeURIComponent(encoded)).toBe(param); + }); + } + + test("leaves ':' intact", () => { + expect(encodeURIPath(':')).toBe(':'); + }); + + test("leaves '@' intact", () => { + expect(encodeURIPath('@')).toBe('@'); + }); +}); diff --git a/tests/stringifyQuery.test.ts b/tests/stringifyQuery.test.ts new file mode 100644 index 00000000..ce8b6918 --- /dev/null +++ b/tests/stringifyQuery.test.ts @@ -0,0 +1,29 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { Kernel } from 'kernel'; + +const { stringifyQuery } = Kernel.prototype as any; + +describe(stringifyQuery, () => { + for (const [input, expected] of [ + [{ a: '1', b: 2, c: true }, 'a=1&b=2&c=true'], + [{ a: null, b: false, c: undefined }, 'a=&b=false'], + [{ 'a/b': 1.28341 }, `${encodeURIComponent('a/b')}=1.28341`], + [ + { 'a/b': 'c/d', 'e=f': 'g&h' }, + `${encodeURIComponent('a/b')}=${encodeURIComponent('c/d')}&${encodeURIComponent( + 'e=f', + )}=${encodeURIComponent('g&h')}`, + ], + ]) { + it(`${JSON.stringify(input)} -> ${expected}`, () => { + expect(stringifyQuery(input)).toEqual(expected); + }); + } + + for (const value of [[], {}, new Date()]) { + it(`${JSON.stringify(value)} -> `, () => { + expect(() => stringifyQuery({ value })).toThrow(`Cannot stringify type ${typeof value}`); + }); + } +}); diff --git a/tests/uploads.test.ts b/tests/uploads.test.ts new file mode 100644 index 00000000..d6fb8d31 --- /dev/null +++ b/tests/uploads.test.ts @@ -0,0 +1,107 @@ +import fs from 'fs'; +import type { ResponseLike } from 'kernel/internal/to-file'; +import { toFile } from 'kernel/core/uploads'; +import { File } from 'node:buffer'; + +class MyClass { + name: string = 'foo'; +} + +function mockResponse({ url, content }: { url: string; content?: Blob }): ResponseLike { + return { + url, + blob: async () => content || new Blob([]), + }; +} + +describe('toFile', () => { + it('throws a helpful error for mismatched types', async () => { + await expect( + // @ts-expect-error intentionally mismatched type + toFile({ foo: 'string' }), + ).rejects.toThrowErrorMatchingInlineSnapshot( + `"Unexpected data type: object; constructor: Object; props: ["foo"]"`, + ); + + await expect( + // @ts-expect-error intentionally mismatched type + toFile(new MyClass()), + ).rejects.toThrowErrorMatchingInlineSnapshot( + `"Unexpected data type: object; constructor: MyClass; props: ["name"]"`, + ); + }); + + it('disallows string at the type-level', async () => { + // @ts-expect-error we intentionally do not type support for `string` + // to help people avoid passing a file path + const file = await toFile('contents'); + expect(file.text()).resolves.toEqual('contents'); + }); + + it('extracts a file name from a Response', async () => { + const response = mockResponse({ url: 'https://example.com/my/audio.mp3' }); + const file = await toFile(response); + expect(file.name).toEqual('audio.mp3'); + }); + + it('extracts a file name from a File', async () => { + const input = new File(['foo'], 'input.jsonl'); + const file = await toFile(input); + expect(file.name).toEqual('input.jsonl'); + }); + + it('extracts a file name from a ReadStream', async () => { + const input = fs.createReadStream('tests/uploads.test.ts'); + const file = await toFile(input); + expect(file.name).toEqual('uploads.test.ts'); + }); + + it('does not copy File objects', async () => { + const input = new File(['foo'], 'input.jsonl', { type: 'jsonl' }); + const file = await toFile(input); + expect(file).toBe(input); + expect(file.name).toEqual('input.jsonl'); + expect(file.type).toBe('jsonl'); + }); + + it('is assignable to File and Blob', async () => { + const input = new File(['foo'], 'input.jsonl', { type: 'jsonl' }); + const result = await toFile(input); + const file: File = result; + const blob: Blob = result; + void file, blob; + }); +}); + +describe('missing File error message', () => { + let prevGlobalFile: unknown; + let prevNodeFile: unknown; + beforeEach(() => { + // The file shim captures the global File object when it's first imported. + // Reset modules before each test so we can test the error thrown when it's undefined. + jest.resetModules(); + const buffer = require('node:buffer'); + // @ts-ignore + prevGlobalFile = globalThis.File; + prevNodeFile = buffer.File; + // @ts-ignore + globalThis.File = undefined; + buffer.File = undefined; + }); + afterEach(() => { + // Clean up + // @ts-ignore + globalThis.File = prevGlobalFile; + require('node:buffer').File = prevNodeFile; + jest.resetModules(); + }); + + test('is thrown', async () => { + const uploads = await import('kernel/core/uploads'); + await expect( + uploads.toFile(mockResponse({ url: 'https://example.com/my/audio.mp3' })), + ).rejects.toMatchInlineSnapshot( + `[Error: \`File\` is not defined as a global, which is required for file uploads.]`, + ); + }); +}); diff --git a/tsc-multi.json b/tsc-multi.json new file mode 100644 index 00000000..170bac7a --- /dev/null +++ b/tsc-multi.json @@ -0,0 +1,7 @@ +{ + "targets": [ + { "extname": ".js", "module": "commonjs", "shareHelpers": "internal/tslib.js" }, + { "extname": ".mjs", "module": "esnext", "shareHelpers": "internal/tslib.mjs" } + ], + "projects": ["tsconfig.build.json"] +} diff --git a/tsconfig.build.json b/tsconfig.build.json new file mode 100644 index 00000000..291f7ad9 --- /dev/null +++ b/tsconfig.build.json @@ -0,0 +1,18 @@ +{ + "extends": "./tsconfig.json", + "include": ["dist/src"], + "exclude": [], + "compilerOptions": { + "rootDir": "./dist/src", + "paths": { + "kernel/*": ["dist/src/*"], + "kernel": ["dist/src/index.ts"] + }, + "noEmit": false, + "declaration": true, + "declarationMap": true, + "outDir": "dist", + "pretty": true, + "sourceMap": true + } +} diff --git a/tsconfig.deno.json b/tsconfig.deno.json new file mode 100644 index 00000000..849e070d --- /dev/null +++ b/tsconfig.deno.json @@ -0,0 +1,15 @@ +{ + "extends": "./tsconfig.json", + "include": ["dist-deno"], + "exclude": [], + "compilerOptions": { + "rootDir": "./dist-deno", + "lib": ["es2020", "DOM"], + "noEmit": true, + "declaration": true, + "declarationMap": true, + "outDir": "dist-deno", + "pretty": true, + "sourceMap": true + } +} diff --git a/tsconfig.dist-src.json b/tsconfig.dist-src.json new file mode 100644 index 00000000..c550e299 --- /dev/null +++ b/tsconfig.dist-src.json @@ -0,0 +1,11 @@ +{ + // this config is included in the published src directory to prevent TS errors + // from appearing when users go to source, and VSCode opens the source .ts file + // via declaration maps + "include": ["index.ts"], + "compilerOptions": { + "target": "ES2015", + "lib": ["DOM", "DOM.Iterable", "ES2018"], + "moduleResolution": "node" + } +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 00000000..67838cf9 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,38 @@ +{ + "include": ["src", "tests", "examples"], + "exclude": [], + "compilerOptions": { + "target": "es2020", + "lib": ["es2020"], + "module": "commonjs", + "moduleResolution": "node", + "esModuleInterop": true, + "baseUrl": "./", + "paths": { + "kernel/*": ["src/*"], + "kernel": ["src/index.ts"] + }, + "noEmit": true, + + "resolveJsonModule": true, + + "forceConsistentCasingInFileNames": true, + + "strict": true, + "noImplicitAny": true, + "strictNullChecks": true, + "strictFunctionTypes": true, + "strictBindCallApply": true, + "strictPropertyInitialization": true, + "noImplicitThis": true, + "noImplicitReturns": true, + "alwaysStrict": true, + "exactOptionalPropertyTypes": true, + "noUncheckedIndexedAccess": true, + "noImplicitOverride": true, + "noPropertyAccessFromIndexSignature": true, + "isolatedModules": false, + + "skipLibCheck": true + } +} diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 00000000..43da555d --- /dev/null +++ b/yarn.lock @@ -0,0 +1,3506 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@aashutoshrathi/word-wrap@^1.2.3": + version "1.2.6" + resolved "https://registry.yarnpkg.com/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz#bd9154aec9983f77b3a034ecaa015c2e4201f6cf" + integrity sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA== + +"@ampproject/remapping@^2.2.0": + version "2.2.1" + resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.1.tgz#99e8e11851128b8702cd57c33684f1d0f260b630" + integrity sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg== + dependencies: + "@jridgewell/gen-mapping" "^0.3.0" + "@jridgewell/trace-mapping" "^0.3.9" + +"@andrewbranch/untar.js@^1.0.3": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@andrewbranch/untar.js/-/untar.js-1.0.3.tgz#ba9494f85eb83017c5c855763969caf1d0adea00" + integrity sha512-Jh15/qVmrLGhkKJBdXlK1+9tY4lZruYjsgkDFj08ZmDiWVBLJcqkok7Z0/R0In+i1rScBpJlSvrTS2Lm41Pbnw== + +"@arethetypeswrong/cli@^0.17.0": + version "0.17.0" + resolved "https://registry.yarnpkg.com/@arethetypeswrong/cli/-/cli-0.17.0.tgz#f97f10926b3f9f9eb5117550242d2e06c25cadac" + integrity sha512-xSMW7bfzVWpYw5JFgZqBXqr6PdR0/REmn3DkxCES5N0JTcB0CVgbIynJCvKBFmXaPc3hzmmTrb7+yPDRoOSZdA== + dependencies: + "@arethetypeswrong/core" "0.17.0" + chalk "^4.1.2" + cli-table3 "^0.6.3" + commander "^10.0.1" + marked "^9.1.2" + marked-terminal "^7.1.0" + semver "^7.5.4" + +"@arethetypeswrong/core@0.17.0": + version "0.17.0" + resolved "https://registry.yarnpkg.com/@arethetypeswrong/core/-/core-0.17.0.tgz#abb3b5f425056d37193644c2a2de4aecf866b76b" + integrity sha512-FHyhFizXNetigTVsIhqXKGYLpazPS5YNojEPpZEUcBPt9wVvoEbNIvG+hybuBR+pjlRcbyuqhukHZm1fr+bDgA== + dependencies: + "@andrewbranch/untar.js" "^1.0.3" + cjs-module-lexer "^1.2.3" + fflate "^0.8.2" + lru-cache "^10.4.3" + semver "^7.5.4" + typescript "5.6.1-rc" + validate-npm-package-name "^5.0.0" + +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.22.13", "@babel/code-frame@^7.23.5": + version "7.23.5" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.23.5.tgz#9009b69a8c602293476ad598ff53e4562e15c244" + integrity sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA== + dependencies: + "@babel/highlight" "^7.23.4" + chalk "^2.4.2" + +"@babel/compat-data@^7.23.5": + version "7.23.5" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.23.5.tgz#ffb878728bb6bdcb6f4510aa51b1be9afb8cfd98" + integrity sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw== + +"@babel/core@^7.11.6", "@babel/core@^7.12.3": + version "7.23.6" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.23.6.tgz#8be77cd77c55baadcc1eae1c33df90ab6d2151d4" + integrity sha512-FxpRyGjrMJXh7X3wGLGhNDCRiwpWEF74sKjTLDJSG5Kyvow3QZaG0Adbqzi9ZrVjTWpsX+2cxWXD71NMg93kdw== + dependencies: + "@ampproject/remapping" "^2.2.0" + "@babel/code-frame" "^7.23.5" + "@babel/generator" "^7.23.6" + "@babel/helper-compilation-targets" "^7.23.6" + "@babel/helper-module-transforms" "^7.23.3" + "@babel/helpers" "^7.23.6" + "@babel/parser" "^7.23.6" + "@babel/template" "^7.22.15" + "@babel/traverse" "^7.23.6" + "@babel/types" "^7.23.6" + convert-source-map "^2.0.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.2.3" + semver "^6.3.1" + +"@babel/generator@^7.23.6", "@babel/generator@^7.7.2": + version "7.23.6" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.23.6.tgz#9e1fca4811c77a10580d17d26b57b036133f3c2e" + integrity sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw== + dependencies: + "@babel/types" "^7.23.6" + "@jridgewell/gen-mapping" "^0.3.2" + "@jridgewell/trace-mapping" "^0.3.17" + jsesc "^2.5.1" + +"@babel/helper-compilation-targets@^7.23.6": + version "7.23.6" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz#4d79069b16cbcf1461289eccfbbd81501ae39991" + integrity sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ== + dependencies: + "@babel/compat-data" "^7.23.5" + "@babel/helper-validator-option" "^7.23.5" + browserslist "^4.22.2" + lru-cache "^5.1.1" + semver "^6.3.1" + +"@babel/helper-environment-visitor@^7.22.20": + version "7.22.20" + resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz#96159db61d34a29dba454c959f5ae4a649ba9167" + integrity sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA== + +"@babel/helper-function-name@^7.23.0": + version "7.23.0" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz#1f9a3cdbd5b2698a670c30d2735f9af95ed52759" + integrity sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw== + dependencies: + "@babel/template" "^7.22.15" + "@babel/types" "^7.23.0" + +"@babel/helper-hoist-variables@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz#c01a007dac05c085914e8fb652b339db50d823bb" + integrity sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw== + dependencies: + "@babel/types" "^7.22.5" + +"@babel/helper-module-imports@^7.22.15": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz#16146307acdc40cc00c3b2c647713076464bdbf0" + integrity sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w== + dependencies: + "@babel/types" "^7.22.15" + +"@babel/helper-module-transforms@^7.23.3": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz#d7d12c3c5d30af5b3c0fcab2a6d5217773e2d0f1" + integrity sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ== + dependencies: + "@babel/helper-environment-visitor" "^7.22.20" + "@babel/helper-module-imports" "^7.22.15" + "@babel/helper-simple-access" "^7.22.5" + "@babel/helper-split-export-declaration" "^7.22.6" + "@babel/helper-validator-identifier" "^7.22.20" + +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.22.5", "@babel/helper-plugin-utils@^7.8.0": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz#dd7ee3735e8a313b9f7b05a773d892e88e6d7295" + integrity sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg== + +"@babel/helper-simple-access@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz#4938357dc7d782b80ed6dbb03a0fba3d22b1d5de" + integrity sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w== + dependencies: + "@babel/types" "^7.22.5" + +"@babel/helper-split-export-declaration@^7.22.6": + version "7.22.6" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz#322c61b7310c0997fe4c323955667f18fcefb91c" + integrity sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g== + dependencies: + "@babel/types" "^7.22.5" + +"@babel/helper-string-parser@^7.23.4": + version "7.23.4" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz#9478c707febcbbe1ddb38a3d91a2e054ae622d83" + integrity sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ== + +"@babel/helper-validator-identifier@^7.22.20": + version "7.22.20" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0" + integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A== + +"@babel/helper-validator-option@^7.23.5": + version "7.23.5" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz#907a3fbd4523426285365d1206c423c4c5520307" + integrity sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw== + +"@babel/helpers@^7.23.6": + version "7.23.6" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.23.6.tgz#d03af2ee5fb34691eec0cda90f5ecbb4d4da145a" + integrity sha512-wCfsbN4nBidDRhpDhvcKlzHWCTlgJYUUdSJfzXb2NuBssDSIjc3xcb+znA7l+zYsFljAcGM0aFkN40cR3lXiGA== + dependencies: + "@babel/template" "^7.22.15" + "@babel/traverse" "^7.23.6" + "@babel/types" "^7.23.6" + +"@babel/highlight@^7.23.4": + version "7.23.4" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.23.4.tgz#edaadf4d8232e1a961432db785091207ead0621b" + integrity sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A== + dependencies: + "@babel/helper-validator-identifier" "^7.22.20" + chalk "^2.4.2" + js-tokens "^4.0.0" + +"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7", "@babel/parser@^7.22.15", "@babel/parser@^7.23.6": + version "7.23.6" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.23.6.tgz#ba1c9e512bda72a47e285ae42aff9d2a635a9e3b" + integrity sha512-Z2uID7YJ7oNvAI20O9X0bblw7Qqs8Q2hFy0R9tAfnfLkp5MW0UH9eUvnDSnFwKZ0AvgS1ucqR4KzvVHgnke1VQ== + +"@babel/plugin-syntax-async-generators@^7.8.4": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" + integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-bigint@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz#4c9a6f669f5d0cdf1b90a1671e9a146be5300cea" + integrity sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-class-properties@^7.8.3": + version "7.12.13" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10" + integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA== + dependencies: + "@babel/helper-plugin-utils" "^7.12.13" + +"@babel/plugin-syntax-import-meta@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51" + integrity sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-json-strings@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" + integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-jsx@^7.7.2": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.23.3.tgz#8f2e4f8a9b5f9aa16067e142c1ac9cd9f810f473" + integrity sha512-EB2MELswq55OHUoRZLGg/zC7QWUKfNLpE57m/S2yr1uEneIgsTgrSzXP3NXEsMkVn76OlaVVnzN+ugObuYGwhg== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-syntax-logical-assignment-operators@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" + integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" + integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-numeric-separator@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" + integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-object-rest-spread@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" + integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-optional-catch-binding@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" + integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-optional-chaining@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" + integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-top-level-await@^7.8.3": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz#c1cfdadc35a646240001f06138247b741c34d94c" + integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + +"@babel/plugin-syntax-typescript@^7.7.2": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.23.3.tgz#24f460c85dbbc983cd2b9c4994178bcc01df958f" + integrity sha512-9EiNjVJOMwCO+43TqoTrgQ8jMwcAd0sWyXi9RPfIsLTj4R2MADDDQXELhffaUx/uJv2AYcxBgPwH6j4TIA4ytQ== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/template@^7.22.15", "@babel/template@^7.3.3": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.15.tgz#09576efc3830f0430f4548ef971dde1350ef2f38" + integrity sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w== + dependencies: + "@babel/code-frame" "^7.22.13" + "@babel/parser" "^7.22.15" + "@babel/types" "^7.22.15" + +"@babel/traverse@^7.23.6": + version "7.23.6" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.23.6.tgz#b53526a2367a0dd6edc423637f3d2d0f2521abc5" + integrity sha512-czastdK1e8YByZqezMPFiZ8ahwVMh/ESl9vPgvgdB9AmFMGP5jfpFax74AQgl5zj4XHzqeYAg2l8PuUeRS1MgQ== + dependencies: + "@babel/code-frame" "^7.23.5" + "@babel/generator" "^7.23.6" + "@babel/helper-environment-visitor" "^7.22.20" + "@babel/helper-function-name" "^7.23.0" + "@babel/helper-hoist-variables" "^7.22.5" + "@babel/helper-split-export-declaration" "^7.22.6" + "@babel/parser" "^7.23.6" + "@babel/types" "^7.23.6" + debug "^4.3.1" + globals "^11.1.0" + +"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.22.15", "@babel/types@^7.22.5", "@babel/types@^7.23.0", "@babel/types@^7.23.6", "@babel/types@^7.3.3": + version "7.23.6" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.23.6.tgz#be33fdb151e1f5a56877d704492c240fc71c7ccd" + integrity sha512-+uarb83brBzPKN38NX1MkB6vb6+mwvR6amUulqAE7ccQw1pEl+bCia9TbdG1lsnFP7lZySvUn37CHyXQdfTwzg== + dependencies: + "@babel/helper-string-parser" "^7.23.4" + "@babel/helper-validator-identifier" "^7.22.20" + to-fast-properties "^2.0.0" + +"@bcoe/v8-coverage@^0.2.3": + version "0.2.3" + resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" + integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== + +"@colors/colors@1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9" + integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ== + +"@cspotcode/source-map-consumer@0.8.0": + version "0.8.0" + resolved "https://registry.yarnpkg.com/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz#33bf4b7b39c178821606f669bbc447a6a629786b" + integrity sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg== + +"@cspotcode/source-map-support@0.7.0": + version "0.7.0" + resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.7.0.tgz#4789840aa859e46d2f3173727ab707c66bf344f5" + integrity sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA== + dependencies: + "@cspotcode/source-map-consumer" "0.8.0" + +"@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0": + version "4.4.0" + resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" + integrity sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA== + dependencies: + eslint-visitor-keys "^3.3.0" + +"@eslint-community/regexpp@^4.10.0", "@eslint-community/regexpp@^4.12.1": + version "4.12.1" + resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.12.1.tgz#cfc6cffe39df390a3841cde2abccf92eaa7ae0e0" + integrity sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ== + +"@eslint/config-array@^0.19.0": + version "0.19.2" + resolved "https://registry.yarnpkg.com/@eslint/config-array/-/config-array-0.19.2.tgz#3060b809e111abfc97adb0bb1172778b90cb46aa" + integrity sha512-GNKqxfHG2ySmJOBSHg7LxeUx4xpuCoFjacmlCoYWEbaPXLwvfIjixRI12xCQZeULksQb23uiA8F40w5TojpV7w== + dependencies: + "@eslint/object-schema" "^2.1.6" + debug "^4.3.1" + minimatch "^3.1.2" + +"@eslint/core@^0.10.0": + version "0.10.0" + resolved "https://registry.yarnpkg.com/@eslint/core/-/core-0.10.0.tgz#23727063c21b335f752dbb3a16450f6f9cbc9091" + integrity sha512-gFHJ+xBOo4G3WRlR1e/3G8A6/KZAH6zcE/hkLRCZTi/B9avAG365QhFA8uOGzTMqgTghpn7/fSnscW++dpMSAw== + dependencies: + "@types/json-schema" "^7.0.15" + +"@eslint/core@^0.11.0": + version "0.11.0" + resolved "https://registry.yarnpkg.com/@eslint/core/-/core-0.11.0.tgz#7a9226e850922e42cbd2ba71361eacbe74352a12" + integrity sha512-DWUB2pksgNEb6Bz2fggIy1wh6fGgZP4Xyy/Mt0QZPiloKKXerbqq9D3SBQTlCRYOrcRPu4vuz+CGjwdfqxnoWA== + dependencies: + "@types/json-schema" "^7.0.15" + +"@eslint/eslintrc@^3.2.0": + version "3.2.0" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-3.2.0.tgz#57470ac4e2e283a6bf76044d63281196e370542c" + integrity sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w== + dependencies: + ajv "^6.12.4" + debug "^4.3.2" + espree "^10.0.1" + globals "^14.0.0" + ignore "^5.2.0" + import-fresh "^3.2.1" + js-yaml "^4.1.0" + minimatch "^3.1.2" + strip-json-comments "^3.1.1" + +"@eslint/js@9.20.0": + version "9.20.0" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-9.20.0.tgz#7421bcbe74889fcd65d1be59f00130c289856eb4" + integrity sha512-iZA07H9io9Wn836aVTytRaNqh00Sad+EamwOVJT12GTLw1VGMFV/4JaME+JjLtr9fiGaoWgYnS54wrfWsSs4oQ== + +"@eslint/object-schema@^2.1.6": + version "2.1.6" + resolved "https://registry.yarnpkg.com/@eslint/object-schema/-/object-schema-2.1.6.tgz#58369ab5b5b3ca117880c0f6c0b0f32f6950f24f" + integrity sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA== + +"@eslint/plugin-kit@^0.2.5": + version "0.2.5" + resolved "https://registry.yarnpkg.com/@eslint/plugin-kit/-/plugin-kit-0.2.5.tgz#ee07372035539e7847ef834e3f5e7b79f09e3a81" + integrity sha512-lB05FkqEdUg2AA0xEbUz0SnkXT1LcCTa438W4IWTUh4hdOnVbQyOJ81OrDXsJk/LSiJHubgGEFoR5EHq1NsH1A== + dependencies: + "@eslint/core" "^0.10.0" + levn "^0.4.1" + +"@humanfs/core@^0.19.1": + version "0.19.1" + resolved "https://registry.yarnpkg.com/@humanfs/core/-/core-0.19.1.tgz#17c55ca7d426733fe3c561906b8173c336b40a77" + integrity sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA== + +"@humanfs/node@^0.16.6": + version "0.16.6" + resolved "https://registry.yarnpkg.com/@humanfs/node/-/node-0.16.6.tgz#ee2a10eaabd1131987bf0488fd9b820174cd765e" + integrity sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw== + dependencies: + "@humanfs/core" "^0.19.1" + "@humanwhocodes/retry" "^0.3.0" + +"@humanwhocodes/module-importer@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" + integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== + +"@humanwhocodes/retry@^0.3.0": + version "0.3.1" + resolved "https://registry.yarnpkg.com/@humanwhocodes/retry/-/retry-0.3.1.tgz#c72a5c76a9fbaf3488e231b13dc52c0da7bab42a" + integrity sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA== + +"@humanwhocodes/retry@^0.4.1": + version "0.4.1" + resolved "https://registry.yarnpkg.com/@humanwhocodes/retry/-/retry-0.4.1.tgz#9a96ce501bc62df46c4031fbd970e3cc6b10f07b" + integrity sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA== + +"@istanbuljs/load-nyc-config@^1.0.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" + integrity sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ== + dependencies: + camelcase "^5.3.1" + find-up "^4.1.0" + get-package-type "^0.1.0" + js-yaml "^3.13.1" + resolve-from "^5.0.0" + +"@istanbuljs/schema@^0.1.2": + version "0.1.3" + resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" + integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== + +"@jest/console@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/console/-/console-29.7.0.tgz#cd4822dbdb84529265c5a2bdb529a3c9cc950ffc" + integrity sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg== + dependencies: + "@jest/types" "^29.6.3" + "@types/node" "*" + chalk "^4.0.0" + jest-message-util "^29.7.0" + jest-util "^29.7.0" + slash "^3.0.0" + +"@jest/core@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/core/-/core-29.7.0.tgz#b6cccc239f30ff36609658c5a5e2291757ce448f" + integrity sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg== + dependencies: + "@jest/console" "^29.7.0" + "@jest/reporters" "^29.7.0" + "@jest/test-result" "^29.7.0" + "@jest/transform" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + ansi-escapes "^4.2.1" + chalk "^4.0.0" + ci-info "^3.2.0" + exit "^0.1.2" + graceful-fs "^4.2.9" + jest-changed-files "^29.7.0" + jest-config "^29.7.0" + jest-haste-map "^29.7.0" + jest-message-util "^29.7.0" + jest-regex-util "^29.6.3" + jest-resolve "^29.7.0" + jest-resolve-dependencies "^29.7.0" + jest-runner "^29.7.0" + jest-runtime "^29.7.0" + jest-snapshot "^29.7.0" + jest-util "^29.7.0" + jest-validate "^29.7.0" + jest-watcher "^29.7.0" + micromatch "^4.0.4" + pretty-format "^29.7.0" + slash "^3.0.0" + strip-ansi "^6.0.0" + +"@jest/create-cache-key-function@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/create-cache-key-function/-/create-cache-key-function-29.7.0.tgz#793be38148fab78e65f40ae30c36785f4ad859f0" + integrity sha512-4QqS3LY5PBmTRHj9sAg1HLoPzqAI0uOX6wI/TRqHIcOxlFidy6YEmCQJk6FSZjNLGCeubDMfmkWL+qaLKhSGQA== + dependencies: + "@jest/types" "^29.6.3" + +"@jest/environment@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-29.7.0.tgz#24d61f54ff1f786f3cd4073b4b94416383baf2a7" + integrity sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw== + dependencies: + "@jest/fake-timers" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + jest-mock "^29.7.0" + +"@jest/expect-utils@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/expect-utils/-/expect-utils-29.7.0.tgz#023efe5d26a8a70f21677d0a1afc0f0a44e3a1c6" + integrity sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA== + dependencies: + jest-get-type "^29.6.3" + +"@jest/expect@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/expect/-/expect-29.7.0.tgz#76a3edb0cb753b70dfbfe23283510d3d45432bf2" + integrity sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ== + dependencies: + expect "^29.7.0" + jest-snapshot "^29.7.0" + +"@jest/fake-timers@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-29.7.0.tgz#fd91bf1fffb16d7d0d24a426ab1a47a49881a565" + integrity sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ== + dependencies: + "@jest/types" "^29.6.3" + "@sinonjs/fake-timers" "^10.0.2" + "@types/node" "*" + jest-message-util "^29.7.0" + jest-mock "^29.7.0" + jest-util "^29.7.0" + +"@jest/globals@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-29.7.0.tgz#8d9290f9ec47ff772607fa864ca1d5a2efae1d4d" + integrity sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ== + dependencies: + "@jest/environment" "^29.7.0" + "@jest/expect" "^29.7.0" + "@jest/types" "^29.6.3" + jest-mock "^29.7.0" + +"@jest/reporters@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-29.7.0.tgz#04b262ecb3b8faa83b0b3d321623972393e8f4c7" + integrity sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg== + dependencies: + "@bcoe/v8-coverage" "^0.2.3" + "@jest/console" "^29.7.0" + "@jest/test-result" "^29.7.0" + "@jest/transform" "^29.7.0" + "@jest/types" "^29.6.3" + "@jridgewell/trace-mapping" "^0.3.18" + "@types/node" "*" + chalk "^4.0.0" + collect-v8-coverage "^1.0.0" + exit "^0.1.2" + glob "^7.1.3" + graceful-fs "^4.2.9" + istanbul-lib-coverage "^3.0.0" + istanbul-lib-instrument "^6.0.0" + istanbul-lib-report "^3.0.0" + istanbul-lib-source-maps "^4.0.0" + istanbul-reports "^3.1.3" + jest-message-util "^29.7.0" + jest-util "^29.7.0" + jest-worker "^29.7.0" + slash "^3.0.0" + string-length "^4.0.1" + strip-ansi "^6.0.0" + v8-to-istanbul "^9.0.1" + +"@jest/schemas@^29.6.3": + version "29.6.3" + resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-29.6.3.tgz#430b5ce8a4e0044a7e3819663305a7b3091c8e03" + integrity sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA== + dependencies: + "@sinclair/typebox" "^0.27.8" + +"@jest/source-map@^29.6.3": + version "29.6.3" + resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-29.6.3.tgz#d90ba772095cf37a34a5eb9413f1b562a08554c4" + integrity sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw== + dependencies: + "@jridgewell/trace-mapping" "^0.3.18" + callsites "^3.0.0" + graceful-fs "^4.2.9" + +"@jest/test-result@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-29.7.0.tgz#8db9a80aa1a097bb2262572686734baed9b1657c" + integrity sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA== + dependencies: + "@jest/console" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/istanbul-lib-coverage" "^2.0.0" + collect-v8-coverage "^1.0.0" + +"@jest/test-sequencer@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz#6cef977ce1d39834a3aea887a1726628a6f072ce" + integrity sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw== + dependencies: + "@jest/test-result" "^29.7.0" + graceful-fs "^4.2.9" + jest-haste-map "^29.7.0" + slash "^3.0.0" + +"@jest/transform@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-29.7.0.tgz#df2dd9c346c7d7768b8a06639994640c642e284c" + integrity sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw== + dependencies: + "@babel/core" "^7.11.6" + "@jest/types" "^29.6.3" + "@jridgewell/trace-mapping" "^0.3.18" + babel-plugin-istanbul "^6.1.1" + chalk "^4.0.0" + convert-source-map "^2.0.0" + fast-json-stable-stringify "^2.1.0" + graceful-fs "^4.2.9" + jest-haste-map "^29.7.0" + jest-regex-util "^29.6.3" + jest-util "^29.7.0" + micromatch "^4.0.4" + pirates "^4.0.4" + slash "^3.0.0" + write-file-atomic "^4.0.2" + +"@jest/types@^29.6.3": + version "29.6.3" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-29.6.3.tgz#1131f8cf634e7e84c5e77bab12f052af585fba59" + integrity sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw== + dependencies: + "@jest/schemas" "^29.6.3" + "@types/istanbul-lib-coverage" "^2.0.0" + "@types/istanbul-reports" "^3.0.0" + "@types/node" "*" + "@types/yargs" "^17.0.8" + chalk "^4.0.0" + +"@jridgewell/gen-mapping@^0.3.0", "@jridgewell/gen-mapping@^0.3.2": + version "0.3.3" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz#7e02e6eb5df901aaedb08514203b096614024098" + integrity sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ== + dependencies: + "@jridgewell/set-array" "^1.0.1" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping" "^0.3.9" + +"@jridgewell/resolve-uri@^3.1.0": + version "3.1.1" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz#c08679063f279615a3326583ba3a90d1d82cc721" + integrity sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA== + +"@jridgewell/set-array@^1.0.1": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" + integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== + +"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14": + version "1.4.15" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" + integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== + +"@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.18", "@jridgewell/trace-mapping@^0.3.9": + version "0.3.20" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz#72e45707cf240fa6b081d0366f8265b0cd10197f" + integrity sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q== + dependencies: + "@jridgewell/resolve-uri" "^3.1.0" + "@jridgewell/sourcemap-codec" "^1.4.14" + +"@nodelib/fs.scandir@2.1.5": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" + integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== + dependencies: + "@nodelib/fs.stat" "2.0.5" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" + integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== + +"@nodelib/fs.walk@^1.2.3": + version "1.2.8" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" + integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== + dependencies: + "@nodelib/fs.scandir" "2.1.5" + fastq "^1.6.0" + +"@pkgr/core@^0.1.0": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@pkgr/core/-/core-0.1.1.tgz#1ec17e2edbec25c8306d424ecfbf13c7de1aaa31" + integrity sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA== + +"@sinclair/typebox@^0.27.8": + version "0.27.8" + resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.27.8.tgz#6667fac16c436b5434a387a34dedb013198f6e6e" + integrity sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA== + +"@sindresorhus/is@^4.6.0": + version "4.6.0" + resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-4.6.0.tgz#3c7c9c46e678feefe7a2e5bb609d3dbd665ffb3f" + integrity sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw== + +"@sinonjs/commons@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-3.0.0.tgz#beb434fe875d965265e04722ccfc21df7f755d72" + integrity sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA== + dependencies: + type-detect "4.0.8" + +"@sinonjs/fake-timers@^10.0.2": + version "10.3.0" + resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz#55fdff1ecab9f354019129daf4df0dd4d923ea66" + integrity sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA== + dependencies: + "@sinonjs/commons" "^3.0.0" + +"@swc/core-darwin-arm64@1.4.16": + version "1.4.16" + resolved "https://registry.yarnpkg.com/@swc/core-darwin-arm64/-/core-darwin-arm64-1.4.16.tgz#2cd45d709ce76d448d96bf8d0006849541436611" + integrity sha512-UOCcH1GvjRnnM/LWT6VCGpIk0OhHRq6v1U6QXuPt5wVsgXnXQwnf5k3sG5Cm56hQHDvhRPY6HCsHi/p0oek8oQ== + +"@swc/core-darwin-x64@1.4.16": + version "1.4.16" + resolved "https://registry.yarnpkg.com/@swc/core-darwin-x64/-/core-darwin-x64-1.4.16.tgz#a5bc7d8b1dd850adb0bb95c6b5c742b92201fd01" + integrity sha512-t3bgqFoYLWvyVtVL6KkFNCINEoOrIlyggT/kJRgi1y0aXSr0oVgcrQ4ezJpdeahZZ4N+Q6vT3ffM30yIunELNA== + +"@swc/core-linux-arm-gnueabihf@1.4.16": + version "1.4.16" + resolved "https://registry.yarnpkg.com/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.4.16.tgz#961744908ee5cbb79bc009dcf58cc8b831111f38" + integrity sha512-DvHuwvEF86YvSd0lwnzVcjOTZ0jcxewIbsN0vc/0fqm9qBdMMjr9ox6VCam1n3yYeRtj4VFgrjeNFksqbUejdQ== + +"@swc/core-linux-arm64-gnu@1.4.16": + version "1.4.16" + resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.4.16.tgz#43713be3f26757d82d2745dc25f8b63400e0a3d0" + integrity sha512-9Uu5YlPbyCvbidjKtYEsPpyZlu16roOZ5c2tP1vHfnU9bgf5Tz5q5VovSduNxPHx+ed2iC1b1URODHvDzbbDuQ== + +"@swc/core-linux-arm64-musl@1.4.16": + version "1.4.16" + resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.4.16.tgz#394a7d030f3a61902bd3947bb9d70d26d42f3c81" + integrity sha512-/YZq/qB1CHpeoL0eMzyqK5/tYZn/rzKoCYDviFU4uduSUIJsDJQuQA/skdqUzqbheOXKAd4mnJ1hT04RbJ8FPQ== + +"@swc/core-linux-x64-gnu@1.4.16": + version "1.4.16" + resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.4.16.tgz#71eb108b784f9d551ee8a35ebcdaed972f567981" + integrity sha512-UUjaW5VTngZYDcA8yQlrFmqs1tLi1TxbKlnaJwoNhel9zRQ0yG1YEVGrzTvv4YApSuIiDK18t+Ip927bwucuVQ== + +"@swc/core-linux-x64-musl@1.4.16": + version "1.4.16" + resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.4.16.tgz#10dbaedb4e3dfc7268e3a9a66ad3431471ef035b" + integrity sha512-aFhxPifevDTwEDKPi4eRYWzC0p/WYJeiFkkpNU5Uc7a7M5iMWPAbPFUbHesdlb9Jfqs5c07oyz86u+/HySBNPQ== + +"@swc/core-win32-arm64-msvc@1.4.16": + version "1.4.16" + resolved "https://registry.yarnpkg.com/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.4.16.tgz#80247adff6c245ff32b44d773c1a148858cd655f" + integrity sha512-bTD43MbhIHL2s5QgCwyleaGwl96Gk/scF2TaVKdUe4QlJCDV/YK9h5oIBAp63ckHtE8GHlH4c8dZNBiAXn4Org== + +"@swc/core-win32-ia32-msvc@1.4.16": + version "1.4.16" + resolved "https://registry.yarnpkg.com/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.4.16.tgz#e540afc3ccf3224267b4ddfb408f9d9737984686" + integrity sha512-/lmZeAN/qV5XbK2SEvi8e2RkIg8FQNYiSA8y2/Zb4gTUMKVO5JMLH0BSWMiIKMstKDPDSxMWgwJaQHF8UMyPmQ== + +"@swc/core-win32-x64-msvc@1.4.16": + version "1.4.16" + resolved "https://registry.yarnpkg.com/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.4.16.tgz#f880939fca32c181adfe7e3abd2b6b7857bd3489" + integrity sha512-BPAfFfODWXtUu6SwaTTftDHvcbDyWBSI/oanUeRbQR5vVWkXoQ3cxLTsDluc3H74IqXS5z1Uyoe0vNo2hB1opA== + +"@swc/core@^1.3.102": + version "1.4.16" + resolved "https://registry.yarnpkg.com/@swc/core/-/core-1.4.16.tgz#d175bae2acfecd53bcbd4293f1fba5ec316634a0" + integrity sha512-Xaf+UBvW6JNuV131uvSNyMXHn+bh6LyKN4tbv7tOUFQpXyz/t9YWRE04emtlUW9Y0qrm/GKFCbY8n3z6BpZbTA== + dependencies: + "@swc/counter" "^0.1.2" + "@swc/types" "^0.1.5" + optionalDependencies: + "@swc/core-darwin-arm64" "1.4.16" + "@swc/core-darwin-x64" "1.4.16" + "@swc/core-linux-arm-gnueabihf" "1.4.16" + "@swc/core-linux-arm64-gnu" "1.4.16" + "@swc/core-linux-arm64-musl" "1.4.16" + "@swc/core-linux-x64-gnu" "1.4.16" + "@swc/core-linux-x64-musl" "1.4.16" + "@swc/core-win32-arm64-msvc" "1.4.16" + "@swc/core-win32-ia32-msvc" "1.4.16" + "@swc/core-win32-x64-msvc" "1.4.16" + +"@swc/counter@^0.1.2", "@swc/counter@^0.1.3": + version "0.1.3" + resolved "https://registry.yarnpkg.com/@swc/counter/-/counter-0.1.3.tgz#cc7463bd02949611c6329596fccd2b0ec782b0e9" + integrity sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ== + +"@swc/jest@^0.2.29": + version "0.2.36" + resolved "https://registry.yarnpkg.com/@swc/jest/-/jest-0.2.36.tgz#2797450a30d28b471997a17e901ccad946fe693e" + integrity sha512-8X80dp81ugxs4a11z1ka43FPhP+/e+mJNXJSxiNYk8gIX/jPBtY4gQTrKu/KIoco8bzKuPI5lUxjfLiGsfvnlw== + dependencies: + "@jest/create-cache-key-function" "^29.7.0" + "@swc/counter" "^0.1.3" + jsonc-parser "^3.2.0" + +"@swc/types@^0.1.5": + version "0.1.6" + resolved "https://registry.yarnpkg.com/@swc/types/-/types-0.1.6.tgz#2f13f748995b247d146de2784d3eb7195410faba" + integrity sha512-/JLo/l2JsT/LRd80C3HfbmVpxOAJ11FO2RCEslFrgzLltoP9j8XIbsyDcfCt2WWyX+CM96rBoNM+IToAkFOugg== + dependencies: + "@swc/counter" "^0.1.3" + +"@tsconfig/node10@^1.0.7": + version "1.0.8" + resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.8.tgz#c1e4e80d6f964fbecb3359c43bd48b40f7cadad9" + integrity sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg== + +"@tsconfig/node12@^1.0.7": + version "1.0.9" + resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.9.tgz#62c1f6dee2ebd9aead80dc3afa56810e58e1a04c" + integrity sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw== + +"@tsconfig/node14@^1.0.0": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.1.tgz#95f2d167ffb9b8d2068b0b235302fafd4df711f2" + integrity sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg== + +"@tsconfig/node16@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.2.tgz#423c77877d0569db20e1fc80885ac4118314010e" + integrity sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA== + +"@types/babel__core@^7.1.14": + version "7.20.5" + resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.20.5.tgz#3df15f27ba85319caa07ba08d0721889bb39c017" + integrity sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA== + dependencies: + "@babel/parser" "^7.20.7" + "@babel/types" "^7.20.7" + "@types/babel__generator" "*" + "@types/babel__template" "*" + "@types/babel__traverse" "*" + +"@types/babel__generator@*": + version "7.6.8" + resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.6.8.tgz#f836c61f48b1346e7d2b0d93c6dacc5b9535d3ab" + integrity sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw== + dependencies: + "@babel/types" "^7.0.0" + +"@types/babel__template@*": + version "7.4.4" + resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.4.4.tgz#5672513701c1b2199bc6dad636a9d7491586766f" + integrity sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A== + dependencies: + "@babel/parser" "^7.1.0" + "@babel/types" "^7.0.0" + +"@types/babel__traverse@*", "@types/babel__traverse@^7.0.6": + version "7.20.4" + resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.20.4.tgz#ec2c06fed6549df8bc0eb4615b683749a4a92e1b" + integrity sha512-mSM/iKUk5fDDrEV/e83qY+Cr3I1+Q3qqTuEn++HAWYjEa1+NxZr6CNrcJGf2ZTnq4HoFGC3zaTPZTobCzCFukA== + dependencies: + "@babel/types" "^7.20.7" + +"@types/estree@^1.0.6": + version "1.0.6" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.6.tgz#628effeeae2064a1b4e79f78e81d87b7e5fc7b50" + integrity sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw== + +"@types/graceful-fs@^4.1.3": + version "4.1.9" + resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.9.tgz#2a06bc0f68a20ab37b3e36aa238be6abdf49e8b4" + integrity sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ== + dependencies: + "@types/node" "*" + +"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1": + version "2.0.6" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz#7739c232a1fee9b4d3ce8985f314c0c6d33549d7" + integrity sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w== + +"@types/istanbul-lib-report@*": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz#53047614ae72e19fc0401d872de3ae2b4ce350bf" + integrity sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA== + dependencies: + "@types/istanbul-lib-coverage" "*" + +"@types/istanbul-reports@^3.0.0": + version "3.0.4" + resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz#0f03e3d2f670fbdac586e34b433783070cc16f54" + integrity sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ== + dependencies: + "@types/istanbul-lib-report" "*" + +"@types/jest@^29.4.0": + version "29.5.11" + resolved "https://registry.yarnpkg.com/@types/jest/-/jest-29.5.11.tgz#0c13aa0da7d0929f078ab080ae5d4ced80fa2f2c" + integrity sha512-S2mHmYIVe13vrm6q4kN6fLYYAka15ALQki/vgDC3mIukEOx8WJlv0kQPM+d4w8Gp6u0uSdKND04IlTXBv0rwnQ== + dependencies: + expect "^29.0.0" + pretty-format "^29.0.0" + +"@types/json-schema@^7.0.15": + version "7.0.15" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" + integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== + +"@types/node@*": + version "20.10.5" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.10.5.tgz#47ad460b514096b7ed63a1dae26fad0914ed3ab2" + integrity sha512-nNPsNE65wjMxEKI93yOP+NPGGBJz/PoN3kZsVLee0XMiJolxSekEVD8wRwBUBqkwc7UWop0edW50yrCQW4CyRw== + dependencies: + undici-types "~5.26.4" + +"@types/node@^20.17.6": + version "20.17.6" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.17.6.tgz#6e4073230c180d3579e8c60141f99efdf5df0081" + integrity sha512-VEI7OdvK2wP7XHnsuXbAJnEpEkF6NjSN45QJlL4VGqZSXsnicpesdTWsg9RISeSdYd3yeRj/y3k5KGjUXYnFwQ== + dependencies: + undici-types "~6.19.2" + +"@types/stack-utils@^2.0.0": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.3.tgz#6209321eb2c1712a7e7466422b8cb1fc0d9dd5d8" + integrity sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw== + +"@types/yargs-parser@*": + version "21.0.3" + resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.3.tgz#815e30b786d2e8f0dcd85fd5bcf5e1a04d008f15" + integrity sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ== + +"@types/yargs@^17.0.8": + version "17.0.32" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.32.tgz#030774723a2f7faafebf645f4e5a48371dca6229" + integrity sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog== + dependencies: + "@types/yargs-parser" "*" + +"@typescript-eslint/eslint-plugin@8.31.1": + version "8.31.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.31.1.tgz#62f1befe59647524994e89de4516d8dcba7a850a" + integrity sha512-oUlH4h1ABavI4F0Xnl8/fOtML/eu8nI2A1nYd+f+55XI0BLu+RIqKoCiZKNo6DtqZBEQm5aNKA20G3Z5w3R6GQ== + dependencies: + "@eslint-community/regexpp" "^4.10.0" + "@typescript-eslint/scope-manager" "8.31.1" + "@typescript-eslint/type-utils" "8.31.1" + "@typescript-eslint/utils" "8.31.1" + "@typescript-eslint/visitor-keys" "8.31.1" + graphemer "^1.4.0" + ignore "^5.3.1" + natural-compare "^1.4.0" + ts-api-utils "^2.0.1" + +"@typescript-eslint/parser@8.31.1": + version "8.31.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.31.1.tgz#e9b0ccf30d37dde724ee4d15f4dbc195995cce1b" + integrity sha512-oU/OtYVydhXnumd0BobL9rkJg7wFJ9bFFPmSmB/bf/XWN85hlViji59ko6bSKBXyseT9V8l+CN1nwmlbiN0G7Q== + dependencies: + "@typescript-eslint/scope-manager" "8.31.1" + "@typescript-eslint/types" "8.31.1" + "@typescript-eslint/typescript-estree" "8.31.1" + "@typescript-eslint/visitor-keys" "8.31.1" + debug "^4.3.4" + +"@typescript-eslint/scope-manager@8.31.1": + version "8.31.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.31.1.tgz#1eb52e76878f545e4add142e0d8e3e97e7aa443b" + integrity sha512-BMNLOElPxrtNQMIsFHE+3P0Yf1z0dJqV9zLdDxN/xLlWMlXK/ApEsVEKzpizg9oal8bAT5Sc7+ocal7AC1HCVw== + dependencies: + "@typescript-eslint/types" "8.31.1" + "@typescript-eslint/visitor-keys" "8.31.1" + +"@typescript-eslint/type-utils@8.31.1": + version "8.31.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.31.1.tgz#be0f438fb24b03568e282a0aed85f776409f970c" + integrity sha512-fNaT/m9n0+dpSp8G/iOQ05GoHYXbxw81x+yvr7TArTuZuCA6VVKbqWYVZrV5dVagpDTtj/O8k5HBEE/p/HM5LA== + dependencies: + "@typescript-eslint/typescript-estree" "8.31.1" + "@typescript-eslint/utils" "8.31.1" + debug "^4.3.4" + ts-api-utils "^2.0.1" + +"@typescript-eslint/types@8.31.1": + version "8.31.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.31.1.tgz#478ed6f7e8aee1be7b63a60212b6bffe1423b5d4" + integrity sha512-SfepaEFUDQYRoA70DD9GtytljBePSj17qPxFHA/h3eg6lPTqGJ5mWOtbXCk1YrVU1cTJRd14nhaXWFu0l2troQ== + +"@typescript-eslint/typescript-estree@8.31.1": + version "8.31.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.31.1.tgz#37792fe7ef4d3021c7580067c8f1ae66daabacdf" + integrity sha512-kaA0ueLe2v7KunYOyWYtlf/QhhZb7+qh4Yw6Ni5kgukMIG+iP773tjgBiLWIXYumWCwEq3nLW+TUywEp8uEeag== + dependencies: + "@typescript-eslint/types" "8.31.1" + "@typescript-eslint/visitor-keys" "8.31.1" + debug "^4.3.4" + fast-glob "^3.3.2" + is-glob "^4.0.3" + minimatch "^9.0.4" + semver "^7.6.0" + ts-api-utils "^2.0.1" + +"@typescript-eslint/utils@8.31.1": + version "8.31.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.31.1.tgz#5628ea0393598a0b2f143d0fc6d019f0dee9dd14" + integrity sha512-2DSI4SNfF5T4oRveQ4nUrSjUqjMND0nLq9rEkz0gfGr3tg0S5KB6DhwR+WZPCjzkZl3cH+4x2ce3EsL50FubjQ== + dependencies: + "@eslint-community/eslint-utils" "^4.4.0" + "@typescript-eslint/scope-manager" "8.31.1" + "@typescript-eslint/types" "8.31.1" + "@typescript-eslint/typescript-estree" "8.31.1" + +"@typescript-eslint/visitor-keys@8.31.1": + version "8.31.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.31.1.tgz#6742b0e3ba1e0c1e35bdaf78c03e759eb8dd8e75" + integrity sha512-I+/rgqOVBn6f0o7NDTmAPWWC6NuqhV174lfYvAm9fUaWeiefLdux9/YI3/nLugEn9L8fcSi0XmpKi/r5u0nmpw== + dependencies: + "@typescript-eslint/types" "8.31.1" + eslint-visitor-keys "^4.2.0" + +acorn-jsx@^5.3.2: + version "5.3.2" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" + integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== + +acorn-walk@^8.1.1: + version "8.2.0" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" + integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== + +acorn@^8.14.0: + version "8.14.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.14.0.tgz#063e2c70cac5fb4f6467f0b11152e04c682795b0" + integrity sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA== + +acorn@^8.4.1: + version "8.7.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.0.tgz#90951fde0f8f09df93549481e5fc141445b791cf" + integrity sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ== + +aggregate-error@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" + integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA== + dependencies: + clean-stack "^2.0.0" + indent-string "^4.0.0" + +ajv@^6.12.4: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +ansi-escapes@^4.2.1: + version "4.3.2" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" + integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== + dependencies: + type-fest "^0.21.3" + +ansi-escapes@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-7.0.0.tgz#00fc19f491bbb18e1d481b97868204f92109bfe7" + integrity sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw== + dependencies: + environment "^1.0.0" + +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +ansi-regex@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.1.0.tgz#95ec409c69619d6cb1b8b34f14b660ef28ebd654" + integrity sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA== + +ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + +ansi-styles@^4.0.0, ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +ansi-styles@^5.0.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" + integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== + +any-promise@^1.0.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f" + integrity sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A== + +anymatch@^3.0.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" + integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +arg@^4.1.0: + version "4.1.3" + resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" + integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== + +argparse@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== + dependencies: + sprintf-js "~1.0.2" + +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + +babel-jest@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-29.7.0.tgz#f4369919225b684c56085998ac63dbd05be020d5" + integrity sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg== + dependencies: + "@jest/transform" "^29.7.0" + "@types/babel__core" "^7.1.14" + babel-plugin-istanbul "^6.1.1" + babel-preset-jest "^29.6.3" + chalk "^4.0.0" + graceful-fs "^4.2.9" + slash "^3.0.0" + +babel-plugin-istanbul@^6.1.1: + version "6.1.1" + resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz#fa88ec59232fd9b4e36dbbc540a8ec9a9b47da73" + integrity sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@istanbuljs/load-nyc-config" "^1.0.0" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-instrument "^5.0.4" + test-exclude "^6.0.0" + +babel-plugin-jest-hoist@^29.6.3: + version "29.6.3" + resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz#aadbe943464182a8922c3c927c3067ff40d24626" + integrity sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg== + dependencies: + "@babel/template" "^7.3.3" + "@babel/types" "^7.3.3" + "@types/babel__core" "^7.1.14" + "@types/babel__traverse" "^7.0.6" + +babel-preset-current-node-syntax@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz#b4399239b89b2a011f9ddbe3e4f401fc40cff73b" + integrity sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ== + dependencies: + "@babel/plugin-syntax-async-generators" "^7.8.4" + "@babel/plugin-syntax-bigint" "^7.8.3" + "@babel/plugin-syntax-class-properties" "^7.8.3" + "@babel/plugin-syntax-import-meta" "^7.8.3" + "@babel/plugin-syntax-json-strings" "^7.8.3" + "@babel/plugin-syntax-logical-assignment-operators" "^7.8.3" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + "@babel/plugin-syntax-numeric-separator" "^7.8.3" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" + "@babel/plugin-syntax-top-level-await" "^7.8.3" + +babel-preset-jest@^29.6.3: + version "29.6.3" + resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz#fa05fa510e7d493896d7b0dd2033601c840f171c" + integrity sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA== + dependencies: + babel-plugin-jest-hoist "^29.6.3" + babel-preset-current-node-syntax "^1.0.0" + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +brace-expansion@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" + integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== + dependencies: + balanced-match "^1.0.0" + +braces@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" + integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== + dependencies: + fill-range "^7.1.1" + +browserslist@^4.22.2: + version "4.22.2" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.22.2.tgz#704c4943072bd81ea18997f3bd2180e89c77874b" + integrity sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A== + dependencies: + caniuse-lite "^1.0.30001565" + electron-to-chromium "^1.4.601" + node-releases "^2.0.14" + update-browserslist-db "^1.0.13" + +bs-logger@0.x: + version "0.2.6" + resolved "https://registry.yarnpkg.com/bs-logger/-/bs-logger-0.2.6.tgz#eb7d365307a72cf974cc6cda76b68354ad336bd8" + integrity sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog== + dependencies: + fast-json-stable-stringify "2.x" + +bser@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05" + integrity sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ== + dependencies: + node-int64 "^0.4.0" + +buffer-from@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" + integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== + +callsites@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== + +camelcase@^5.3.1: + version "5.3.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== + +camelcase@^6.2.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" + integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== + +caniuse-lite@^1.0.30001565: + version "1.0.30001570" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001570.tgz#b4e5c1fa786f733ab78fc70f592df6b3f23244ca" + integrity sha512-+3e0ASu4sw1SWaoCtvPeyXp+5PsjigkSt8OXZbF9StH5pQWbxEjLAZE3n8Aup5udop1uRiKA7a4utUk/uoSpUw== + +chalk@^2.4.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +chalk@^4.0.0, chalk@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +chalk@^5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.3.0.tgz#67c20a7ebef70e7f3970a01f90fa210cb6860385" + integrity sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w== + +char-regex@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" + integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== + +ci-info@^3.2.0: + version "3.9.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.9.0.tgz#4279a62028a7b1f262f3473fc9605f5e218c59b4" + integrity sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ== + +cjs-module-lexer@^1.0.0: + version "1.2.3" + resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz#6c370ab19f8a3394e318fe682686ec0ac684d107" + integrity sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ== + +cjs-module-lexer@^1.2.3: + version "1.4.1" + resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.4.1.tgz#707413784dbb3a72aa11c2f2b042a0bef4004170" + integrity sha512-cuSVIHi9/9E/+821Qjdvngor+xpnlwnuwIyZOaLmHBVdXL+gP+I6QQB9VkO7RI77YIcTV+S1W9AreJ5eN63JBA== + +clean-stack@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" + integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== + +cli-highlight@^2.1.11: + version "2.1.11" + resolved "https://registry.yarnpkg.com/cli-highlight/-/cli-highlight-2.1.11.tgz#49736fa452f0aaf4fae580e30acb26828d2dc1bf" + integrity sha512-9KDcoEVwyUXrjcJNvHD0NFc/hiwe/WPVYIleQh2O1N2Zro5gWJZ/K+3DGn8w8P/F6FxOgzyC5bxDyHIgCSPhGg== + dependencies: + chalk "^4.0.0" + highlight.js "^10.7.1" + mz "^2.4.0" + parse5 "^5.1.1" + parse5-htmlparser2-tree-adapter "^6.0.0" + yargs "^16.0.0" + +cli-table3@^0.6.3, cli-table3@^0.6.5: + version "0.6.5" + resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.6.5.tgz#013b91351762739c16a9567c21a04632e449bf2f" + integrity sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ== + dependencies: + string-width "^4.2.0" + optionalDependencies: + "@colors/colors" "1.5.0" + +cliui@^7.0.2: + version "7.0.4" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" + integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^7.0.0" + +cliui@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" + integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.1" + wrap-ansi "^7.0.0" + +co@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" + integrity sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ== + +collect-v8-coverage@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz#c0b29bcd33bcd0779a1344c2136051e6afd3d9e9" + integrity sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q== + +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +commander@^10.0.1: + version "10.0.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.1.tgz#881ee46b4f77d1c1dccc5823433aa39b022cbe06" + integrity sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug== + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== + +convert-source-map@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" + integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== + +create-jest@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/create-jest/-/create-jest-29.7.0.tgz#a355c5b3cb1e1af02ba177fe7afd7feee49a5320" + integrity sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q== + dependencies: + "@jest/types" "^29.6.3" + chalk "^4.0.0" + exit "^0.1.2" + graceful-fs "^4.2.9" + jest-config "^29.7.0" + jest-util "^29.7.0" + prompts "^2.0.1" + +create-require@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" + integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== + +cross-spawn@^7.0.3, cross-spawn@^7.0.6: + version "7.0.6" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f" + integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + +debug@^4.3.4, debug@^4.3.7: + version "4.3.7" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.7.tgz#87945b4151a011d76d95a198d7111c865c360a52" + integrity sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ== + dependencies: + ms "^2.1.3" + +dedent@^1.0.0: + version "1.5.1" + resolved "https://registry.yarnpkg.com/dedent/-/dedent-1.5.1.tgz#4f3fc94c8b711e9bb2800d185cd6ad20f2a90aff" + integrity sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg== + +deep-is@^0.1.3: + version "0.1.4" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" + integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== + +deepmerge@^4.2.2: + version "4.3.1" + resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a" + integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A== + +detect-newline@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" + integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA== + +diff-sequences@^29.6.3: + version "29.6.3" + resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.6.3.tgz#4deaf894d11407c51efc8418012f9e70b84ea921" + integrity sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q== + +diff@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" + integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== + +electron-to-chromium@^1.4.601: + version "1.4.614" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.614.tgz#2fe789d61fa09cb875569f37c309d0c2701f91c0" + integrity sha512-X4ze/9Sc3QWs6h92yerwqv7aB/uU8vCjZcrMjA8N9R1pjMFRe44dLsck5FzLilOYvcXuDn93B+bpGYyufc70gQ== + +emittery@^0.13.1: + version "0.13.1" + resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.13.1.tgz#c04b8c3457490e0847ae51fced3af52d338e3dad" + integrity sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ== + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +emojilib@^2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/emojilib/-/emojilib-2.4.0.tgz#ac518a8bb0d5f76dda57289ccb2fdf9d39ae721e" + integrity sha512-5U0rVMU5Y2n2+ykNLQqMoqklN9ICBT/KsvC1Gz6vqHbz2AXXGkG+Pm5rMWk/8Vjrr/mY9985Hi8DYzn1F09Nyw== + +environment@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/environment/-/environment-1.1.0.tgz#8e86c66b180f363c7ab311787e0259665f45a9f1" + integrity sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q== + +error-ex@^1.3.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" + integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== + dependencies: + is-arrayish "^0.2.1" + +escalade@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" + integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== + +escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== + +escape-string-regexp@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" + integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== + +escape-string-regexp@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + +eslint-plugin-prettier@^5.2.3: + version "5.2.3" + resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.3.tgz#c4af01691a6fa9905207f0fbba0d7bea0902cce5" + integrity sha512-qJ+y0FfCp/mQYQ/vWQ3s7eUlFEL4PyKfAJxsnYTJ4YT73nsJBWqmEpFryxV9OeUiqmsTsYJ5Y+KDNaeP31wrRw== + dependencies: + prettier-linter-helpers "^1.0.0" + synckit "^0.9.1" + +eslint-plugin-unused-imports@^4.1.4: + version "4.1.4" + resolved "https://registry.yarnpkg.com/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-4.1.4.tgz#62ddc7446ccbf9aa7b6f1f0b00a980423cda2738" + integrity sha512-YptD6IzQjDardkl0POxnnRBhU1OEePMV0nd6siHaRBbd+lyh6NAhFEobiznKU7kTsSsDeSD62Pe7kAM1b7dAZQ== + +eslint-scope@^8.2.0: + version "8.2.0" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-8.2.0.tgz#377aa6f1cb5dc7592cfd0b7f892fd0cf352ce442" + integrity sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A== + dependencies: + esrecurse "^4.3.0" + estraverse "^5.2.0" + +eslint-visitor-keys@^3.3.0: + version "3.4.3" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" + integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== + +eslint-visitor-keys@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz#687bacb2af884fcdda8a6e7d65c606f46a14cd45" + integrity sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw== + +eslint@^9.20.1: + version "9.20.1" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-9.20.1.tgz#923924c078f5226832449bac86662dd7e53c91d6" + integrity sha512-m1mM33o6dBUjxl2qb6wv6nGNwCAsns1eKtaQ4l/NPHeTvhiUPbtdfMyktxN4B3fgHIgsYh1VT3V9txblpQHq+g== + dependencies: + "@eslint-community/eslint-utils" "^4.2.0" + "@eslint-community/regexpp" "^4.12.1" + "@eslint/config-array" "^0.19.0" + "@eslint/core" "^0.11.0" + "@eslint/eslintrc" "^3.2.0" + "@eslint/js" "9.20.0" + "@eslint/plugin-kit" "^0.2.5" + "@humanfs/node" "^0.16.6" + "@humanwhocodes/module-importer" "^1.0.1" + "@humanwhocodes/retry" "^0.4.1" + "@types/estree" "^1.0.6" + "@types/json-schema" "^7.0.15" + ajv "^6.12.4" + chalk "^4.0.0" + cross-spawn "^7.0.6" + debug "^4.3.2" + escape-string-regexp "^4.0.0" + eslint-scope "^8.2.0" + eslint-visitor-keys "^4.2.0" + espree "^10.3.0" + esquery "^1.5.0" + esutils "^2.0.2" + fast-deep-equal "^3.1.3" + file-entry-cache "^8.0.0" + find-up "^5.0.0" + glob-parent "^6.0.2" + ignore "^5.2.0" + imurmurhash "^0.1.4" + is-glob "^4.0.0" + json-stable-stringify-without-jsonify "^1.0.1" + lodash.merge "^4.6.2" + minimatch "^3.1.2" + natural-compare "^1.4.0" + optionator "^0.9.3" + +espree@^10.0.1, espree@^10.3.0: + version "10.3.0" + resolved "https://registry.yarnpkg.com/espree/-/espree-10.3.0.tgz#29267cf5b0cb98735b65e64ba07e0ed49d1eed8a" + integrity sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg== + dependencies: + acorn "^8.14.0" + acorn-jsx "^5.3.2" + eslint-visitor-keys "^4.2.0" + +esprima@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== + +esquery@^1.5.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.6.0.tgz#91419234f804d852a82dceec3e16cdc22cf9dae7" + integrity sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg== + dependencies: + estraverse "^5.1.0" + +esrecurse@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== + dependencies: + estraverse "^5.2.0" + +estraverse@^5.1.0, estraverse@^5.2.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" + integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== + +esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + +execa@^5.0.0: + version "5.1.1" + resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" + integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== + dependencies: + cross-spawn "^7.0.3" + get-stream "^6.0.0" + human-signals "^2.1.0" + is-stream "^2.0.0" + merge-stream "^2.0.0" + npm-run-path "^4.0.1" + onetime "^5.1.2" + signal-exit "^3.0.3" + strip-final-newline "^2.0.0" + +exit@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" + integrity sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ== + +expect@^29.0.0, expect@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/expect/-/expect-29.7.0.tgz#578874590dcb3214514084c08115d8aee61e11bc" + integrity sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw== + dependencies: + "@jest/expect-utils" "^29.7.0" + jest-get-type "^29.6.3" + jest-matcher-utils "^29.7.0" + jest-message-util "^29.7.0" + jest-util "^29.7.0" + +fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-diff@^1.1.2: + version "1.3.0" + resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.3.0.tgz#ece407fa550a64d638536cd727e129c61616e0f0" + integrity sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw== + +fast-glob@^3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129" + integrity sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.2" + merge2 "^1.3.0" + micromatch "^4.0.4" + +fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0, fast-json-stable-stringify@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + +fast-levenshtein@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== + +fastq@^1.6.0: + version "1.17.1" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.17.1.tgz#2a523f07a4e7b1e81a42b91b8bf2254107753b47" + integrity sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w== + dependencies: + reusify "^1.0.4" + +fb-watchman@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.2.tgz#e9524ee6b5c77e9e5001af0f85f3adbb8623255c" + integrity sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA== + dependencies: + bser "2.1.1" + +fflate@^0.8.2: + version "0.8.2" + resolved "https://registry.yarnpkg.com/fflate/-/fflate-0.8.2.tgz#fc8631f5347812ad6028bbe4a2308b2792aa1dea" + integrity sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A== + +file-entry-cache@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-8.0.0.tgz#7787bddcf1131bffb92636c69457bbc0edd6d81f" + integrity sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ== + dependencies: + flat-cache "^4.0.0" + +fill-range@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" + integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== + dependencies: + to-regex-range "^5.0.1" + +find-up@^4.0.0, find-up@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + +find-up@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + dependencies: + locate-path "^6.0.0" + path-exists "^4.0.0" + +flat-cache@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-4.0.1.tgz#0ece39fcb14ee012f4b0410bd33dd9c1f011127c" + integrity sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw== + dependencies: + flatted "^3.2.9" + keyv "^4.5.4" + +flatted@^3.2.9: + version "3.3.2" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.2.tgz#adba1448a9841bec72b42c532ea23dbbedef1a27" + integrity sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA== + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== + +fsevents@^2.3.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" + integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== + +function-bind@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== + +gensync@^1.0.0-beta.2: + version "1.0.0-beta.2" + resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" + integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== + +get-caller-file@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +get-package-type@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" + integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== + +get-stdin@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-8.0.0.tgz#cbad6a73feb75f6eeb22ba9e01f89aa28aa97a53" + integrity sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg== + +get-stream@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" + integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== + +glob-parent@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +glob-parent@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" + integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== + dependencies: + is-glob "^4.0.3" + +glob@^7.1.3, glob@^7.1.4: + version "7.2.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" + integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.1.1" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@^8.0.1: + version "8.1.0" + resolved "https://registry.yarnpkg.com/glob/-/glob-8.1.0.tgz#d388f656593ef708ee3e34640fdfb99a9fd1c33e" + integrity sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^5.0.1" + once "^1.3.0" + +globals@^11.1.0: + version "11.12.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" + integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== + +globals@^14.0.0: + version "14.0.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-14.0.0.tgz#898d7413c29babcf6bafe56fcadded858ada724e" + integrity sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ== + +graceful-fs@^4.2.9: + version "4.2.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== + +graphemer@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" + integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +hasown@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.0.tgz#f4c513d454a57b7c7e1650778de226b11700546c" + integrity sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA== + dependencies: + function-bind "^1.1.2" + +highlight.js@^10.7.1: + version "10.7.3" + resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-10.7.3.tgz#697272e3991356e40c3cac566a74eef681756531" + integrity sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A== + +html-escaper@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" + integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== + +human-signals@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" + integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== + +iconv-lite@^0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" + integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== + dependencies: + safer-buffer ">= 2.1.2 < 3.0.0" + +ignore-walk@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-5.0.1.tgz#5f199e23e1288f518d90358d461387788a154776" + integrity sha512-yemi4pMf51WKT7khInJqAvsIGzoqYXblnsz0ql8tM+yi1EKYTY1evX4NAbJrLL/Aanr2HyZeluqU+Oi7MGHokw== + dependencies: + minimatch "^5.0.1" + +ignore@^5.2.0, ignore@^5.3.1: + version "5.3.2" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5" + integrity sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g== + +import-fresh@^3.2.1: + version "3.3.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" + integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + +import-local@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.1.0.tgz#b4479df8a5fd44f6cdce24070675676063c95cb4" + integrity sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg== + dependencies: + pkg-dir "^4.2.0" + resolve-cwd "^3.0.0" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== + +indent-string@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" + integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@^2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== + +is-core-module@^2.13.0: + version "2.13.1" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.1.tgz#ad0d7532c6fea9da1ebdc82742d74525c6273384" + integrity sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw== + dependencies: + hasown "^2.0.0" + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-generator-fn@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118" + integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== + +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-stream@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" + integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + +istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0: + version "3.2.2" + resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz#2d166c4b0644d43a39f04bf6c2edd1e585f31756" + integrity sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg== + +istanbul-lib-instrument@^5.0.4: + version "5.2.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz#d10c8885c2125574e1c231cacadf955675e1ce3d" + integrity sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg== + dependencies: + "@babel/core" "^7.12.3" + "@babel/parser" "^7.14.7" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-coverage "^3.2.0" + semver "^6.3.0" + +istanbul-lib-instrument@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.1.tgz#71e87707e8041428732518c6fb5211761753fbdf" + integrity sha512-EAMEJBsYuyyztxMxW3g7ugGPkrZsV57v0Hmv3mm1uQsmB+QnZuepg731CRaIgeUVSdmsTngOkSnauNF8p7FIhA== + dependencies: + "@babel/core" "^7.12.3" + "@babel/parser" "^7.14.7" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-coverage "^3.2.0" + semver "^7.5.4" + +istanbul-lib-report@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz#908305bac9a5bd175ac6a74489eafd0fc2445a7d" + integrity sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw== + dependencies: + istanbul-lib-coverage "^3.0.0" + make-dir "^4.0.0" + supports-color "^7.1.0" + +istanbul-lib-source-maps@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz#895f3a709fcfba34c6de5a42939022f3e4358551" + integrity sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw== + dependencies: + debug "^4.1.1" + istanbul-lib-coverage "^3.0.0" + source-map "^0.6.1" + +istanbul-reports@^3.1.3: + version "3.1.6" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.6.tgz#2544bcab4768154281a2f0870471902704ccaa1a" + integrity sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg== + dependencies: + html-escaper "^2.0.0" + istanbul-lib-report "^3.0.0" + +jest-changed-files@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-29.7.0.tgz#1c06d07e77c78e1585d020424dedc10d6e17ac3a" + integrity sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w== + dependencies: + execa "^5.0.0" + jest-util "^29.7.0" + p-limit "^3.1.0" + +jest-circus@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-29.7.0.tgz#b6817a45fcc835d8b16d5962d0c026473ee3668a" + integrity sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw== + dependencies: + "@jest/environment" "^29.7.0" + "@jest/expect" "^29.7.0" + "@jest/test-result" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + chalk "^4.0.0" + co "^4.6.0" + dedent "^1.0.0" + is-generator-fn "^2.0.0" + jest-each "^29.7.0" + jest-matcher-utils "^29.7.0" + jest-message-util "^29.7.0" + jest-runtime "^29.7.0" + jest-snapshot "^29.7.0" + jest-util "^29.7.0" + p-limit "^3.1.0" + pretty-format "^29.7.0" + pure-rand "^6.0.0" + slash "^3.0.0" + stack-utils "^2.0.3" + +jest-cli@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-29.7.0.tgz#5592c940798e0cae677eec169264f2d839a37995" + integrity sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg== + dependencies: + "@jest/core" "^29.7.0" + "@jest/test-result" "^29.7.0" + "@jest/types" "^29.6.3" + chalk "^4.0.0" + create-jest "^29.7.0" + exit "^0.1.2" + import-local "^3.0.2" + jest-config "^29.7.0" + jest-util "^29.7.0" + jest-validate "^29.7.0" + yargs "^17.3.1" + +jest-config@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-29.7.0.tgz#bcbda8806dbcc01b1e316a46bb74085a84b0245f" + integrity sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ== + dependencies: + "@babel/core" "^7.11.6" + "@jest/test-sequencer" "^29.7.0" + "@jest/types" "^29.6.3" + babel-jest "^29.7.0" + chalk "^4.0.0" + ci-info "^3.2.0" + deepmerge "^4.2.2" + glob "^7.1.3" + graceful-fs "^4.2.9" + jest-circus "^29.7.0" + jest-environment-node "^29.7.0" + jest-get-type "^29.6.3" + jest-regex-util "^29.6.3" + jest-resolve "^29.7.0" + jest-runner "^29.7.0" + jest-util "^29.7.0" + jest-validate "^29.7.0" + micromatch "^4.0.4" + parse-json "^5.2.0" + pretty-format "^29.7.0" + slash "^3.0.0" + strip-json-comments "^3.1.1" + +jest-diff@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-29.7.0.tgz#017934a66ebb7ecf6f205e84699be10afd70458a" + integrity sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw== + dependencies: + chalk "^4.0.0" + diff-sequences "^29.6.3" + jest-get-type "^29.6.3" + pretty-format "^29.7.0" + +jest-docblock@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-29.7.0.tgz#8fddb6adc3cdc955c93e2a87f61cfd350d5d119a" + integrity sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g== + dependencies: + detect-newline "^3.0.0" + +jest-each@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-29.7.0.tgz#162a9b3f2328bdd991beaabffbb74745e56577d1" + integrity sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ== + dependencies: + "@jest/types" "^29.6.3" + chalk "^4.0.0" + jest-get-type "^29.6.3" + jest-util "^29.7.0" + pretty-format "^29.7.0" + +jest-environment-node@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-29.7.0.tgz#0b93e111dda8ec120bc8300e6d1fb9576e164376" + integrity sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw== + dependencies: + "@jest/environment" "^29.7.0" + "@jest/fake-timers" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + jest-mock "^29.7.0" + jest-util "^29.7.0" + +jest-get-type@^29.6.3: + version "29.6.3" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-29.6.3.tgz#36f499fdcea197c1045a127319c0481723908fd1" + integrity sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw== + +jest-haste-map@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-29.7.0.tgz#3c2396524482f5a0506376e6c858c3bbcc17b104" + integrity sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA== + dependencies: + "@jest/types" "^29.6.3" + "@types/graceful-fs" "^4.1.3" + "@types/node" "*" + anymatch "^3.0.3" + fb-watchman "^2.0.0" + graceful-fs "^4.2.9" + jest-regex-util "^29.6.3" + jest-util "^29.7.0" + jest-worker "^29.7.0" + micromatch "^4.0.4" + walker "^1.0.8" + optionalDependencies: + fsevents "^2.3.2" + +jest-leak-detector@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz#5b7ec0dadfdfec0ca383dc9aa016d36b5ea4c728" + integrity sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw== + dependencies: + jest-get-type "^29.6.3" + pretty-format "^29.7.0" + +jest-matcher-utils@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz#ae8fec79ff249fd592ce80e3ee474e83a6c44f12" + integrity sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g== + dependencies: + chalk "^4.0.0" + jest-diff "^29.7.0" + jest-get-type "^29.6.3" + pretty-format "^29.7.0" + +jest-message-util@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-29.7.0.tgz#8bc392e204e95dfe7564abbe72a404e28e51f7f3" + integrity sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w== + dependencies: + "@babel/code-frame" "^7.12.13" + "@jest/types" "^29.6.3" + "@types/stack-utils" "^2.0.0" + chalk "^4.0.0" + graceful-fs "^4.2.9" + micromatch "^4.0.4" + pretty-format "^29.7.0" + slash "^3.0.0" + stack-utils "^2.0.3" + +jest-mock@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-29.7.0.tgz#4e836cf60e99c6fcfabe9f99d017f3fdd50a6347" + integrity sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw== + dependencies: + "@jest/types" "^29.6.3" + "@types/node" "*" + jest-util "^29.7.0" + +jest-pnp-resolver@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz#930b1546164d4ad5937d5540e711d4d38d4cad2e" + integrity sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w== + +jest-regex-util@^29.6.3: + version "29.6.3" + resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-29.6.3.tgz#4a556d9c776af68e1c5f48194f4d0327d24e8a52" + integrity sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg== + +jest-resolve-dependencies@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz#1b04f2c095f37fc776ff40803dc92921b1e88428" + integrity sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA== + dependencies: + jest-regex-util "^29.6.3" + jest-snapshot "^29.7.0" + +jest-resolve@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-29.7.0.tgz#64d6a8992dd26f635ab0c01e5eef4399c6bcbc30" + integrity sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA== + dependencies: + chalk "^4.0.0" + graceful-fs "^4.2.9" + jest-haste-map "^29.7.0" + jest-pnp-resolver "^1.2.2" + jest-util "^29.7.0" + jest-validate "^29.7.0" + resolve "^1.20.0" + resolve.exports "^2.0.0" + slash "^3.0.0" + +jest-runner@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-29.7.0.tgz#809af072d408a53dcfd2e849a4c976d3132f718e" + integrity sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ== + dependencies: + "@jest/console" "^29.7.0" + "@jest/environment" "^29.7.0" + "@jest/test-result" "^29.7.0" + "@jest/transform" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + chalk "^4.0.0" + emittery "^0.13.1" + graceful-fs "^4.2.9" + jest-docblock "^29.7.0" + jest-environment-node "^29.7.0" + jest-haste-map "^29.7.0" + jest-leak-detector "^29.7.0" + jest-message-util "^29.7.0" + jest-resolve "^29.7.0" + jest-runtime "^29.7.0" + jest-util "^29.7.0" + jest-watcher "^29.7.0" + jest-worker "^29.7.0" + p-limit "^3.1.0" + source-map-support "0.5.13" + +jest-runtime@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-29.7.0.tgz#efecb3141cf7d3767a3a0cc8f7c9990587d3d817" + integrity sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ== + dependencies: + "@jest/environment" "^29.7.0" + "@jest/fake-timers" "^29.7.0" + "@jest/globals" "^29.7.0" + "@jest/source-map" "^29.6.3" + "@jest/test-result" "^29.7.0" + "@jest/transform" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + chalk "^4.0.0" + cjs-module-lexer "^1.0.0" + collect-v8-coverage "^1.0.0" + glob "^7.1.3" + graceful-fs "^4.2.9" + jest-haste-map "^29.7.0" + jest-message-util "^29.7.0" + jest-mock "^29.7.0" + jest-regex-util "^29.6.3" + jest-resolve "^29.7.0" + jest-snapshot "^29.7.0" + jest-util "^29.7.0" + slash "^3.0.0" + strip-bom "^4.0.0" + +jest-snapshot@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-29.7.0.tgz#c2c574c3f51865da1bb329036778a69bf88a6be5" + integrity sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw== + dependencies: + "@babel/core" "^7.11.6" + "@babel/generator" "^7.7.2" + "@babel/plugin-syntax-jsx" "^7.7.2" + "@babel/plugin-syntax-typescript" "^7.7.2" + "@babel/types" "^7.3.3" + "@jest/expect-utils" "^29.7.0" + "@jest/transform" "^29.7.0" + "@jest/types" "^29.6.3" + babel-preset-current-node-syntax "^1.0.0" + chalk "^4.0.0" + expect "^29.7.0" + graceful-fs "^4.2.9" + jest-diff "^29.7.0" + jest-get-type "^29.6.3" + jest-matcher-utils "^29.7.0" + jest-message-util "^29.7.0" + jest-util "^29.7.0" + natural-compare "^1.4.0" + pretty-format "^29.7.0" + semver "^7.5.3" + +jest-util@^29.0.0, jest-util@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.7.0.tgz#23c2b62bfb22be82b44de98055802ff3710fc0bc" + integrity sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA== + dependencies: + "@jest/types" "^29.6.3" + "@types/node" "*" + chalk "^4.0.0" + ci-info "^3.2.0" + graceful-fs "^4.2.9" + picomatch "^2.2.3" + +jest-validate@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-29.7.0.tgz#7bf705511c64da591d46b15fce41400d52147d9c" + integrity sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw== + dependencies: + "@jest/types" "^29.6.3" + camelcase "^6.2.0" + chalk "^4.0.0" + jest-get-type "^29.6.3" + leven "^3.1.0" + pretty-format "^29.7.0" + +jest-watcher@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-29.7.0.tgz#7810d30d619c3a62093223ce6bb359ca1b28a2f2" + integrity sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g== + dependencies: + "@jest/test-result" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + ansi-escapes "^4.2.1" + chalk "^4.0.0" + emittery "^0.13.1" + jest-util "^29.7.0" + string-length "^4.0.1" + +jest-worker@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-29.7.0.tgz#acad073acbbaeb7262bd5389e1bcf43e10058d4a" + integrity sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw== + dependencies: + "@types/node" "*" + jest-util "^29.7.0" + merge-stream "^2.0.0" + supports-color "^8.0.0" + +jest@^29.4.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest/-/jest-29.7.0.tgz#994676fc24177f088f1c5e3737f5697204ff2613" + integrity sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw== + dependencies: + "@jest/core" "^29.7.0" + "@jest/types" "^29.6.3" + import-local "^3.0.2" + jest-cli "^29.7.0" + +js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +js-yaml@^3.13.1: + version "3.14.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" + integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +js-yaml@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" + integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + dependencies: + argparse "^2.0.1" + +jsesc@^2.5.1: + version "2.5.2" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" + integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== + +json-buffer@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" + integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== + +json-parse-even-better-errors@^2.3.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" + integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-stable-stringify-without-jsonify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== + +json5@^2.2.2, json5@^2.2.3: + version "2.2.3" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" + integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== + +jsonc-parser@^3.2.0: + version "3.2.1" + resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-3.2.1.tgz#031904571ccf929d7670ee8c547545081cb37f1a" + integrity sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA== + +keyv@^4.5.4: + version "4.5.4" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" + integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw== + dependencies: + json-buffer "3.0.1" + +kleur@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" + integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== + +leven@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" + integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== + +levn@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" + integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== + dependencies: + prelude-ls "^1.2.1" + type-check "~0.4.0" + +lines-and-columns@^1.1.6: + version "1.2.4" + resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" + integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== + +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== + dependencies: + p-locate "^4.1.0" + +locate-path@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" + integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== + dependencies: + p-locate "^5.0.0" + +lodash.memoize@4.x: + version "4.1.2" + resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" + integrity sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag== + +lodash.merge@^4.6.2: + version "4.6.2" + resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" + integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== + +lru-cache@^10.4.3: + version "10.4.3" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.4.3.tgz#410fc8a17b70e598013df257c2446b7f3383f119" + integrity sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ== + +lru-cache@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" + integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== + dependencies: + yallist "^3.0.2" + +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + +make-dir@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-4.0.0.tgz#c3c2307a771277cd9638305f915c29ae741b614e" + integrity sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw== + dependencies: + semver "^7.5.3" + +make-error@1.x, make-error@^1.1.1: + version "1.3.6" + resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" + integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== + +makeerror@1.0.12: + version "1.0.12" + resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.12.tgz#3e5dd2079a82e812e983cc6610c4a2cb0eaa801a" + integrity sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg== + dependencies: + tmpl "1.0.5" + +marked-terminal@^7.1.0: + version "7.2.1" + resolved "https://registry.yarnpkg.com/marked-terminal/-/marked-terminal-7.2.1.tgz#9c1ae073a245a03c6a13e3eeac6f586f29856068" + integrity sha512-rQ1MoMFXZICWNsKMiiHwP/Z+92PLKskTPXj+e7uwXmuMPkNn7iTqC+IvDekVm1MPeC9wYQeLxeFaOvudRR/XbQ== + dependencies: + ansi-escapes "^7.0.0" + ansi-regex "^6.1.0" + chalk "^5.3.0" + cli-highlight "^2.1.11" + cli-table3 "^0.6.5" + node-emoji "^2.1.3" + supports-hyperlinks "^3.1.0" + +marked@^9.1.2: + version "9.1.6" + resolved "https://registry.yarnpkg.com/marked/-/marked-9.1.6.tgz#5d2a3f8180abfbc5d62e3258a38a1c19c0381695" + integrity sha512-jcByLnIFkd5gSXZmjNvS1TlmRhCXZjIzHYlaGkPlLIekG55JDR2Z4va9tZwCiP+/RDERiNhMOFu01xd6O5ct1Q== + +merge-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" + integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== + +merge2@^1.3.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== + +micromatch@^4.0.4: + version "4.0.8" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202" + integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA== + dependencies: + braces "^3.0.3" + picomatch "^2.3.1" + +mimic-fn@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" + integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== + +minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== + dependencies: + brace-expansion "^1.1.7" + +minimatch@^5.0.1: + version "5.1.6" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96" + integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g== + dependencies: + brace-expansion "^2.0.1" + +minimatch@^9.0.4: + version "9.0.5" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.5.tgz#d74f9dd6b57d83d8e98cfb82133b03978bc929e5" + integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow== + dependencies: + brace-expansion "^2.0.1" + +minimist@^1.2.6: + version "1.2.6" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44" + integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== + +mri@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/mri/-/mri-1.2.0.tgz#6721480fec2a11a4889861115a48b6cbe7cc8f0b" + integrity sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA== + +ms@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +ms@^2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +mz@^2.4.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32" + integrity sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q== + dependencies: + any-promise "^1.0.0" + object-assign "^4.0.1" + thenify-all "^1.0.0" + +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== + +node-emoji@^2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/node-emoji/-/node-emoji-2.1.3.tgz#93cfabb5cc7c3653aa52f29d6ffb7927d8047c06" + integrity sha512-E2WEOVsgs7O16zsURJ/eH8BqhF029wGpEOnv7Urwdo2wmQanOACwJQh0devF9D9RhoZru0+9JXIS0dBXIAz+lA== + dependencies: + "@sindresorhus/is" "^4.6.0" + char-regex "^1.0.2" + emojilib "^2.4.0" + skin-tone "^2.0.0" + +node-int64@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" + integrity sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw== + +node-releases@^2.0.14: + version "2.0.14" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.14.tgz#2ffb053bceb8b2be8495ece1ab6ce600c4461b0b" + integrity sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw== + +normalize-path@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +npm-bundled@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-2.0.1.tgz#94113f7eb342cd7a67de1e789f896b04d2c600f4" + integrity sha512-gZLxXdjEzE/+mOstGDqR6b0EkhJ+kM6fxM6vUuckuctuVPh80Q6pw/rSZj9s4Gex9GxWtIicO1pc8DB9KZWudw== + dependencies: + npm-normalize-package-bin "^2.0.0" + +npm-normalize-package-bin@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/npm-normalize-package-bin/-/npm-normalize-package-bin-2.0.0.tgz#9447a1adaaf89d8ad0abe24c6c84ad614a675fff" + integrity sha512-awzfKUO7v0FscrSpRoogyNm0sajikhBWpU0QMrW09AMi9n1PoKU6WaIqUzuJSQnpciZZmJ/jMZ2Egfmb/9LiWQ== + +npm-packlist@^5.1.3: + version "5.1.3" + resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-5.1.3.tgz#69d253e6fd664b9058b85005905012e00e69274b" + integrity sha512-263/0NGrn32YFYi4J533qzrQ/krmmrWwhKkzwTuM4f/07ug51odoaNjUexxO4vxlzURHcmYMH1QjvHjsNDKLVg== + dependencies: + glob "^8.0.1" + ignore-walk "^5.0.1" + npm-bundled "^2.0.0" + npm-normalize-package-bin "^2.0.0" + +npm-run-path@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" + integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== + dependencies: + path-key "^3.0.0" + +object-assign@^4.0.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== + +once@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== + dependencies: + wrappy "1" + +onetime@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" + integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== + dependencies: + mimic-fn "^2.1.0" + +optionator@^0.9.3: + version "0.9.3" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.3.tgz#007397d44ed1872fdc6ed31360190f81814e2c64" + integrity sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg== + dependencies: + "@aashutoshrathi/word-wrap" "^1.2.3" + deep-is "^0.1.3" + fast-levenshtein "^2.0.6" + levn "^0.4.1" + prelude-ls "^1.2.1" + type-check "^0.4.0" + +p-all@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/p-all/-/p-all-3.0.0.tgz#077c023c37e75e760193badab2bad3ccd5782bfb" + integrity sha512-qUZbvbBFVXm6uJ7U/WDiO0fv6waBMbjlCm4E66oZdRR+egswICarIdHyVSZZHudH8T5SF8x/JG0q0duFzPnlBw== + dependencies: + p-map "^4.0.0" + +p-limit@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== + dependencies: + p-try "^2.0.0" + +p-limit@^3.0.2, p-limit@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + dependencies: + yocto-queue "^0.1.0" + +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== + dependencies: + p-limit "^2.2.0" + +p-locate@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" + integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== + dependencies: + p-limit "^3.0.2" + +p-map@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b" + integrity sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ== + dependencies: + aggregate-error "^3.0.0" + +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== + +parent-module@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" + integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== + dependencies: + callsites "^3.0.0" + +parse-json@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" + integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== + dependencies: + "@babel/code-frame" "^7.0.0" + error-ex "^1.3.1" + json-parse-even-better-errors "^2.3.0" + lines-and-columns "^1.1.6" + +parse5-htmlparser2-tree-adapter@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz#2cdf9ad823321140370d4dbf5d3e92c7c8ddc6e6" + integrity sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA== + dependencies: + parse5 "^6.0.1" + +parse5@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/parse5/-/parse5-5.1.1.tgz#f68e4e5ba1852ac2cadc00f4555fff6c2abb6178" + integrity sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug== + +parse5@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b" + integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw== + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== + +path-key@^3.0.0, path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +path-parse@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + +picocolors@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" + integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== + +picocolors@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" + integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== + +picomatch@^2.0.4, picomatch@^2.2.3, picomatch@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +pirates@^4.0.4: + version "4.0.6" + resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.6.tgz#3018ae32ecfcff6c29ba2267cbf21166ac1f36b9" + integrity sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg== + +pkg-dir@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" + integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== + dependencies: + find-up "^4.0.0" + +prelude-ls@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" + integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== + +prettier-linter-helpers@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" + integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w== + dependencies: + fast-diff "^1.1.2" + +prettier@^3.0.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.1.1.tgz#6ba9f23165d690b6cbdaa88cb0807278f7019848" + integrity sha512-22UbSzg8luF4UuZtzgiUOfcGM8s4tjBv6dJRT7j275NXsy2jb4aJa4NNveul5x4eqlF1wuhuR2RElK71RvmVaw== + +pretty-format@^29.0.0, pretty-format@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.7.0.tgz#ca42c758310f365bfa71a0bda0a807160b776812" + integrity sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ== + dependencies: + "@jest/schemas" "^29.6.3" + ansi-styles "^5.0.0" + react-is "^18.0.0" + +prompts@^2.0.1: + version "2.4.2" + resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069" + integrity sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q== + dependencies: + kleur "^3.0.3" + sisteransi "^1.0.5" + +publint@^0.2.12: + version "0.2.12" + resolved "https://registry.yarnpkg.com/publint/-/publint-0.2.12.tgz#d25cd6bd243d5bdd640344ecdddb3eeafdcc4059" + integrity sha512-YNeUtCVeM4j9nDiTT2OPczmlyzOkIXNtdDZnSuajAxS/nZ6j3t7Vs9SUB4euQNddiltIwu7Tdd3s+hr08fAsMw== + dependencies: + npm-packlist "^5.1.3" + picocolors "^1.1.1" + sade "^1.8.1" + +punycode@^2.1.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f" + integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA== + +pure-rand@^6.0.0: + version "6.0.4" + resolved "https://registry.yarnpkg.com/pure-rand/-/pure-rand-6.0.4.tgz#50b737f6a925468679bff00ad20eade53f37d5c7" + integrity sha512-LA0Y9kxMYv47GIPJy6MI84fqTd2HmYZI83W/kM/SkKfDlajnZYfmXFTxkbY+xSBPkLJxltMa9hIkmdc29eguMA== + +queue-microtask@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" + integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== + +react-is@^18.0.0: + version "18.2.0" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b" + integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w== + +readable-stream@^3.4.0: + version "3.6.2" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" + integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== + +resolve-cwd@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" + integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg== + dependencies: + resolve-from "^5.0.0" + +resolve-from@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== + +resolve-from@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" + integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== + +resolve.exports@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-2.0.2.tgz#f8c934b8e6a13f539e38b7098e2e36134f01e800" + integrity sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg== + +resolve@^1.20.0: + version "1.22.8" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" + integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== + dependencies: + is-core-module "^2.13.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + +reusify@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" + integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + +run-parallel@^1.1.9: + version "1.2.0" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" + integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== + dependencies: + queue-microtask "^1.2.2" + +sade@^1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/sade/-/sade-1.8.1.tgz#0a78e81d658d394887be57d2a409bf703a3b2701" + integrity sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A== + dependencies: + mri "^1.1.0" + +safe-buffer@~5.2.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +"safer-buffer@>= 2.1.2 < 3.0.0": + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +semver@^6.3.0, semver@^6.3.1: + version "6.3.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" + integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== + +semver@^7.5.3: + version "7.5.4" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" + integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== + dependencies: + lru-cache "^6.0.0" + +semver@^7.5.4: + version "7.6.3" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143" + integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A== + +semver@^7.6.0: + version "7.7.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.1.tgz#abd5098d82b18c6c81f6074ff2647fd3e7220c9f" + integrity sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA== + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +signal-exit@^3.0.3, signal-exit@^3.0.7: + version "3.0.7" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== + +sisteransi@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" + integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== + +skin-tone@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/skin-tone/-/skin-tone-2.0.0.tgz#4e3933ab45c0d4f4f781745d64b9f4c208e41237" + integrity sha512-kUMbT1oBJCpgrnKoSr0o6wPtvRWT9W9UKvGLwfJYO2WuahZRHOpEyL1ckyMGgMWh0UdpmaoFqKKD29WTomNEGA== + dependencies: + unicode-emoji-modifier-base "^1.0.0" + +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" + integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== + +source-map-support@0.5.13: + version "0.5.13" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932" + integrity sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map@^0.6.0, source-map@^0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== + +stack-utils@^2.0.3: + version "2.0.6" + resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.6.tgz#aaf0748169c02fc33c8232abccf933f54a1cc34f" + integrity sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ== + dependencies: + escape-string-regexp "^2.0.0" + +string-length@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a" + integrity sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ== + dependencies: + char-regex "^1.0.2" + strip-ansi "^6.0.0" + +string-to-stream@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/string-to-stream/-/string-to-stream-3.0.1.tgz#480e6fb4d5476d31cb2221f75307a5dcb6638a42" + integrity sha512-Hl092MV3USJuUCC6mfl9sPzGloA3K5VwdIeJjYIkXY/8K+mUvaeEabWJgArp+xXrsWxCajeT2pc4axbVhIZJyg== + dependencies: + readable-stream "^3.4.0" + +string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-bom@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" + integrity sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA== + +strip-bom@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878" + integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w== + +strip-final-newline@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" + integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== + +strip-json-comments@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + +superstruct@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/superstruct/-/superstruct-1.0.4.tgz#0adb99a7578bd2f1c526220da6571b2d485d91ca" + integrity sha512-7JpaAoX2NGyoFlI9NBh66BQXGONc+uE+MRS5i2iOBKuS4e+ccgMDjATgZldkah+33DakBxDHiss9kvUcGAO8UQ== + +supports-color@^5.3.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + +supports-color@^7.0.0, supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +supports-color@^8.0.0: + version "8.1.1" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== + dependencies: + has-flag "^4.0.0" + +supports-hyperlinks@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/supports-hyperlinks/-/supports-hyperlinks-3.1.0.tgz#b56150ff0173baacc15f21956450b61f2b18d3ac" + integrity sha512-2rn0BZ+/f7puLOHZm1HOJfwBggfaHXUpPUSSG/SWM4TWp5KCfmNYwnC3hruy2rZlMnmWZ+QAGpZfchu3f3695A== + dependencies: + has-flag "^4.0.0" + supports-color "^7.0.0" + +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== + +synckit@0.8.8, synckit@^0.9.1: + version "0.8.8" + resolved "https://registry.yarnpkg.com/synckit/-/synckit-0.8.8.tgz#fe7fe446518e3d3d49f5e429f443cf08b6edfcd7" + integrity sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ== + dependencies: + "@pkgr/core" "^0.1.0" + tslib "^2.6.2" + +test-exclude@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" + integrity sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w== + dependencies: + "@istanbuljs/schema" "^0.1.2" + glob "^7.1.4" + minimatch "^3.0.4" + +thenify-all@^1.0.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/thenify-all/-/thenify-all-1.6.0.tgz#1a1918d402d8fc3f98fbf234db0bcc8cc10e9726" + integrity sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA== + dependencies: + thenify ">= 3.1.0 < 4" + +"thenify@>= 3.1.0 < 4": + version "3.3.1" + resolved "https://registry.yarnpkg.com/thenify/-/thenify-3.3.1.tgz#8932e686a4066038a016dd9e2ca46add9838a95f" + integrity sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw== + dependencies: + any-promise "^1.0.0" + +tmpl@1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" + integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw== + +to-fast-properties@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" + integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +ts-api-utils@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-2.0.1.tgz#660729385b625b939aaa58054f45c058f33f10cd" + integrity sha512-dnlgjFSVetynI8nzgJ+qF62efpglpWRk8isUEWZGWlJYySCTD6aKvbUDu+zbPeDakk3bg5H4XpitHukgfL1m9w== + +ts-jest@^29.1.0: + version "29.1.1" + resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-29.1.1.tgz#f58fe62c63caf7bfcc5cc6472082f79180f0815b" + integrity sha512-D6xjnnbP17cC85nliwGiL+tpoKN0StpgE0TeOjXQTU6MVCfsB4v7aW05CgQ/1OywGb0x/oy9hHFnN+sczTiRaA== + dependencies: + bs-logger "0.x" + fast-json-stable-stringify "2.x" + jest-util "^29.0.0" + json5 "^2.2.3" + lodash.memoize "4.x" + make-error "1.x" + semver "^7.5.3" + yargs-parser "^21.0.1" + +ts-node@^10.5.0: + version "10.7.0" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.7.0.tgz#35d503d0fab3e2baa672a0e94f4b40653c2463f5" + integrity sha512-TbIGS4xgJoX2i3do417KSaep1uRAW/Lu+WAL2doDHC0D6ummjirVOXU5/7aiZotbQ5p1Zp9tP7U6cYhA0O7M8A== + dependencies: + "@cspotcode/source-map-support" "0.7.0" + "@tsconfig/node10" "^1.0.7" + "@tsconfig/node12" "^1.0.7" + "@tsconfig/node14" "^1.0.0" + "@tsconfig/node16" "^1.0.2" + acorn "^8.4.1" + acorn-walk "^8.1.1" + arg "^4.1.0" + create-require "^1.1.0" + diff "^4.0.1" + make-error "^1.1.1" + v8-compile-cache-lib "^3.0.0" + yn "3.1.1" + +"tsc-multi@https://github.com/stainless-api/tsc-multi/releases/download/v1.1.4/tsc-multi-1.1.4.tgz": + version "1.1.4" + resolved "https://github.com/stainless-api/tsc-multi/releases/download/v1.1.4/tsc-multi-1.1.4.tgz#cbed459a9e902f5295ec3daaf1c7aa3b10427e55" + dependencies: + debug "^4.3.7" + fast-glob "^3.3.2" + get-stdin "^8.0.0" + p-all "^3.0.0" + picocolors "^1.1.1" + signal-exit "^3.0.7" + string-to-stream "^3.0.1" + superstruct "^1.0.4" + tslib "^2.8.1" + yargs "^17.7.2" + +tsconfig-paths@^4.0.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz#ef78e19039133446d244beac0fd6a1632e2d107c" + integrity sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg== + dependencies: + json5 "^2.2.2" + minimist "^1.2.6" + strip-bom "^3.0.0" + +tslib@^2.6.2: + version "2.6.2" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" + integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== + +tslib@^2.8.1: + version "2.8.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" + integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== + +type-check@^0.4.0, type-check@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" + integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== + dependencies: + prelude-ls "^1.2.1" + +type-detect@4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" + integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== + +type-fest@^0.21.3: + version "0.21.3" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" + integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== + +typescript-eslint@8.31.1: + version "8.31.1" + resolved "https://registry.yarnpkg.com/typescript-eslint/-/typescript-eslint-8.31.1.tgz#b77ab1e48ced2daab9225ff94bab54391a4af69b" + integrity sha512-j6DsEotD/fH39qKzXTQRwYYWlt7D+0HmfpOK+DVhwJOFLcdmn92hq3mBb7HlKJHbjjI/gTOqEcc9d6JfpFf/VA== + dependencies: + "@typescript-eslint/eslint-plugin" "8.31.1" + "@typescript-eslint/parser" "8.31.1" + "@typescript-eslint/utils" "8.31.1" + +typescript@5.6.1-rc: + version "5.6.1-rc" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.6.1-rc.tgz#d5e4d7d8170174fed607b74cc32aba3d77018e02" + integrity sha512-E3b2+1zEFu84jB0YQi9BORDjz9+jGbwwy1Zi3G0LUNw7a7cePUrHMRNy8aPh53nXpkFGVHSxIZo5vKTfYaFiBQ== + +typescript@5.8.3: + version "5.8.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.8.3.tgz#92f8a3e5e3cf497356f4178c34cd65a7f5e8440e" + integrity sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ== + +undici-types@~5.26.4: + version "5.26.5" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" + integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== + +undici-types@~6.19.2: + version "6.19.8" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.19.8.tgz#35111c9d1437ab83a7cdc0abae2f26d88eda0a02" + integrity sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw== + +unicode-emoji-modifier-base@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unicode-emoji-modifier-base/-/unicode-emoji-modifier-base-1.0.0.tgz#dbbd5b54ba30f287e2a8d5a249da6c0cef369459" + integrity sha512-yLSH4py7oFH3oG/9K+XWrz1pSi3dfUrWEnInbxMfArOfc1+33BlGPQtLsOYwvdMy11AwUBetYuaRxSPqgkq+8g== + +update-browserslist-db@^1.0.13: + version "1.0.13" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz#3c5e4f5c083661bd38ef64b6328c26ed6c8248c4" + integrity sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg== + dependencies: + escalade "^3.1.1" + picocolors "^1.0.0" + +uri-js@^4.2.2: + version "4.4.1" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + +util-deprecate@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== + +v8-compile-cache-lib@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.0.tgz#0582bcb1c74f3a2ee46487ceecf372e46bce53e8" + integrity sha512-mpSYqfsFvASnSn5qMiwrr4VKfumbPyONLCOPmsR3A6pTY/r0+tSaVbgPWSAIuzbk3lCTa+FForeTiO+wBQGkjA== + +v8-to-istanbul@^9.0.1: + version "9.2.0" + resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-9.2.0.tgz#2ed7644a245cddd83d4e087b9b33b3e62dfd10ad" + integrity sha512-/EH/sDgxU2eGxajKdwLCDmQ4FWq+kpi3uCmBGpw1xJtnAxEjlD8j8PEiGWpCIMIs3ciNAgH0d3TTJiUkYzyZjA== + dependencies: + "@jridgewell/trace-mapping" "^0.3.12" + "@types/istanbul-lib-coverage" "^2.0.1" + convert-source-map "^2.0.0" + +validate-npm-package-name@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/validate-npm-package-name/-/validate-npm-package-name-5.0.1.tgz#a316573e9b49f3ccd90dbb6eb52b3f06c6d604e8" + integrity sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ== + +walker@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.8.tgz#bd498db477afe573dc04185f011d3ab8a8d7653f" + integrity sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ== + dependencies: + makeerror "1.0.12" + +which@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== + +write-file-atomic@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-4.0.2.tgz#a9df01ae5b77858a027fd2e80768ee433555fcfd" + integrity sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg== + dependencies: + imurmurhash "^0.1.4" + signal-exit "^3.0.7" + +y18n@^5.0.5: + version "5.0.8" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" + integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== + +yallist@^3.0.2: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" + integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== + +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + +yargs-parser@^20.2.2: + version "20.2.9" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" + integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== + +yargs-parser@^21.0.1, yargs-parser@^21.1.1: + version "21.1.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" + integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== + +yargs@^16.0.0: + version "16.2.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" + integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== + dependencies: + cliui "^7.0.2" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.0" + y18n "^5.0.5" + yargs-parser "^20.2.2" + +yargs@^17.3.1, yargs@^17.7.2: + version "17.7.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" + integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== + dependencies: + cliui "^8.0.1" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.3" + y18n "^5.0.5" + yargs-parser "^21.1.1" + +yn@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" + integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== + +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== From b3aa24b1d0aeab9d4e74c5fec3b008f051ae5bda Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 8 May 2025 16:36:25 +0000 Subject: [PATCH 002/551] chore: update SDK settings --- .github/workflows/release-doctor.yml | 20 +++++++++ .release-please-manifest.json | 3 ++ .stats.yml | 2 +- CONTRIBUTING.md | 6 +-- README.md | 4 +- bin/check-release-environment | 18 ++++++++ package.json | 2 +- release-please-config.json | 64 ++++++++++++++++++++++++++++ src/version.ts | 2 +- 9 files changed, 113 insertions(+), 8 deletions(-) create mode 100644 .github/workflows/release-doctor.yml create mode 100644 .release-please-manifest.json create mode 100644 bin/check-release-environment create mode 100644 release-please-config.json diff --git a/.github/workflows/release-doctor.yml b/.github/workflows/release-doctor.yml new file mode 100644 index 00000000..519bd29b --- /dev/null +++ b/.github/workflows/release-doctor.yml @@ -0,0 +1,20 @@ +name: Release Doctor +on: + pull_request: + branches: + - main + workflow_dispatch: + +jobs: + release_doctor: + name: release doctor + runs-on: ubuntu-latest + if: github.repository == 'onkernel/kernel-node-sdk' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch' || startsWith(github.head_ref, 'release-please') || github.head_ref == 'next') + + steps: + - uses: actions/checkout@v4 + + - name: Check release environment + run: | + bash ./bin/check-release-environment + env: diff --git a/.release-please-manifest.json b/.release-please-manifest.json new file mode 100644 index 00000000..67dcd73f --- /dev/null +++ b/.release-please-manifest.json @@ -0,0 +1,3 @@ +{ + ".": "0.0.1-alpha.0" +} diff --git a/.stats.yml b/.stats.yml index b59ce7c7..d93970e4 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 4 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-2a9a9232d72f52fc9b2404958857a1b744762356421cf1bffb99db2c24045378.yml openapi_spec_hash: ba3c6823319d99762e7e1c6a624bc2ed -config_hash: e48b09ec26046e2b2ba98ad41ecbaf1c +config_hash: 5d8104e64e7d71c412fd8a49600ad33d diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d10d10f1..089b7029 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -42,15 +42,15 @@ If you’d like to use the repository from source, you can either install from g To install via git: ```sh -$ npm install git+ssh://git@github.com:stainless-sdks/kernel-typescript.git +$ npm install git+ssh://git@github.com:onkernel/kernel-node-sdk.git ``` Alternatively, to link a local copy of the repo: ```sh # Clone -$ git clone https://www.github.com/stainless-sdks/kernel-typescript -$ cd kernel-typescript +$ git clone https://www.github.com/onkernel/kernel-node-sdk +$ cd kernel-node-sdk # With yarn $ yarn link diff --git a/README.md b/README.md index 475e2681..b262652d 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ It is generated with [Stainless](https://www.stainless.com/). ## Installation ```sh -npm install git+ssh://git@github.com:stainless-sdks/kernel-typescript.git +npm install git+ssh://git@github.com:onkernel/kernel-node-sdk.git ``` > [!NOTE] @@ -412,7 +412,7 @@ This package generally follows [SemVer](https://semver.org/spec/v2.0.0.html) con We take backwards-compatibility seriously and work hard to ensure you can rely on a smooth upgrade experience. -We are keen for your feedback; please open an [issue](https://www.github.com/stainless-sdks/kernel-typescript/issues) with questions, bugs, or suggestions. +We are keen for your feedback; please open an [issue](https://www.github.com/onkernel/kernel-node-sdk/issues) with questions, bugs, or suggestions. ## Requirements diff --git a/bin/check-release-environment b/bin/check-release-environment new file mode 100644 index 00000000..6b43775a --- /dev/null +++ b/bin/check-release-environment @@ -0,0 +1,18 @@ +#!/usr/bin/env bash + +errors=() + +lenErrors=${#errors[@]} + +if [[ lenErrors -gt 0 ]]; then + echo -e "Found the following errors in the release environment:\n" + + for error in "${errors[@]}"; do + echo -e "- $error\n" + done + + exit 1 +fi + +echo "The environment is ready to push releases!" + diff --git a/package.json b/package.json index 51640651..8cb58617 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "types": "dist/index.d.ts", "main": "dist/index.js", "type": "commonjs", - "repository": "github:stainless-sdks/kernel-typescript", + "repository": "github:onkernel/kernel-node-sdk", "license": "Apache-2.0", "packageManager": "yarn@1.22.22", "files": [ diff --git a/release-please-config.json b/release-please-config.json new file mode 100644 index 00000000..1ebd0bde --- /dev/null +++ b/release-please-config.json @@ -0,0 +1,64 @@ +{ + "packages": { + ".": {} + }, + "$schema": "https://raw.githubusercontent.com/stainless-api/release-please/main/schemas/config.json", + "include-v-in-tag": true, + "include-component-in-tag": false, + "versioning": "prerelease", + "prerelease": true, + "bump-minor-pre-major": true, + "bump-patch-for-minor-pre-major": false, + "pull-request-header": "Automated Release PR", + "pull-request-title-pattern": "release: ${version}", + "changelog-sections": [ + { + "type": "feat", + "section": "Features" + }, + { + "type": "fix", + "section": "Bug Fixes" + }, + { + "type": "perf", + "section": "Performance Improvements" + }, + { + "type": "revert", + "section": "Reverts" + }, + { + "type": "chore", + "section": "Chores" + }, + { + "type": "docs", + "section": "Documentation" + }, + { + "type": "style", + "section": "Styles" + }, + { + "type": "refactor", + "section": "Refactors" + }, + { + "type": "test", + "section": "Tests", + "hidden": true + }, + { + "type": "build", + "section": "Build System" + }, + { + "type": "ci", + "section": "Continuous Integration", + "hidden": true + } + ], + "release-type": "node", + "extra-files": ["src/version.ts", "README.md"] +} diff --git a/src/version.ts b/src/version.ts index 55a1a527..db692bc9 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.0.1-alpha.0'; +export const VERSION = '0.0.1-alpha.0'; // x-release-please-version From 1408f18c58a6435b4ab512762628e9223c1eb29b Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 8 May 2025 16:38:36 +0000 Subject: [PATCH 003/551] chore: update SDK settings --- .github/workflows/publish-npm.yml | 32 ++++++++++++++++++++++++++++ .github/workflows/release-doctor.yml | 1 + .stats.yml | 2 +- CONTRIBUTING.md | 18 ++++++++++++++-- README.md | 27 +++++++++++------------ bin/check-release-environment | 4 ++++ eslint.config.mjs | 2 +- jest.config.ts | 4 ++-- package.json | 6 +++--- scripts/build | 6 +++--- tests/api-resources/apps.test.ts | 2 +- tests/api-resources/browser.test.ts | 2 +- tests/base64.test.ts | 2 +- tests/buildHeaders.test.ts | 2 +- tests/form.test.ts | 4 ++-- tests/index.test.ts | 6 +++--- tests/path.test.ts | 2 +- tests/stringifyQuery.test.ts | 2 +- tests/uploads.test.ts | 6 +++--- tsconfig.build.json | 4 ++-- tsconfig.json | 4 ++-- 21 files changed, 93 insertions(+), 45 deletions(-) create mode 100644 .github/workflows/publish-npm.yml diff --git a/.github/workflows/publish-npm.yml b/.github/workflows/publish-npm.yml new file mode 100644 index 00000000..45c2cfde --- /dev/null +++ b/.github/workflows/publish-npm.yml @@ -0,0 +1,32 @@ +# This workflow is triggered when a GitHub release is created. +# It can also be run manually to re-publish to NPM in case it failed for some reason. +# You can run this workflow by navigating to https://www.github.com/onkernel/kernel-node-sdk/actions/workflows/publish-npm.yml +name: Publish NPM +on: + workflow_dispatch: + + release: + types: [published] + +jobs: + publish: + name: publish + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Set up Node + uses: actions/setup-node@v3 + with: + node-version: '20' + + - name: Install dependencies + run: | + yarn install + + - name: Publish to NPM + run: | + bash ./bin/publish-npm + env: + NPM_TOKEN: ${{ secrets.KERNEL_NPM_TOKEN || secrets.NPM_TOKEN }} diff --git a/.github/workflows/release-doctor.yml b/.github/workflows/release-doctor.yml index 519bd29b..56150c7e 100644 --- a/.github/workflows/release-doctor.yml +++ b/.github/workflows/release-doctor.yml @@ -18,3 +18,4 @@ jobs: run: | bash ./bin/check-release-environment env: + NPM_TOKEN: ${{ secrets.KERNEL_NPM_TOKEN || secrets.NPM_TOKEN }} diff --git a/.stats.yml b/.stats.yml index d93970e4..49a57d82 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 4 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-2a9a9232d72f52fc9b2404958857a1b744762356421cf1bffb99db2c24045378.yml openapi_spec_hash: ba3c6823319d99762e7e1c6a624bc2ed -config_hash: 5d8104e64e7d71c412fd8a49600ad33d +config_hash: 0961a6d918b6ba9b875508988aa408a1 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 089b7029..0b5a2c32 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -55,12 +55,12 @@ $ cd kernel-node-sdk # With yarn $ yarn link $ cd ../my-package -$ yarn link kernel +$ yarn link @kernel/sdk # With pnpm $ pnpm link --global $ cd ../my-package -$ pnpm link -—global kernel +$ pnpm link -—global @kernel/sdk ``` ## Running tests @@ -91,3 +91,17 @@ To format and fix all lint issues automatically: ```sh $ yarn fix ``` + +## Publishing and releases + +Changes made to this repository via the automated release PR pipeline should publish to npm automatically. If +the changes aren't made through the automated pipeline, you may want to make releases manually. + +### Publish with a GitHub workflow + +You can release to package managers by using [the `Publish NPM` GitHub action](https://www.github.com/onkernel/kernel-node-sdk/actions/workflows/publish-npm.yml). This requires a setup organization or repository secret to be set up. + +### Publish manually + +If you need to manually release a package, you can run the `bin/publish-npm` script with an `NPM_TOKEN` set on +the environment. diff --git a/README.md b/README.md index b262652d..d8c6bd4c 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Kernel TypeScript API Library -[![NPM version](https://img.shields.io/npm/v/kernel.svg)](https://npmjs.org/package/kernel) ![npm bundle size](https://img.shields.io/bundlephobia/minzip/kernel) +[![NPM version](https://img.shields.io/npm/v/@kernel/sdk.svg)](https://npmjs.org/package/@kernel/sdk) ![npm bundle size](https://img.shields.io/bundlephobia/minzip/@kernel/sdk) This library provides convenient access to the Kernel REST API from server-side TypeScript or JavaScript. @@ -11,19 +11,16 @@ It is generated with [Stainless](https://www.stainless.com/). ## Installation ```sh -npm install git+ssh://git@github.com:onkernel/kernel-node-sdk.git +npm install @kernel/sdk ``` -> [!NOTE] -> Once this package is [published to npm](https://app.stainless.com/docs/guides/publish), this will become: `npm install kernel` - ## Usage The full API of this library can be found in [api.md](api.md). ```js -import Kernel from 'kernel'; +import Kernel from '@kernel/sdk'; const client = new Kernel({ apiKey: process.env['KERNEL_API_KEY'], // This is the default and can be omitted @@ -48,7 +45,7 @@ This library includes TypeScript definitions for all request params and response ```ts -import Kernel from 'kernel'; +import Kernel from '@kernel/sdk'; const client = new Kernel({ apiKey: process.env['KERNEL_API_KEY'], // This is the default and can be omitted @@ -79,7 +76,7 @@ Request parameters that correspond to file uploads can be passed in many differe ```ts import fs from 'fs'; -import Kernel, { toFile } from 'kernel'; +import Kernel, { toFile } from '@kernel/sdk'; const client = new Kernel(); @@ -238,7 +235,7 @@ The log level can be configured in two ways: 2. Using the `logLevel` client option (overrides the environment variable if set) ```ts -import Kernel from 'kernel'; +import Kernel from '@kernel/sdk'; const client = new Kernel({ logLevel: 'debug', // Show all log messages @@ -266,7 +263,7 @@ When providing a custom logger, the `logLevel` option still controls which messa below the configured level will not be sent to your logger. ```ts -import Kernel from 'kernel'; +import Kernel from '@kernel/sdk'; import pino from 'pino'; const logger = pino(); @@ -336,7 +333,7 @@ globalThis.fetch = fetch; Or pass it to the client: ```ts -import Kernel from 'kernel'; +import Kernel from '@kernel/sdk'; import fetch from 'my-fetch'; const client = new Kernel({ fetch }); @@ -347,7 +344,7 @@ const client = new Kernel({ fetch }); If you want to set custom `fetch` options without overriding the `fetch` function, you can provide a `fetchOptions` object when instantiating the client or making a request. (Request-specific options override client options.) ```ts -import Kernel from 'kernel'; +import Kernel from '@kernel/sdk'; const client = new Kernel({ fetchOptions: { @@ -364,7 +361,7 @@ options to requests: **Node** [[docs](https://github.com/nodejs/undici/blob/main/docs/docs/api/ProxyAgent.md#example---proxyagent-with-fetch)] ```ts -import Kernel from 'kernel'; +import Kernel from '@kernel/sdk'; import * as undici from 'undici'; const proxyAgent = new undici.ProxyAgent('http://localhost:8888'); @@ -378,7 +375,7 @@ const client = new Kernel({ **Bun** [[docs](https://bun.sh/guides/http/proxy)] ```ts -import Kernel from 'kernel'; +import Kernel from '@kernel/sdk'; const client = new Kernel({ fetchOptions: { @@ -390,7 +387,7 @@ const client = new Kernel({ **Deno** [[docs](https://docs.deno.com/api/deno/~/Deno.createHttpClient)] ```ts -import Kernel from 'npm:kernel'; +import Kernel from 'npm:@kernel/sdk'; const httpClient = Deno.createHttpClient({ proxy: { url: 'http://localhost:8888' } }); const client = new Kernel({ diff --git a/bin/check-release-environment b/bin/check-release-environment index 6b43775a..530e8533 100644 --- a/bin/check-release-environment +++ b/bin/check-release-environment @@ -2,6 +2,10 @@ errors=() +if [ -z "${NPM_TOKEN}" ]; then + errors+=("The KERNEL_NPM_TOKEN secret has not been set. Please set it in either this repository's secrets or your organization secrets") +fi + lenErrors=${#errors[@]} if [[ lenErrors -gt 0 ]]; then diff --git a/eslint.config.mjs b/eslint.config.mjs index 0064bc53..fde34433 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -25,7 +25,7 @@ export default tseslint.config( { patterns: [ { - regex: '^kernel(/.*)?', + regex: '^@kernel/sdk(/.*)?', message: 'Use a relative import, not a package import.', }, ], diff --git a/jest.config.ts b/jest.config.ts index 5c1b4bd6..95816db3 100644 --- a/jest.config.ts +++ b/jest.config.ts @@ -7,8 +7,8 @@ const config: JestConfigWithTsJest = { '^.+\\.(t|j)sx?$': ['@swc/jest', { sourceMaps: 'inline' }], }, moduleNameMapper: { - '^kernel$': '/src/index.ts', - '^kernel/(.*)$': '/src/$1', + '^@kernel/sdk$': '/src/index.ts', + '^@kernel/sdk/(.*)$': '/src/$1', }, modulePathIgnorePatterns: [ '/ecosystem-tests/', diff --git a/package.json b/package.json index 8cb58617..78bd2622 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "kernel", + "name": "@kernel/sdk", "version": "0.0.1-alpha.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", @@ -50,8 +50,8 @@ "synckit": "0.8.8" }, "imports": { - "kernel": ".", - "kernel/*": "./src/*" + "@kernel/sdk": ".", + "@kernel/sdk/*": "./src/*" }, "exports": { ".": { diff --git a/scripts/build b/scripts/build index 4513a5f1..e76c2211 100755 --- a/scripts/build +++ b/scripts/build @@ -8,7 +8,7 @@ node scripts/utils/check-version.cjs # Build into dist and will publish the package from there, # so that src/resources/foo.ts becomes /resources/foo.js -# This way importing from `"kernel/resources/foo"` works +# This way importing from `"@kernel/sdk/resources/foo"` works # even with `"moduleResolution": "node"` rm -rf dist; mkdir dist @@ -44,8 +44,8 @@ node scripts/utils/postprocess-files.cjs # make sure that nothing crashes when we require the output CJS or # import the output ESM -(cd dist && node -e 'require("kernel")') -(cd dist && node -e 'import("kernel")' --input-type=module) +(cd dist && node -e 'require("@kernel/sdk")') +(cd dist && node -e 'import("@kernel/sdk")' --input-type=module) if [ -e ./scripts/build-deno ] then diff --git a/tests/api-resources/apps.test.ts b/tests/api-resources/apps.test.ts index 67b47bad..c327215f 100644 --- a/tests/api-resources/apps.test.ts +++ b/tests/api-resources/apps.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Kernel, { toFile } from 'kernel'; +import Kernel, { toFile } from '@kernel/sdk'; const client = new Kernel({ apiKey: 'My API Key', diff --git a/tests/api-resources/browser.test.ts b/tests/api-resources/browser.test.ts index c7f40d73..621161e9 100644 --- a/tests/api-resources/browser.test.ts +++ b/tests/api-resources/browser.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Kernel from 'kernel'; +import Kernel from '@kernel/sdk'; const client = new Kernel({ apiKey: 'My API Key', diff --git a/tests/base64.test.ts b/tests/base64.test.ts index 6a9cf51e..9b722466 100644 --- a/tests/base64.test.ts +++ b/tests/base64.test.ts @@ -1,4 +1,4 @@ -import { fromBase64, toBase64 } from 'kernel/internal/utils/base64'; +import { fromBase64, toBase64 } from '@kernel/sdk/internal/utils/base64'; describe.each(['Buffer', 'atob'])('with %s', (mode) => { let originalBuffer: BufferConstructor; diff --git a/tests/buildHeaders.test.ts b/tests/buildHeaders.test.ts index 62e52f61..ec9447af 100644 --- a/tests/buildHeaders.test.ts +++ b/tests/buildHeaders.test.ts @@ -1,5 +1,5 @@ import { inspect } from 'node:util'; -import { buildHeaders, type HeadersLike, type NullableHeaders } from 'kernel/internal/headers'; +import { buildHeaders, type HeadersLike, type NullableHeaders } from '@kernel/sdk/internal/headers'; function inspectNullableHeaders(headers: NullableHeaders) { return `NullableHeaders {${[ diff --git a/tests/form.test.ts b/tests/form.test.ts index c5e1be22..68fda151 100644 --- a/tests/form.test.ts +++ b/tests/form.test.ts @@ -1,5 +1,5 @@ -import { multipartFormRequestOptions, createForm } from 'kernel/internal/uploads'; -import { toFile } from 'kernel/core/uploads'; +import { multipartFormRequestOptions, createForm } from '@kernel/sdk/internal/uploads'; +import { toFile } from '@kernel/sdk/core/uploads'; describe('form data validation', () => { test('valid values do not error', async () => { diff --git a/tests/index.test.ts b/tests/index.test.ts index 589c1cd0..f6b78555 100644 --- a/tests/index.test.ts +++ b/tests/index.test.ts @@ -1,10 +1,10 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { APIPromise } from 'kernel/core/api-promise'; +import { APIPromise } from '@kernel/sdk/core/api-promise'; import util from 'node:util'; -import Kernel from 'kernel'; -import { APIUserAbortError } from 'kernel'; +import Kernel from '@kernel/sdk'; +import { APIUserAbortError } from '@kernel/sdk'; const defaultFetch = fetch; describe('instantiate client', () => { diff --git a/tests/path.test.ts b/tests/path.test.ts index c581f275..b48bce5e 100644 --- a/tests/path.test.ts +++ b/tests/path.test.ts @@ -1,4 +1,4 @@ -import { createPathTagFunction, encodeURIPath } from 'kernel/internal/utils/path'; +import { createPathTagFunction, encodeURIPath } from '@kernel/sdk/internal/utils/path'; import { inspect } from 'node:util'; describe('path template tag function', () => { diff --git a/tests/stringifyQuery.test.ts b/tests/stringifyQuery.test.ts index ce8b6918..05e5cc3c 100644 --- a/tests/stringifyQuery.test.ts +++ b/tests/stringifyQuery.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { Kernel } from 'kernel'; +import { Kernel } from '@kernel/sdk'; const { stringifyQuery } = Kernel.prototype as any; diff --git a/tests/uploads.test.ts b/tests/uploads.test.ts index d6fb8d31..df09f708 100644 --- a/tests/uploads.test.ts +++ b/tests/uploads.test.ts @@ -1,6 +1,6 @@ import fs from 'fs'; -import type { ResponseLike } from 'kernel/internal/to-file'; -import { toFile } from 'kernel/core/uploads'; +import type { ResponseLike } from '@kernel/sdk/internal/to-file'; +import { toFile } from '@kernel/sdk/core/uploads'; import { File } from 'node:buffer'; class MyClass { @@ -97,7 +97,7 @@ describe('missing File error message', () => { }); test('is thrown', async () => { - const uploads = await import('kernel/core/uploads'); + const uploads = await import('@kernel/sdk/core/uploads'); await expect( uploads.toFile(mockResponse({ url: 'https://example.com/my/audio.mp3' })), ).rejects.toMatchInlineSnapshot( diff --git a/tsconfig.build.json b/tsconfig.build.json index 291f7ad9..91ae5b31 100644 --- a/tsconfig.build.json +++ b/tsconfig.build.json @@ -5,8 +5,8 @@ "compilerOptions": { "rootDir": "./dist/src", "paths": { - "kernel/*": ["dist/src/*"], - "kernel": ["dist/src/index.ts"] + "@kernel/sdk/*": ["dist/src/*"], + "@kernel/sdk": ["dist/src/index.ts"] }, "noEmit": false, "declaration": true, diff --git a/tsconfig.json b/tsconfig.json index 67838cf9..fe4228aa 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -9,8 +9,8 @@ "esModuleInterop": true, "baseUrl": "./", "paths": { - "kernel/*": ["src/*"], - "kernel": ["src/index.ts"] + "@kernel/sdk/*": ["src/*"], + "@kernel/sdk": ["src/index.ts"] }, "noEmit": true, From b2c08fa1e6fcb362f33723586010abc917569122 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 8 May 2025 16:44:36 +0000 Subject: [PATCH 004/551] feat(api): update via SDK Studio --- .stats.yml | 6 +++--- CONTRIBUTING.md | 4 ++-- README.md | 24 ++++++++++++------------ eslint.config.mjs | 2 +- jest.config.ts | 4 ++-- package.json | 6 +++--- scripts/build | 6 +++--- tests/api-resources/apps.test.ts | 2 +- tests/api-resources/browser.test.ts | 2 +- tests/base64.test.ts | 2 +- tests/buildHeaders.test.ts | 2 +- tests/form.test.ts | 4 ++-- tests/index.test.ts | 6 +++--- tests/path.test.ts | 2 +- tests/stringifyQuery.test.ts | 2 +- tests/uploads.test.ts | 6 +++--- tsconfig.build.json | 4 ++-- tsconfig.json | 4 ++-- 18 files changed, 44 insertions(+), 44 deletions(-) diff --git a/.stats.yml b/.stats.yml index 49a57d82..b66a1bc8 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 4 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-2a9a9232d72f52fc9b2404958857a1b744762356421cf1bffb99db2c24045378.yml -openapi_spec_hash: ba3c6823319d99762e7e1c6a624bc2ed -config_hash: 0961a6d918b6ba9b875508988aa408a1 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-e642528081bcfbb78b52900cb9b8b1407a9c7a8653c57ab021a79d4d52585695.yml +openapi_spec_hash: 8d91d1ac100906977531a93b9f4ae380 +config_hash: 49c38455e0bcb05feb11399f9da1fb4f diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0b5a2c32..679eb772 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -55,12 +55,12 @@ $ cd kernel-node-sdk # With yarn $ yarn link $ cd ../my-package -$ yarn link @kernel/sdk +$ yarn link @onkernel/sdk # With pnpm $ pnpm link --global $ cd ../my-package -$ pnpm link -—global @kernel/sdk +$ pnpm link -—global @onkernel/sdk ``` ## Running tests diff --git a/README.md b/README.md index d8c6bd4c..9c777685 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Kernel TypeScript API Library -[![NPM version](https://img.shields.io/npm/v/@kernel/sdk.svg)](https://npmjs.org/package/@kernel/sdk) ![npm bundle size](https://img.shields.io/bundlephobia/minzip/@kernel/sdk) +[![NPM version](https://img.shields.io/npm/v/@onkernel/sdk.svg)](https://npmjs.org/package/@onkernel/sdk) ![npm bundle size](https://img.shields.io/bundlephobia/minzip/@onkernel/sdk) This library provides convenient access to the Kernel REST API from server-side TypeScript or JavaScript. @@ -11,7 +11,7 @@ It is generated with [Stainless](https://www.stainless.com/). ## Installation ```sh -npm install @kernel/sdk +npm install @onkernel/sdk ``` ## Usage @@ -20,7 +20,7 @@ The full API of this library can be found in [api.md](api.md). ```js -import Kernel from '@kernel/sdk'; +import Kernel from '@onkernel/sdk'; const client = new Kernel({ apiKey: process.env['KERNEL_API_KEY'], // This is the default and can be omitted @@ -45,7 +45,7 @@ This library includes TypeScript definitions for all request params and response ```ts -import Kernel from '@kernel/sdk'; +import Kernel from '@onkernel/sdk'; const client = new Kernel({ apiKey: process.env['KERNEL_API_KEY'], // This is the default and can be omitted @@ -76,7 +76,7 @@ Request parameters that correspond to file uploads can be passed in many differe ```ts import fs from 'fs'; -import Kernel, { toFile } from '@kernel/sdk'; +import Kernel, { toFile } from '@onkernel/sdk'; const client = new Kernel(); @@ -235,7 +235,7 @@ The log level can be configured in two ways: 2. Using the `logLevel` client option (overrides the environment variable if set) ```ts -import Kernel from '@kernel/sdk'; +import Kernel from '@onkernel/sdk'; const client = new Kernel({ logLevel: 'debug', // Show all log messages @@ -263,7 +263,7 @@ When providing a custom logger, the `logLevel` option still controls which messa below the configured level will not be sent to your logger. ```ts -import Kernel from '@kernel/sdk'; +import Kernel from '@onkernel/sdk'; import pino from 'pino'; const logger = pino(); @@ -333,7 +333,7 @@ globalThis.fetch = fetch; Or pass it to the client: ```ts -import Kernel from '@kernel/sdk'; +import Kernel from '@onkernel/sdk'; import fetch from 'my-fetch'; const client = new Kernel({ fetch }); @@ -344,7 +344,7 @@ const client = new Kernel({ fetch }); If you want to set custom `fetch` options without overriding the `fetch` function, you can provide a `fetchOptions` object when instantiating the client or making a request. (Request-specific options override client options.) ```ts -import Kernel from '@kernel/sdk'; +import Kernel from '@onkernel/sdk'; const client = new Kernel({ fetchOptions: { @@ -361,7 +361,7 @@ options to requests: **Node** [[docs](https://github.com/nodejs/undici/blob/main/docs/docs/api/ProxyAgent.md#example---proxyagent-with-fetch)] ```ts -import Kernel from '@kernel/sdk'; +import Kernel from '@onkernel/sdk'; import * as undici from 'undici'; const proxyAgent = new undici.ProxyAgent('http://localhost:8888'); @@ -375,7 +375,7 @@ const client = new Kernel({ **Bun** [[docs](https://bun.sh/guides/http/proxy)] ```ts -import Kernel from '@kernel/sdk'; +import Kernel from '@onkernel/sdk'; const client = new Kernel({ fetchOptions: { @@ -387,7 +387,7 @@ const client = new Kernel({ **Deno** [[docs](https://docs.deno.com/api/deno/~/Deno.createHttpClient)] ```ts -import Kernel from 'npm:@kernel/sdk'; +import Kernel from 'npm:@onkernel/sdk'; const httpClient = Deno.createHttpClient({ proxy: { url: 'http://localhost:8888' } }); const client = new Kernel({ diff --git a/eslint.config.mjs b/eslint.config.mjs index fde34433..4d61d875 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -25,7 +25,7 @@ export default tseslint.config( { patterns: [ { - regex: '^@kernel/sdk(/.*)?', + regex: '^@onkernel/sdk(/.*)?', message: 'Use a relative import, not a package import.', }, ], diff --git a/jest.config.ts b/jest.config.ts index 95816db3..a3ef35c7 100644 --- a/jest.config.ts +++ b/jest.config.ts @@ -7,8 +7,8 @@ const config: JestConfigWithTsJest = { '^.+\\.(t|j)sx?$': ['@swc/jest', { sourceMaps: 'inline' }], }, moduleNameMapper: { - '^@kernel/sdk$': '/src/index.ts', - '^@kernel/sdk/(.*)$': '/src/$1', + '^@onkernel/sdk$': '/src/index.ts', + '^@onkernel/sdk/(.*)$': '/src/$1', }, modulePathIgnorePatterns: [ '/ecosystem-tests/', diff --git a/package.json b/package.json index 78bd2622..74a8d967 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "@kernel/sdk", + "name": "@onkernel/sdk", "version": "0.0.1-alpha.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", @@ -50,8 +50,8 @@ "synckit": "0.8.8" }, "imports": { - "@kernel/sdk": ".", - "@kernel/sdk/*": "./src/*" + "@onkernel/sdk": ".", + "@onkernel/sdk/*": "./src/*" }, "exports": { ".": { diff --git a/scripts/build b/scripts/build index e76c2211..6a52f04a 100755 --- a/scripts/build +++ b/scripts/build @@ -8,7 +8,7 @@ node scripts/utils/check-version.cjs # Build into dist and will publish the package from there, # so that src/resources/foo.ts becomes /resources/foo.js -# This way importing from `"@kernel/sdk/resources/foo"` works +# This way importing from `"@onkernel/sdk/resources/foo"` works # even with `"moduleResolution": "node"` rm -rf dist; mkdir dist @@ -44,8 +44,8 @@ node scripts/utils/postprocess-files.cjs # make sure that nothing crashes when we require the output CJS or # import the output ESM -(cd dist && node -e 'require("@kernel/sdk")') -(cd dist && node -e 'import("@kernel/sdk")' --input-type=module) +(cd dist && node -e 'require("@onkernel/sdk")') +(cd dist && node -e 'import("@onkernel/sdk")' --input-type=module) if [ -e ./scripts/build-deno ] then diff --git a/tests/api-resources/apps.test.ts b/tests/api-resources/apps.test.ts index c327215f..614eb1e9 100644 --- a/tests/api-resources/apps.test.ts +++ b/tests/api-resources/apps.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Kernel, { toFile } from '@kernel/sdk'; +import Kernel, { toFile } from '@onkernel/sdk'; const client = new Kernel({ apiKey: 'My API Key', diff --git a/tests/api-resources/browser.test.ts b/tests/api-resources/browser.test.ts index 621161e9..6782448f 100644 --- a/tests/api-resources/browser.test.ts +++ b/tests/api-resources/browser.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Kernel from '@kernel/sdk'; +import Kernel from '@onkernel/sdk'; const client = new Kernel({ apiKey: 'My API Key', diff --git a/tests/base64.test.ts b/tests/base64.test.ts index 9b722466..2e2538eb 100644 --- a/tests/base64.test.ts +++ b/tests/base64.test.ts @@ -1,4 +1,4 @@ -import { fromBase64, toBase64 } from '@kernel/sdk/internal/utils/base64'; +import { fromBase64, toBase64 } from '@onkernel/sdk/internal/utils/base64'; describe.each(['Buffer', 'atob'])('with %s', (mode) => { let originalBuffer: BufferConstructor; diff --git a/tests/buildHeaders.test.ts b/tests/buildHeaders.test.ts index ec9447af..039a8008 100644 --- a/tests/buildHeaders.test.ts +++ b/tests/buildHeaders.test.ts @@ -1,5 +1,5 @@ import { inspect } from 'node:util'; -import { buildHeaders, type HeadersLike, type NullableHeaders } from '@kernel/sdk/internal/headers'; +import { buildHeaders, type HeadersLike, type NullableHeaders } from '@onkernel/sdk/internal/headers'; function inspectNullableHeaders(headers: NullableHeaders) { return `NullableHeaders {${[ diff --git a/tests/form.test.ts b/tests/form.test.ts index 68fda151..56981ca7 100644 --- a/tests/form.test.ts +++ b/tests/form.test.ts @@ -1,5 +1,5 @@ -import { multipartFormRequestOptions, createForm } from '@kernel/sdk/internal/uploads'; -import { toFile } from '@kernel/sdk/core/uploads'; +import { multipartFormRequestOptions, createForm } from '@onkernel/sdk/internal/uploads'; +import { toFile } from '@onkernel/sdk/core/uploads'; describe('form data validation', () => { test('valid values do not error', async () => { diff --git a/tests/index.test.ts b/tests/index.test.ts index f6b78555..3e6bf889 100644 --- a/tests/index.test.ts +++ b/tests/index.test.ts @@ -1,10 +1,10 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { APIPromise } from '@kernel/sdk/core/api-promise'; +import { APIPromise } from '@onkernel/sdk/core/api-promise'; import util from 'node:util'; -import Kernel from '@kernel/sdk'; -import { APIUserAbortError } from '@kernel/sdk'; +import Kernel from '@onkernel/sdk'; +import { APIUserAbortError } from '@onkernel/sdk'; const defaultFetch = fetch; describe('instantiate client', () => { diff --git a/tests/path.test.ts b/tests/path.test.ts index b48bce5e..6d7177f4 100644 --- a/tests/path.test.ts +++ b/tests/path.test.ts @@ -1,4 +1,4 @@ -import { createPathTagFunction, encodeURIPath } from '@kernel/sdk/internal/utils/path'; +import { createPathTagFunction, encodeURIPath } from '@onkernel/sdk/internal/utils/path'; import { inspect } from 'node:util'; describe('path template tag function', () => { diff --git a/tests/stringifyQuery.test.ts b/tests/stringifyQuery.test.ts index 05e5cc3c..1170f010 100644 --- a/tests/stringifyQuery.test.ts +++ b/tests/stringifyQuery.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { Kernel } from '@kernel/sdk'; +import { Kernel } from '@onkernel/sdk'; const { stringifyQuery } = Kernel.prototype as any; diff --git a/tests/uploads.test.ts b/tests/uploads.test.ts index df09f708..ba84b0c1 100644 --- a/tests/uploads.test.ts +++ b/tests/uploads.test.ts @@ -1,6 +1,6 @@ import fs from 'fs'; -import type { ResponseLike } from '@kernel/sdk/internal/to-file'; -import { toFile } from '@kernel/sdk/core/uploads'; +import type { ResponseLike } from '@onkernel/sdk/internal/to-file'; +import { toFile } from '@onkernel/sdk/core/uploads'; import { File } from 'node:buffer'; class MyClass { @@ -97,7 +97,7 @@ describe('missing File error message', () => { }); test('is thrown', async () => { - const uploads = await import('@kernel/sdk/core/uploads'); + const uploads = await import('@onkernel/sdk/core/uploads'); await expect( uploads.toFile(mockResponse({ url: 'https://example.com/my/audio.mp3' })), ).rejects.toMatchInlineSnapshot( diff --git a/tsconfig.build.json b/tsconfig.build.json index 91ae5b31..7a7d5e09 100644 --- a/tsconfig.build.json +++ b/tsconfig.build.json @@ -5,8 +5,8 @@ "compilerOptions": { "rootDir": "./dist/src", "paths": { - "@kernel/sdk/*": ["dist/src/*"], - "@kernel/sdk": ["dist/src/index.ts"] + "@onkernel/sdk/*": ["dist/src/*"], + "@onkernel/sdk": ["dist/src/index.ts"] }, "noEmit": false, "declaration": true, diff --git a/tsconfig.json b/tsconfig.json index fe4228aa..ffa29592 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -9,8 +9,8 @@ "esModuleInterop": true, "baseUrl": "./", "paths": { - "@kernel/sdk/*": ["src/*"], - "@kernel/sdk": ["src/index.ts"] + "@onkernel/sdk/*": ["src/*"], + "@onkernel/sdk": ["src/index.ts"] }, "noEmit": true, From ae6f02133ee27d69ddb40c1f97b76bd0e402e44e Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 8 May 2025 16:47:46 +0000 Subject: [PATCH 005/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 67dcd73f..d7a87356 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.0.1-alpha.0" + ".": "0.1.0-alpha.1" } diff --git a/package.json b/package.json index 74a8d967..054352c9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.0.1-alpha.0", + "version": "0.1.0-alpha.1", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index db692bc9..b0bfd9e7 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.0.1-alpha.0'; // x-release-please-version +export const VERSION = '0.1.0-alpha.1'; // x-release-please-version From 006eae1c39116ef6f6743f3c69cc905a87a52b13 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 8 May 2025 16:50:59 +0000 Subject: [PATCH 006/551] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index b66a1bc8..25b168b7 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 4 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-e642528081bcfbb78b52900cb9b8b1407a9c7a8653c57ab021a79d4d52585695.yml openapi_spec_hash: 8d91d1ac100906977531a93b9f4ae380 -config_hash: 49c38455e0bcb05feb11399f9da1fb4f +config_hash: 75c0b894355904e2a91b70445072d4b4 From 2031d6300d9c2c5e95188a13ecfbf441a8cecc9c Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 9 May 2025 15:39:32 +0000 Subject: [PATCH 007/551] feat(api): update via SDK Studio --- .stats.yml | 4 ++-- src/resources/apps.ts | 13 ++++++++++++- tests/api-resources/apps.test.ts | 2 ++ 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/.stats.yml b/.stats.yml index 25b168b7..f654ed7c 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 4 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-e642528081bcfbb78b52900cb9b8b1407a9c7a8653c57ab021a79d4d52585695.yml -openapi_spec_hash: 8d91d1ac100906977531a93b9f4ae380 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-d168b58fcf39dbd0458d132091793d3e2d0930070b7dda2d5f7f1baff20dd31b.yml +openapi_spec_hash: b7e0fd7ee1656d7dbad57209d1584d92 config_hash: 75c0b894355904e2a91b70445072d4b4 diff --git a/src/resources/apps.ts b/src/resources/apps.ts index c2e4a953..e8feb85b 100644 --- a/src/resources/apps.ts +++ b/src/resources/apps.ts @@ -30,6 +30,7 @@ export class Apps extends APIResource { * @example * ```ts * const response = await client.apps.invoke({ + * actionName: 'analyze', * appName: 'my-awesome-app', * payload: '{ "data": "example input" }', * version: '1.0.0', @@ -81,7 +82,12 @@ export interface AppInvokeResponse { /** * Status of the invocation */ - status: string; + status: 'QUEUED' | 'RUNNING' | 'SUCCEEDED' | 'FAILED'; + + /** + * Output from the invocation (if available) + */ + output?: string; } export interface AppRetrieveInvocationResponse { @@ -123,6 +129,11 @@ export interface AppDeployParams { } export interface AppInvokeParams { + /** + * Name of the action to invoke + */ + actionName: string; + /** * Name of the application */ diff --git a/tests/api-resources/apps.test.ts b/tests/api-resources/apps.test.ts index 614eb1e9..cec0d2b1 100644 --- a/tests/api-resources/apps.test.ts +++ b/tests/api-resources/apps.test.ts @@ -37,6 +37,7 @@ describe('resource apps', () => { // skipped: tests are disabled for the time being test.skip('invoke: only required params', async () => { const responsePromise = client.apps.invoke({ + actionName: 'analyze', appName: 'my-awesome-app', payload: '{ "data": "example input" }', version: '1.0.0', @@ -53,6 +54,7 @@ describe('resource apps', () => { // skipped: tests are disabled for the time being test.skip('invoke: required and optional params', async () => { const response = await client.apps.invoke({ + actionName: 'analyze', appName: 'my-awesome-app', payload: '{ "data": "example input" }', version: '1.0.0', From c0a521a01c9b03b160e5b67480a702c954bbf261 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 9 May 2025 15:43:08 +0000 Subject: [PATCH 008/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index d7a87356..c5e8a3ed 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.1.0-alpha.1" + ".": "0.1.0-alpha.2" } diff --git a/package.json b/package.json index 054352c9..fef74970 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.1.0-alpha.1", + "version": "0.1.0-alpha.2", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index b0bfd9e7..a528f635 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.1.0-alpha.1'; // x-release-please-version +export const VERSION = '0.1.0-alpha.2'; // x-release-please-version From 89afe168c482ca0a2034c6ca5aec38dc81c19419 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 10 May 2025 02:54:22 +0000 Subject: [PATCH 009/551] chore(internal): codegen related update --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index c5e8a3ed..b3b5e583 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.1.0-alpha.2" + ".": "0.1.0-alpha.4" } diff --git a/package.json b/package.json index fef74970..bcd28e4f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.1.0-alpha.2", + "version": "0.1.0-alpha.4", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index a528f635..fe6d1df9 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.1.0-alpha.2'; // x-release-please-version +export const VERSION = '0.1.0-alpha.4'; // x-release-please-version From fd11a43476cb8c25d2c83fc43c08a09d5e0b2f2b Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 10 May 2025 02:59:43 +0000 Subject: [PATCH 010/551] fix(client): always overwrite when merging headers --- src/internal/headers.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/internal/headers.ts b/src/internal/headers.ts index 8659ddea..5cc03ce3 100644 --- a/src/internal/headers.ts +++ b/src/internal/headers.ts @@ -71,8 +71,8 @@ function* iterateHeaders(headers: HeadersLike): IterableIterator { const targetHeaders = new Headers(); const nullHeaders = new Set(); - const seenHeaders = new Set(); for (const headers of newHeaders) { + const seenHeaders = new Set(); for (const [name, value] of iterateHeaders(headers)) { const lowerName = name.toLowerCase(); if (!seenHeaders.has(lowerName)) { From 7b7a9d82acc08cb587cd6fe2943f7d77b600cd3b Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 10 May 2025 19:03:30 +0000 Subject: [PATCH 011/551] feat(api): update via SDK Studio --- .stats.yml | 2 +- README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index f654ed7c..3b0a5f22 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 4 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-d168b58fcf39dbd0458d132091793d3e2d0930070b7dda2d5f7f1baff20dd31b.yml openapi_spec_hash: b7e0fd7ee1656d7dbad57209d1584d92 -config_hash: 75c0b894355904e2a91b70445072d4b4 +config_hash: c2bc5253d8afd6d67e031f73353c9b22 diff --git a/README.md b/README.md index 9c777685..d8e06f72 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ This library provides convenient access to the Kernel REST API from server-side TypeScript or JavaScript. -The full API of this library can be found in [api.md](api.md). +The REST API documentation can be found on [docs.onkernel.com](https://docs.onkernel.com). The full API of this library can be found in [api.md](api.md). It is generated with [Stainless](https://www.stainless.com/). From 16d37b33a6d7acc9769db553af877773abd1a039 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 10 May 2025 19:20:34 +0000 Subject: [PATCH 012/551] feat(api): update via SDK Studio --- .release-please-manifest.json | 2 +- .stats.yml | 2 +- README.md | 2 ++ package.json | 2 +- src/client.ts | 32 ++++++++++++++++++++++++++++---- src/version.ts | 2 +- tests/index.test.ts | 17 +++++++++++++++-- 7 files changed, 49 insertions(+), 10 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index b3b5e583..12342beb 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.1.0-alpha.4" + ".": "0.1.0-alpha.5" } diff --git a/.stats.yml b/.stats.yml index 3b0a5f22..1a7891f2 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 4 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-d168b58fcf39dbd0458d132091793d3e2d0930070b7dda2d5f7f1baff20dd31b.yml openapi_spec_hash: b7e0fd7ee1656d7dbad57209d1584d92 -config_hash: c2bc5253d8afd6d67e031f73353c9b22 +config_hash: 2d282609080a6011e3f6222451f72237 diff --git a/README.md b/README.md index d8e06f72..9373ffc3 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,7 @@ import Kernel from '@onkernel/sdk'; const client = new Kernel({ apiKey: process.env['KERNEL_API_KEY'], // This is the default and can be omitted + environment: 'development', // defaults to 'production' }); async function main() { @@ -49,6 +50,7 @@ import Kernel from '@onkernel/sdk'; const client = new Kernel({ apiKey: process.env['KERNEL_API_KEY'], // This is the default and can be omitted + environment: 'development', // defaults to 'production' }); async function main() { diff --git a/package.json b/package.json index bcd28e4f..ec153c2e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.1.0-alpha.4", + "version": "0.1.0-alpha.5", "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 0e2dbad7..6d1d344d 100644 --- a/src/client.ts +++ b/src/client.ts @@ -33,12 +33,27 @@ import { readEnv } from './internal/utils/env'; import { formatRequestDetails, loggerFor } from './internal/utils/log'; import { isEmptyObj } from './internal/utils/values'; +const environments = { + production: 'https://api.onkernel.com/', + development: 'https://localhost:3001/', +}; +type Environment = keyof typeof environments; + export interface ClientOptions { /** * Defaults to process.env['KERNEL_API_KEY']. */ apiKey?: string | undefined; + /** + * Specifies the environment to use for the API. + * + * Each environment maps to a different base URL: + * - `production` corresponds to `https://api.onkernel.com/` + * - `development` corresponds to `https://localhost:3001/` + */ + environment?: Environment | undefined; + /** * Override the default base URL for the API, e.g., "https://api.example.com/v2/" * @@ -128,7 +143,8 @@ export class Kernel { * API Client for interfacing with the Kernel API. * * @param {string | undefined} [opts.apiKey=process.env['KERNEL_API_KEY'] ?? undefined] - * @param {string} [opts.baseURL=process.env['KERNEL_BASE_URL'] ?? http://localhost:3001] - Override the default base URL for the API. + * @param {Environment} [opts.environment=production] - Specifies the environment URL to use for the API. + * @param {string} [opts.baseURL=process.env['KERNEL_BASE_URL'] ?? https://api.onkernel.com/] - Override the default base URL for the API. * @param {number} [opts.timeout=1 minute] - The maximum amount of time (in milliseconds) the client will wait for a response before timing out. * @param {MergedRequestInit} [opts.fetchOptions] - Additional `RequestInit` options to be passed to `fetch` calls. * @param {Fetch} [opts.fetch] - Specify a custom `fetch` function implementation. @@ -150,10 +166,17 @@ export class Kernel { const options: ClientOptions = { apiKey, ...opts, - baseURL: baseURL || `http://localhost:3001`, + baseURL, + environment: opts.environment ?? 'production', }; - this.baseURL = options.baseURL!; + if (baseURL && opts.environment) { + throw new Errors.KernelError( + 'Ambiguous URL; The `baseURL` option (or KERNEL_BASE_URL env var) and the `environment` option are given. If you want to use the environment you must pass baseURL: null', + ); + } + + this.baseURL = options.baseURL || environments[options.environment || 'production']; this.timeout = options.timeout ?? Kernel.DEFAULT_TIMEOUT /* 1 minute */; this.logger = options.logger ?? console; const defaultLogLevel = 'warn'; @@ -179,7 +202,8 @@ export class Kernel { withOptions(options: Partial): this { return new (this.constructor as any as new (props: ClientOptions) => typeof this)({ ...this._options, - baseURL: this.baseURL, + environment: options.environment ? options.environment : undefined, + baseURL: options.environment ? undefined : this.baseURL, maxRetries: this.maxRetries, timeout: this.timeout, logger: this.logger, diff --git a/src/version.ts b/src/version.ts index fe6d1df9..66c10e67 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.1.0-alpha.4'; // x-release-please-version +export const VERSION = '0.1.0-alpha.5'; // x-release-please-version diff --git a/tests/index.test.ts b/tests/index.test.ts index 3e6bf889..b452e0f4 100644 --- a/tests/index.test.ts +++ b/tests/index.test.ts @@ -302,13 +302,26 @@ describe('instantiate client', () => { test('empty env variable', () => { process.env['KERNEL_BASE_URL'] = ''; // empty const client = new Kernel({ apiKey: 'My API Key' }); - expect(client.baseURL).toEqual('http://localhost:3001'); + expect(client.baseURL).toEqual('https://api.onkernel.com/'); }); test('blank env variable', () => { process.env['KERNEL_BASE_URL'] = ' '; // blank const client = new Kernel({ apiKey: 'My API Key' }); - expect(client.baseURL).toEqual('http://localhost:3001'); + expect(client.baseURL).toEqual('https://api.onkernel.com/'); + }); + + test('env variable with environment', () => { + process.env['KERNEL_BASE_URL'] = 'https://example.com/from_env'; + + expect( + () => new Kernel({ apiKey: 'My API Key', environment: 'production' }), + ).toThrowErrorMatchingInlineSnapshot( + `"Ambiguous URL; The \`baseURL\` option (or KERNEL_BASE_URL env var) and the \`environment\` option are given. If you want to use the environment you must pass baseURL: null"`, + ); + + const client = new Kernel({ apiKey: 'My API Key', baseURL: null, environment: 'production' }); + expect(client.baseURL).toEqual('https://api.onkernel.com/'); }); }); From 7598f3cdd2ab95d648050013de24688a5f731b18 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 10 May 2025 19:25:05 +0000 Subject: [PATCH 013/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 12342beb..5375ff4d 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.1.0-alpha.5" + ".": "0.1.0-alpha.6" } diff --git a/package.json b/package.json index ec153c2e..2f6d32a4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.1.0-alpha.5", + "version": "0.1.0-alpha.6", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 66c10e67..9b7cfeb5 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.1.0-alpha.5'; // x-release-please-version +export const VERSION = '0.1.0-alpha.6'; // x-release-please-version From 7f8bc94342b488676d95169b865524509e6db3a8 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sun, 11 May 2025 10:42:25 +0000 Subject: [PATCH 014/551] feat(api): update via SDK Studio --- .stats.yml | 4 ++-- api.md | 2 -- src/client.ts | 2 -- src/resources/apps.ts | 32 -------------------------------- src/resources/index.ts | 1 - tests/api-resources/apps.test.ts | 12 ------------ 6 files changed, 2 insertions(+), 51 deletions(-) diff --git a/.stats.yml b/.stats.yml index 1a7891f2..42510a99 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 4 +configured_endpoints: 3 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-d168b58fcf39dbd0458d132091793d3e2d0930070b7dda2d5f7f1baff20dd31b.yml openapi_spec_hash: b7e0fd7ee1656d7dbad57209d1584d92 -config_hash: 2d282609080a6011e3f6222451f72237 +config_hash: 9139d1eb064baf60fd2265aac382f097 diff --git a/api.md b/api.md index 02224e64..ed6594e7 100644 --- a/api.md +++ b/api.md @@ -4,13 +4,11 @@ Types: - AppDeployResponse - AppInvokeResponse -- AppRetrieveInvocationResponse Methods: - client.apps.deploy({ ...params }) -> AppDeployResponse - client.apps.invoke({ ...params }) -> AppInvokeResponse -- client.apps.retrieveInvocation(id) -> AppRetrieveInvocationResponse # Browser diff --git a/src/client.ts b/src/client.ts index 6d1d344d..c326bea4 100644 --- a/src/client.ts +++ b/src/client.ts @@ -25,7 +25,6 @@ import { AppDeployResponse, AppInvokeParams, AppInvokeResponse, - AppRetrieveInvocationResponse, Apps, } from './resources/apps'; import { Browser, BrowserCreateSessionResponse } from './resources/browser'; @@ -735,7 +734,6 @@ export declare namespace Kernel { Apps as Apps, type AppDeployResponse as AppDeployResponse, type AppInvokeResponse as AppInvokeResponse, - type AppRetrieveInvocationResponse as AppRetrieveInvocationResponse, type AppDeployParams as AppDeployParams, type AppInvokeParams as AppInvokeParams, }; diff --git a/src/resources/apps.ts b/src/resources/apps.ts index e8feb85b..fd601e94 100644 --- a/src/resources/apps.ts +++ b/src/resources/apps.ts @@ -5,7 +5,6 @@ import { APIPromise } from '../core/api-promise'; import { type Uploadable } from '../core/uploads'; import { RequestOptions } from '../internal/request-options'; import { multipartFormRequestOptions } from '../internal/uploads'; -import { path } from '../internal/utils/path'; export class Apps extends APIResource { /** @@ -40,20 +39,6 @@ export class Apps extends APIResource { invoke(body: AppInvokeParams, options?: RequestOptions): APIPromise { return this._client.post('/apps/invoke', { body, ...options }); } - - /** - * Get an app invocation by id - * - * @example - * ```ts - * const response = await client.apps.retrieveInvocation( - * 'ckqwer3o20000jb9s7abcdef', - * ); - * ``` - */ - retrieveInvocation(id: string, options?: RequestOptions): APIPromise { - return this._client.get(path`/apps/invocations/${id}`, options); - } } export interface AppDeployResponse { @@ -90,22 +75,6 @@ export interface AppInvokeResponse { output?: string; } -export interface AppRetrieveInvocationResponse { - id: string; - - appName: string; - - finishedAt: string | null; - - input: string; - - output: string; - - startedAt: string; - - status: string; -} - export interface AppDeployParams { /** * Name of the application @@ -154,7 +123,6 @@ export declare namespace Apps { export { type AppDeployResponse as AppDeployResponse, type AppInvokeResponse as AppInvokeResponse, - type AppRetrieveInvocationResponse as AppRetrieveInvocationResponse, type AppDeployParams as AppDeployParams, type AppInvokeParams as AppInvokeParams, }; diff --git a/src/resources/index.ts b/src/resources/index.ts index b324da12..4880116c 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -4,7 +4,6 @@ export { Apps, type AppDeployResponse, type AppInvokeResponse, - type AppRetrieveInvocationResponse, type AppDeployParams, type AppInvokeParams, } from './apps'; diff --git a/tests/api-resources/apps.test.ts b/tests/api-resources/apps.test.ts index cec0d2b1..426d7682 100644 --- a/tests/api-resources/apps.test.ts +++ b/tests/api-resources/apps.test.ts @@ -60,16 +60,4 @@ describe('resource apps', () => { version: '1.0.0', }); }); - - // skipped: tests are disabled for the time being - test.skip('retrieveInvocation', async () => { - const responsePromise = client.apps.retrieveInvocation('ckqwer3o20000jb9s7abcdef'); - 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); - }); }); From 728638c2c7e7aaa935a8bb31eff17697041048ef Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sun, 11 May 2025 10:46:09 +0000 Subject: [PATCH 015/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 5375ff4d..fad80ad1 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.1.0-alpha.6" + ".": "0.1.0-alpha.7" } diff --git a/package.json b/package.json index 2f6d32a4..d00cf071 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.1.0-alpha.6", + "version": "0.1.0-alpha.7", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 9b7cfeb5..135324a4 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.1.0-alpha.6'; // x-release-please-version +export const VERSION = '0.1.0-alpha.7'; // x-release-please-version From bfb8379dc54972c125b99ffa23de4bf2c49d1d28 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sun, 11 May 2025 11:26:36 +0000 Subject: [PATCH 016/551] feat(api): update via SDK Studio --- .stats.yml | 4 ++-- api.md | 2 ++ src/client.ts | 2 ++ src/resources/apps.ts | 32 ++++++++++++++++++++++++++++++++ src/resources/index.ts | 1 + tests/api-resources/apps.test.ts | 12 ++++++++++++ 6 files changed, 51 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 42510a99..6af3fb9c 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 3 +configured_endpoints: 4 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-d168b58fcf39dbd0458d132091793d3e2d0930070b7dda2d5f7f1baff20dd31b.yml openapi_spec_hash: b7e0fd7ee1656d7dbad57209d1584d92 -config_hash: 9139d1eb064baf60fd2265aac382f097 +config_hash: eab40627b734534462ae3b8ccd8b263b diff --git a/api.md b/api.md index ed6594e7..02224e64 100644 --- a/api.md +++ b/api.md @@ -4,11 +4,13 @@ Types: - AppDeployResponse - AppInvokeResponse +- AppRetrieveInvocationResponse Methods: - client.apps.deploy({ ...params }) -> AppDeployResponse - client.apps.invoke({ ...params }) -> AppInvokeResponse +- client.apps.retrieveInvocation(id) -> AppRetrieveInvocationResponse # Browser diff --git a/src/client.ts b/src/client.ts index c326bea4..6d1d344d 100644 --- a/src/client.ts +++ b/src/client.ts @@ -25,6 +25,7 @@ import { AppDeployResponse, AppInvokeParams, AppInvokeResponse, + AppRetrieveInvocationResponse, Apps, } from './resources/apps'; import { Browser, BrowserCreateSessionResponse } from './resources/browser'; @@ -734,6 +735,7 @@ export declare namespace Kernel { Apps as Apps, type AppDeployResponse as AppDeployResponse, type AppInvokeResponse as AppInvokeResponse, + type AppRetrieveInvocationResponse as AppRetrieveInvocationResponse, type AppDeployParams as AppDeployParams, type AppInvokeParams as AppInvokeParams, }; diff --git a/src/resources/apps.ts b/src/resources/apps.ts index fd601e94..e8feb85b 100644 --- a/src/resources/apps.ts +++ b/src/resources/apps.ts @@ -5,6 +5,7 @@ import { APIPromise } from '../core/api-promise'; import { type Uploadable } from '../core/uploads'; import { RequestOptions } from '../internal/request-options'; import { multipartFormRequestOptions } from '../internal/uploads'; +import { path } from '../internal/utils/path'; export class Apps extends APIResource { /** @@ -39,6 +40,20 @@ export class Apps extends APIResource { invoke(body: AppInvokeParams, options?: RequestOptions): APIPromise { return this._client.post('/apps/invoke', { body, ...options }); } + + /** + * Get an app invocation by id + * + * @example + * ```ts + * const response = await client.apps.retrieveInvocation( + * 'ckqwer3o20000jb9s7abcdef', + * ); + * ``` + */ + retrieveInvocation(id: string, options?: RequestOptions): APIPromise { + return this._client.get(path`/apps/invocations/${id}`, options); + } } export interface AppDeployResponse { @@ -75,6 +90,22 @@ export interface AppInvokeResponse { output?: string; } +export interface AppRetrieveInvocationResponse { + id: string; + + appName: string; + + finishedAt: string | null; + + input: string; + + output: string; + + startedAt: string; + + status: string; +} + export interface AppDeployParams { /** * Name of the application @@ -123,6 +154,7 @@ export declare namespace Apps { export { type AppDeployResponse as AppDeployResponse, type AppInvokeResponse as AppInvokeResponse, + type AppRetrieveInvocationResponse as AppRetrieveInvocationResponse, type AppDeployParams as AppDeployParams, type AppInvokeParams as AppInvokeParams, }; diff --git a/src/resources/index.ts b/src/resources/index.ts index 4880116c..b324da12 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -4,6 +4,7 @@ export { Apps, type AppDeployResponse, type AppInvokeResponse, + type AppRetrieveInvocationResponse, type AppDeployParams, type AppInvokeParams, } from './apps'; diff --git a/tests/api-resources/apps.test.ts b/tests/api-resources/apps.test.ts index 426d7682..cec0d2b1 100644 --- a/tests/api-resources/apps.test.ts +++ b/tests/api-resources/apps.test.ts @@ -60,4 +60,16 @@ describe('resource apps', () => { version: '1.0.0', }); }); + + // skipped: tests are disabled for the time being + test.skip('retrieveInvocation', async () => { + const responsePromise = client.apps.retrieveInvocation('ckqwer3o20000jb9s7abcdef'); + 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); + }); }); From 7ad47720573f823adc2ac41c0127fb366ac1d5e7 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sun, 11 May 2025 11:29:12 +0000 Subject: [PATCH 017/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index fad80ad1..332798e1 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.1.0-alpha.7" + ".": "0.1.0-alpha.8" } diff --git a/package.json b/package.json index d00cf071..f8ba76ee 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.1.0-alpha.7", + "version": "0.1.0-alpha.8", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 135324a4..2cc4fcdc 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.1.0-alpha.7'; // x-release-please-version +export const VERSION = '0.1.0-alpha.8'; // x-release-please-version From 19526316b4edeb63bcd197e560d40dba8a678daa Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 12 May 2025 18:48:41 +0000 Subject: [PATCH 018/551] feat(api): update via SDK Studio --- .stats.yml | 4 +-- README.md | 51 +++++++------------------- api.md | 2 +- src/client.ts | 8 +++-- src/resources/apps.ts | 55 +++++++++++++++++++++-------- src/resources/browser.ts | 19 ++++++++-- src/resources/index.ts | 2 +- tests/api-resources/apps.test.ts | 11 +++--- tests/api-resources/browser.test.ts | 9 +++-- 9 files changed, 91 insertions(+), 70 deletions(-) diff --git a/.stats.yml b/.stats.yml index 6af3fb9c..cbc2ff8f 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 4 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-d168b58fcf39dbd0458d132091793d3e2d0930070b7dda2d5f7f1baff20dd31b.yml -openapi_spec_hash: b7e0fd7ee1656d7dbad57209d1584d92 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-2af763aab4c314b382e1123edc4ee3d51c0fe7977730ce6776b9fb09b29fe291.yml +openapi_spec_hash: be02256478be81fa3f649076879850bc config_hash: eab40627b734534462ae3b8ccd8b263b diff --git a/README.md b/README.md index 9373ffc3..d2163dfd 100644 --- a/README.md +++ b/README.md @@ -29,12 +29,11 @@ const client = new Kernel({ async function main() { const response = await client.apps.deploy({ - appName: 'REPLACE_ME', file: fs.createReadStream('path/to/file'), version: 'REPLACE_ME', }); - console.log(response.id); + console.log(response.apps); } main(); @@ -54,11 +53,7 @@ const client = new Kernel({ }); async function main() { - const params: Kernel.AppDeployParams = { - appName: 'REPLACE_ME', - file: fs.createReadStream('path/to/file'), - version: 'REPLACE_ME', - }; + const params: Kernel.AppDeployParams = { file: fs.createReadStream('path/to/file'), version: 'REPLACE_ME' }; const response: Kernel.AppDeployResponse = await client.apps.deploy(params); } @@ -83,37 +78,17 @@ import Kernel, { toFile } from '@onkernel/sdk'; const client = new Kernel(); // If you have access to Node `fs` we recommend using `fs.createReadStream()`: -await client.apps.deploy({ - appName: 'my-awesome-app', - file: fs.createReadStream('/path/to/file'), - version: '1.0.0', -}); +await client.apps.deploy({ file: fs.createReadStream('/path/to/file') }); // Or if you have the web `File` API you can pass a `File` instance: -await client.apps.deploy({ - appName: 'my-awesome-app', - file: new File(['my bytes'], 'file'), - version: '1.0.0', -}); +await client.apps.deploy({ file: new File(['my bytes'], 'file') }); // You can also pass a `fetch` `Response`: -await client.apps.deploy({ - appName: 'my-awesome-app', - file: await fetch('https://somesite/file'), - version: '1.0.0', -}); +await client.apps.deploy({ file: await fetch('https://somesite/file') }); // Finally, if none of the above are convenient, you can use our `toFile` helper: -await client.apps.deploy({ - appName: 'my-awesome-app', - file: await toFile(Buffer.from('my bytes'), 'file'), - version: '1.0.0', -}); -await client.apps.deploy({ - appName: 'my-awesome-app', - file: await toFile(new Uint8Array([0, 1, 2]), 'file'), - version: '1.0.0', -}); +await client.apps.deploy({ file: await toFile(Buffer.from('my bytes'), 'file') }); +await client.apps.deploy({ file: await toFile(new Uint8Array([0, 1, 2]), 'file') }); ``` ## Handling errors @@ -126,7 +101,7 @@ a subclass of `APIError` will be thrown: ```ts async function main() { const response = await client.apps - .deploy({ appName: 'REPLACE_ME', file: fs.createReadStream('path/to/file'), version: 'REPLACE_ME' }) + .deploy({ file: fs.createReadStream('path/to/file'), version: 'REPLACE_ME' }) .catch(async (err) => { if (err instanceof Kernel.APIError) { console.log(err.status); // 400 @@ -170,7 +145,7 @@ const client = new Kernel({ }); // Or, configure per-request: -await client.apps.deploy({ appName: 'REPLACE_ME', file: fs.createReadStream('path/to/file'), version: 'REPLACE_ME' }, { +await client.apps.deploy({ file: fs.createReadStream('path/to/file'), version: 'REPLACE_ME' }, { maxRetries: 5, }); ``` @@ -187,7 +162,7 @@ const client = new Kernel({ }); // Override per-request: -await client.apps.deploy({ appName: 'REPLACE_ME', file: fs.createReadStream('path/to/file'), version: 'REPLACE_ME' }, { +await client.apps.deploy({ file: fs.createReadStream('path/to/file'), version: 'REPLACE_ME' }, { timeout: 5 * 1000, }); ``` @@ -211,16 +186,16 @@ Unlike `.asResponse()` this method consumes the body, returning once it is parse const client = new Kernel(); const response = await client.apps - .deploy({ appName: 'REPLACE_ME', file: fs.createReadStream('path/to/file'), version: 'REPLACE_ME' }) + .deploy({ file: fs.createReadStream('path/to/file'), version: 'REPLACE_ME' }) .asResponse(); console.log(response.headers.get('X-My-Header')); console.log(response.statusText); // access the underlying Response object const { data: response, response: raw } = await client.apps - .deploy({ appName: 'REPLACE_ME', file: fs.createReadStream('path/to/file'), version: 'REPLACE_ME' }) + .deploy({ file: fs.createReadStream('path/to/file'), version: 'REPLACE_ME' }) .withResponse(); console.log(raw.headers.get('X-My-Header')); -console.log(response.id); +console.log(response.apps); ``` ### Logging diff --git a/api.md b/api.md index 02224e64..88e37988 100644 --- a/api.md +++ b/api.md @@ -20,4 +20,4 @@ Types: Methods: -- client.browser.createSession() -> BrowserCreateSessionResponse +- client.browser.createSession({ ...params }) -> BrowserCreateSessionResponse diff --git a/src/client.ts b/src/client.ts index 6d1d344d..57650a9a 100644 --- a/src/client.ts +++ b/src/client.ts @@ -28,7 +28,7 @@ import { AppRetrieveInvocationResponse, Apps, } from './resources/apps'; -import { Browser, BrowserCreateSessionResponse } from './resources/browser'; +import { Browser, BrowserCreateSessionParams, BrowserCreateSessionResponse } from './resources/browser'; import { readEnv } from './internal/utils/env'; import { formatRequestDetails, loggerFor } from './internal/utils/log'; import { isEmptyObj } from './internal/utils/values'; @@ -740,5 +740,9 @@ export declare namespace Kernel { type AppInvokeParams as AppInvokeParams, }; - export { Browser as Browser, type BrowserCreateSessionResponse as BrowserCreateSessionResponse }; + export { + Browser as Browser, + type BrowserCreateSessionResponse as BrowserCreateSessionResponse, + type BrowserCreateSessionParams as BrowserCreateSessionParams, + }; } diff --git a/src/resources/apps.ts b/src/resources/apps.ts index e8feb85b..8219c1cd 100644 --- a/src/resources/apps.ts +++ b/src/resources/apps.ts @@ -14,9 +14,7 @@ export class Apps extends APIResource { * @example * ```ts * const response = await client.apps.deploy({ - * appName: 'my-awesome-app', * file: fs.createReadStream('path/to/file'), - * version: '1.0.0', * }); * ``` */ @@ -32,7 +30,7 @@ export class Apps extends APIResource { * const response = await client.apps.invoke({ * actionName: 'analyze', * appName: 'my-awesome-app', - * payload: '{ "data": "example input" }', + * payload: { data: 'example input' }, * version: '1.0.0', * }); * ``` @@ -57,10 +55,7 @@ export class Apps extends APIResource { } export interface AppDeployResponse { - /** - * ID of the deployed app version - */ - id: string; + apps: Array; /** * Success message @@ -73,6 +68,31 @@ export interface AppDeployResponse { success: boolean; } +export namespace AppDeployResponse { + export interface App { + /** + * ID for the app version deployed + */ + id: string; + + actions: Array; + + /** + * Name of the app + */ + name: string; + } + + export namespace App { + export interface Action { + /** + * Name of the action + */ + name: string; + } + } +} + export interface AppInvokeResponse { /** * ID of the invocation @@ -108,24 +128,29 @@ export interface AppRetrieveInvocationResponse { export interface AppDeployParams { /** - * Name of the application + * ZIP file containing the application source directory */ - appName: string; + file: Uploadable; /** - * ZIP file containing the application + * Relative path to the entrypoint of the application */ - file: Uploadable; + entrypointRelPath?: string; /** - * Version of the application + * Allow overwriting an existing app version */ - version: string; + force?: 'true' | 'false'; + + /** + * Region for deployment. Currently we only support "aws.us-east-1a" + */ + region?: 'aws.us-east-1a'; /** - * AWS region for deployment (e.g. "aws.us-east-1a") + * Version of the application. Can be any string. */ - region?: string; + version?: string; } export interface AppInvokeParams { diff --git a/src/resources/browser.ts b/src/resources/browser.ts index 3ab78702..2b434f57 100644 --- a/src/resources/browser.ts +++ b/src/resources/browser.ts @@ -8,8 +8,11 @@ export class Browser extends APIResource { /** * Create Browser Session */ - createSession(options?: RequestOptions): APIPromise { - return this._client.post('/browser', options); + createSession( + body: BrowserCreateSessionParams, + options?: RequestOptions, + ): APIPromise { + return this._client.post('/browser', { body, ...options }); } } @@ -30,6 +33,16 @@ export interface BrowserCreateSessionResponse { sessionId: string; } +export interface BrowserCreateSessionParams { + /** + * Kernel App invocation ID + */ + invocationId: string; +} + export declare namespace Browser { - export { type BrowserCreateSessionResponse as BrowserCreateSessionResponse }; + export { + type BrowserCreateSessionResponse as BrowserCreateSessionResponse, + type BrowserCreateSessionParams as BrowserCreateSessionParams, + }; } diff --git a/src/resources/index.ts b/src/resources/index.ts index b324da12..bf366e62 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -8,4 +8,4 @@ export { type AppDeployParams, type AppInvokeParams, } from './apps'; -export { Browser, type BrowserCreateSessionResponse } from './browser'; +export { Browser, type BrowserCreateSessionResponse, type BrowserCreateSessionParams } from './browser'; diff --git a/tests/api-resources/apps.test.ts b/tests/api-resources/apps.test.ts index cec0d2b1..7cb3c564 100644 --- a/tests/api-resources/apps.test.ts +++ b/tests/api-resources/apps.test.ts @@ -11,9 +11,7 @@ describe('resource apps', () => { // skipped: tests are disabled for the time being test.skip('deploy: only required params', async () => { const responsePromise = client.apps.deploy({ - appName: 'my-awesome-app', file: await toFile(Buffer.from('# my file contents'), 'README.md'), - version: '1.0.0', }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); @@ -27,10 +25,11 @@ describe('resource apps', () => { // skipped: tests are disabled for the time being test.skip('deploy: required and optional params', async () => { const response = await client.apps.deploy({ - appName: 'my-awesome-app', file: await toFile(Buffer.from('# my file contents'), 'README.md'), - version: '1.0.0', + entrypointRelPath: 'app.py', + force: 'false', region: 'aws.us-east-1a', + version: '1.0.0', }); }); @@ -39,7 +38,7 @@ describe('resource apps', () => { const responsePromise = client.apps.invoke({ actionName: 'analyze', appName: 'my-awesome-app', - payload: '{ "data": "example input" }', + payload: { data: 'example input' }, version: '1.0.0', }); const rawResponse = await responsePromise.asResponse(); @@ -56,7 +55,7 @@ describe('resource apps', () => { const response = await client.apps.invoke({ actionName: 'analyze', appName: 'my-awesome-app', - payload: '{ "data": "example input" }', + payload: { data: 'example input' }, version: '1.0.0', }); }); diff --git a/tests/api-resources/browser.test.ts b/tests/api-resources/browser.test.ts index 6782448f..012e207c 100644 --- a/tests/api-resources/browser.test.ts +++ b/tests/api-resources/browser.test.ts @@ -9,8 +9,8 @@ const client = new Kernel({ describe('resource browser', () => { // skipped: tests are disabled for the time being - test.skip('createSession', async () => { - const responsePromise = client.browser.createSession(); + test.skip('createSession: only required params', async () => { + const responsePromise = client.browser.createSession({ invocationId: 'invocationId' }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -19,4 +19,9 @@ describe('resource browser', () => { expect(dataAndResponse.data).toBe(response); expect(dataAndResponse.response).toBe(rawResponse); }); + + // skipped: tests are disabled for the time being + test.skip('createSession: required and optional params', async () => { + const response = await client.browser.createSession({ invocationId: 'invocationId' }); + }); }); From 6b52025462950f014178136cd6c2e6e55d9e834f Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 12 May 2025 18:50:50 +0000 Subject: [PATCH 019/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 332798e1..347d8bf7 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.1.0-alpha.8" + ".": "0.1.0-alpha.9" } diff --git a/package.json b/package.json index f8ba76ee..7e24e0f1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.1.0-alpha.8", + "version": "0.1.0-alpha.9", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 2cc4fcdc..fdbf6896 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.1.0-alpha.8'; // x-release-please-version +export const VERSION = '0.1.0-alpha.9'; // x-release-please-version From 4411acf021571409435d7ba07c47b02fd0866cfe Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 13 May 2025 03:12:20 +0000 Subject: [PATCH 020/551] chore(package): remove engines --- package.json | 3 --- 1 file changed, 3 deletions(-) diff --git a/package.json b/package.json index 7e24e0f1..baf0faf0 100644 --- a/package.json +++ b/package.json @@ -68,8 +68,5 @@ "import": "./dist/*.mjs", "require": "./dist/*.js" } - }, - "engines": { - "node": ">= 20" } } From 893fee586868fd28a66bfeeea8ab0262b401a75b Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 14 May 2025 22:51:27 +0000 Subject: [PATCH 021/551] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index cbc2ff8f..1b796feb 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 4 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-2af763aab4c314b382e1123edc4ee3d51c0fe7977730ce6776b9fb09b29fe291.yml openapi_spec_hash: be02256478be81fa3f649076879850bc -config_hash: eab40627b734534462ae3b8ccd8b263b +config_hash: 71cb25ebb05ff0dd0e98c3b2ee091bc4 From fecf30b5dc30ef3ebac35b5c56ae9c61138e0e7d Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 14 May 2025 22:52:58 +0000 Subject: [PATCH 022/551] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index 1b796feb..fbd02611 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 4 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-2af763aab4c314b382e1123edc4ee3d51c0fe7977730ce6776b9fb09b29fe291.yml openapi_spec_hash: be02256478be81fa3f649076879850bc -config_hash: 71cb25ebb05ff0dd0e98c3b2ee091bc4 +config_hash: 2c8351ba6611ce4a352e248405783846 From f64cbbda6ea55980d664025f7a28c1320a6c76c7 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 14 May 2025 22:53:57 +0000 Subject: [PATCH 023/551] feat(api): update via SDK Studio --- .stats.yml | 4 ++-- README.md | 33 +++++++++++++++++++++----------- src/resources/apps.ts | 9 +++++---- tests/api-resources/apps.test.ts | 3 ++- 4 files changed, 31 insertions(+), 18 deletions(-) diff --git a/.stats.yml b/.stats.yml index fbd02611..d6d797ad 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 4 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-2af763aab4c314b382e1123edc4ee3d51c0fe7977730ce6776b9fb09b29fe291.yml -openapi_spec_hash: be02256478be81fa3f649076879850bc +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-07d481d1498bf9677437b555e9ec2d843d50107faa7501e4c430a32b1f3c3343.yml +openapi_spec_hash: 296f78d82afbac95fad12c5eabd71f18 config_hash: 2c8351ba6611ce4a352e248405783846 diff --git a/README.md b/README.md index d2163dfd..e9bb7a32 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,7 @@ const client = new Kernel({ async function main() { const response = await client.apps.deploy({ + entrypointRelPath: 'app.py', file: fs.createReadStream('path/to/file'), version: 'REPLACE_ME', }); @@ -53,7 +54,11 @@ const client = new Kernel({ }); async function main() { - const params: Kernel.AppDeployParams = { file: fs.createReadStream('path/to/file'), version: 'REPLACE_ME' }; + const params: Kernel.AppDeployParams = { + entrypointRelPath: 'app.py', + file: fs.createReadStream('path/to/file'), + version: 'REPLACE_ME', + }; const response: Kernel.AppDeployResponse = await client.apps.deploy(params); } @@ -78,17 +83,23 @@ import Kernel, { toFile } from '@onkernel/sdk'; const client = new Kernel(); // If you have access to Node `fs` we recommend using `fs.createReadStream()`: -await client.apps.deploy({ file: fs.createReadStream('/path/to/file') }); +await client.apps.deploy({ entrypointRelPath: 'app.py', file: fs.createReadStream('/path/to/file') }); // Or if you have the web `File` API you can pass a `File` instance: -await client.apps.deploy({ file: new File(['my bytes'], 'file') }); +await client.apps.deploy({ entrypointRelPath: 'app.py', file: new File(['my bytes'], 'file') }); // You can also pass a `fetch` `Response`: -await client.apps.deploy({ file: await fetch('https://somesite/file') }); +await client.apps.deploy({ entrypointRelPath: 'app.py', file: await fetch('https://somesite/file') }); // Finally, if none of the above are convenient, you can use our `toFile` helper: -await client.apps.deploy({ file: await toFile(Buffer.from('my bytes'), 'file') }); -await client.apps.deploy({ file: await toFile(new Uint8Array([0, 1, 2]), 'file') }); +await client.apps.deploy({ + entrypointRelPath: 'app.py', + file: await toFile(Buffer.from('my bytes'), 'file'), +}); +await client.apps.deploy({ + entrypointRelPath: 'app.py', + file: await toFile(new Uint8Array([0, 1, 2]), 'file'), +}); ``` ## Handling errors @@ -101,7 +112,7 @@ a subclass of `APIError` will be thrown: ```ts async function main() { const response = await client.apps - .deploy({ file: fs.createReadStream('path/to/file'), version: 'REPLACE_ME' }) + .deploy({ entrypointRelPath: 'app.py', file: fs.createReadStream('path/to/file'), version: 'REPLACE_ME' }) .catch(async (err) => { if (err instanceof Kernel.APIError) { console.log(err.status); // 400 @@ -145,7 +156,7 @@ const client = new Kernel({ }); // Or, configure per-request: -await client.apps.deploy({ file: fs.createReadStream('path/to/file'), version: 'REPLACE_ME' }, { +await client.apps.deploy({ entrypointRelPath: 'app.py', file: fs.createReadStream('path/to/file'), version: 'REPLACE_ME' }, { maxRetries: 5, }); ``` @@ -162,7 +173,7 @@ const client = new Kernel({ }); // Override per-request: -await client.apps.deploy({ file: fs.createReadStream('path/to/file'), version: 'REPLACE_ME' }, { +await client.apps.deploy({ entrypointRelPath: 'app.py', file: fs.createReadStream('path/to/file'), version: 'REPLACE_ME' }, { timeout: 5 * 1000, }); ``` @@ -186,13 +197,13 @@ Unlike `.asResponse()` this method consumes the body, returning once it is parse const client = new Kernel(); const response = await client.apps - .deploy({ file: fs.createReadStream('path/to/file'), version: 'REPLACE_ME' }) + .deploy({ entrypointRelPath: 'app.py', file: fs.createReadStream('path/to/file'), version: 'REPLACE_ME' }) .asResponse(); console.log(response.headers.get('X-My-Header')); console.log(response.statusText); // access the underlying Response object const { data: response, response: raw } = await client.apps - .deploy({ file: fs.createReadStream('path/to/file'), version: 'REPLACE_ME' }) + .deploy({ entrypointRelPath: 'app.py', file: fs.createReadStream('path/to/file'), version: 'REPLACE_ME' }) .withResponse(); console.log(raw.headers.get('X-My-Header')); console.log(response.apps); diff --git a/src/resources/apps.ts b/src/resources/apps.ts index 8219c1cd..ddf6f55a 100644 --- a/src/resources/apps.ts +++ b/src/resources/apps.ts @@ -14,6 +14,7 @@ export class Apps extends APIResource { * @example * ```ts * const response = await client.apps.deploy({ + * entrypointRelPath: 'app.py', * file: fs.createReadStream('path/to/file'), * }); * ``` @@ -128,14 +129,14 @@ export interface AppRetrieveInvocationResponse { export interface AppDeployParams { /** - * ZIP file containing the application source directory + * Relative path to the entrypoint of the application */ - file: Uploadable; + entrypointRelPath: string; /** - * Relative path to the entrypoint of the application + * ZIP file containing the application source directory */ - entrypointRelPath?: string; + file: Uploadable; /** * Allow overwriting an existing app version diff --git a/tests/api-resources/apps.test.ts b/tests/api-resources/apps.test.ts index 7cb3c564..974e97b6 100644 --- a/tests/api-resources/apps.test.ts +++ b/tests/api-resources/apps.test.ts @@ -11,6 +11,7 @@ describe('resource apps', () => { // skipped: tests are disabled for the time being test.skip('deploy: only required params', async () => { const responsePromise = client.apps.deploy({ + entrypointRelPath: 'app.py', file: await toFile(Buffer.from('# my file contents'), 'README.md'), }); const rawResponse = await responsePromise.asResponse(); @@ -25,8 +26,8 @@ describe('resource apps', () => { // skipped: tests are disabled for the time being test.skip('deploy: required and optional params', async () => { const response = await client.apps.deploy({ - file: await toFile(Buffer.from('# my file contents'), 'README.md'), entrypointRelPath: 'app.py', + file: await toFile(Buffer.from('# my file contents'), 'README.md'), force: 'false', region: 'aws.us-east-1a', version: '1.0.0', From 7aa5df4b6ebdb867b4afb6a2bfe5102d18231473 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 14 May 2025 22:55:11 +0000 Subject: [PATCH 024/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 347d8bf7..931fce1a 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.1.0-alpha.9" + ".": "0.1.0-alpha.10" } diff --git a/package.json b/package.json index baf0faf0..dacc7bed 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.1.0-alpha.9", + "version": "0.1.0-alpha.10", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index fdbf6896..5ed52cd1 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.1.0-alpha.9'; // x-release-please-version +export const VERSION = '0.1.0-alpha.10'; // x-release-please-version From 81f1bb926a260f193863bfefa40a3efe57f294ee Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 19 May 2025 18:37:59 +0000 Subject: [PATCH 025/551] feat(api): update via SDK Studio --- .stats.yml | 8 +- README.md | 73 +++---- api.md | 30 ++- src/client.ts | 34 ++-- src/resources/apps.ts | 186 +----------------- src/resources/apps/apps.ts | 35 ++++ src/resources/apps/deployments.ts | 103 ++++++++++ src/resources/apps/index.ts | 10 + src/resources/apps/invocations.ts | 140 +++++++++++++ src/resources/browser.ts | 48 ----- src/resources/browsers.ts | 85 ++++++++ src/resources/index.ts | 14 +- tests/api-resources/apps.test.ts | 75 ------- .../deployments.test.ts} | 21 +- tests/api-resources/apps/invocations.test.ts | 48 +++++ tests/api-resources/browsers.test.ts | 39 ++++ 16 files changed, 557 insertions(+), 392 deletions(-) create mode 100644 src/resources/apps/apps.ts create mode 100644 src/resources/apps/deployments.ts create mode 100644 src/resources/apps/index.ts create mode 100644 src/resources/apps/invocations.ts delete mode 100644 src/resources/browser.ts create mode 100644 src/resources/browsers.ts delete mode 100644 tests/api-resources/apps.test.ts rename tests/api-resources/{browser.test.ts => apps/deployments.test.ts} (52%) create mode 100644 tests/api-resources/apps/invocations.test.ts create mode 100644 tests/api-resources/browsers.test.ts diff --git a/.stats.yml b/.stats.yml index d6d797ad..6f21bcbb 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 4 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-07d481d1498bf9677437b555e9ec2d843d50107faa7501e4c430a32b1f3c3343.yml -openapi_spec_hash: 296f78d82afbac95fad12c5eabd71f18 -config_hash: 2c8351ba6611ce4a352e248405783846 +configured_endpoints: 5 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-f40e779e2a48f5e37361f2f4a9879e5c40f2851b8033c23db69ec7b91242bf69.yml +openapi_spec_hash: 2dfa146149e61363f1ec40bf9251eb7c +config_hash: 2ddaa85513b6670889b1a56c905423c7 diff --git a/README.md b/README.md index e9bb7a32..86b14266 100644 --- a/README.md +++ b/README.md @@ -28,13 +28,13 @@ const client = new Kernel({ }); async function main() { - const response = await client.apps.deploy({ - entrypointRelPath: 'app.py', + const deployment = await client.apps.deployments.create({ + entrypoint_rel_path: 'main.ts', file: fs.createReadStream('path/to/file'), - version: 'REPLACE_ME', + version: '1.0.0', }); - console.log(response.apps); + console.log(deployment.apps); } main(); @@ -54,12 +54,8 @@ const client = new Kernel({ }); async function main() { - const params: Kernel.AppDeployParams = { - entrypointRelPath: 'app.py', - file: fs.createReadStream('path/to/file'), - version: 'REPLACE_ME', - }; - const response: Kernel.AppDeployResponse = await client.apps.deploy(params); + const params: Kernel.BrowserCreateParams = { invocation_id: 'REPLACE_ME' }; + const browser: Kernel.BrowserCreateResponse = await client.browsers.create(params); } main(); @@ -83,21 +79,30 @@ import Kernel, { toFile } from '@onkernel/sdk'; const client = new Kernel(); // If you have access to Node `fs` we recommend using `fs.createReadStream()`: -await client.apps.deploy({ entrypointRelPath: 'app.py', file: fs.createReadStream('/path/to/file') }); +await client.apps.deployments.create({ + entrypoint_rel_path: 'src/app.py', + file: fs.createReadStream('/path/to/file'), +}); // Or if you have the web `File` API you can pass a `File` instance: -await client.apps.deploy({ entrypointRelPath: 'app.py', file: new File(['my bytes'], 'file') }); +await client.apps.deployments.create({ + entrypoint_rel_path: 'src/app.py', + file: new File(['my bytes'], 'file'), +}); // You can also pass a `fetch` `Response`: -await client.apps.deploy({ entrypointRelPath: 'app.py', file: await fetch('https://somesite/file') }); +await client.apps.deployments.create({ + entrypoint_rel_path: 'src/app.py', + file: await fetch('https://somesite/file'), +}); // Finally, if none of the above are convenient, you can use our `toFile` helper: -await client.apps.deploy({ - entrypointRelPath: 'app.py', +await client.apps.deployments.create({ + entrypoint_rel_path: 'src/app.py', file: await toFile(Buffer.from('my bytes'), 'file'), }); -await client.apps.deploy({ - entrypointRelPath: 'app.py', +await client.apps.deployments.create({ + entrypoint_rel_path: 'src/app.py', file: await toFile(new Uint8Array([0, 1, 2]), 'file'), }); ``` @@ -111,17 +116,15 @@ a subclass of `APIError` will be thrown: ```ts async function main() { - const response = await client.apps - .deploy({ entrypointRelPath: 'app.py', file: fs.createReadStream('path/to/file'), version: 'REPLACE_ME' }) - .catch(async (err) => { - if (err instanceof Kernel.APIError) { - console.log(err.status); // 400 - console.log(err.name); // BadRequestError - console.log(err.headers); // {server: 'nginx', ...} - } else { - throw err; - } - }); + const browser = await client.browsers.create({ invocation_id: 'REPLACE_ME' }).catch(async (err) => { + if (err instanceof Kernel.APIError) { + console.log(err.status); // 400 + console.log(err.name); // BadRequestError + console.log(err.headers); // {server: 'nginx', ...} + } else { + throw err; + } + }); } main(); @@ -156,7 +159,7 @@ const client = new Kernel({ }); // Or, configure per-request: -await client.apps.deploy({ entrypointRelPath: 'app.py', file: fs.createReadStream('path/to/file'), version: 'REPLACE_ME' }, { +await client.browsers.create({ invocation_id: 'REPLACE_ME' }, { maxRetries: 5, }); ``` @@ -173,7 +176,7 @@ const client = new Kernel({ }); // Override per-request: -await client.apps.deploy({ entrypointRelPath: 'app.py', file: fs.createReadStream('path/to/file'), version: 'REPLACE_ME' }, { +await client.browsers.create({ invocation_id: 'REPLACE_ME' }, { timeout: 5 * 1000, }); ``` @@ -196,17 +199,15 @@ Unlike `.asResponse()` this method consumes the body, returning once it is parse ```ts const client = new Kernel(); -const response = await client.apps - .deploy({ entrypointRelPath: 'app.py', file: fs.createReadStream('path/to/file'), version: 'REPLACE_ME' }) - .asResponse(); +const response = await client.browsers.create({ invocation_id: 'REPLACE_ME' }).asResponse(); console.log(response.headers.get('X-My-Header')); console.log(response.statusText); // access the underlying Response object -const { data: response, response: raw } = await client.apps - .deploy({ entrypointRelPath: 'app.py', file: fs.createReadStream('path/to/file'), version: 'REPLACE_ME' }) +const { data: browser, response: raw } = await client.browsers + .create({ invocation_id: 'REPLACE_ME' }) .withResponse(); console.log(raw.headers.get('X-My-Header')); -console.log(response.apps); +console.log(browser.session_id); ``` ### Logging diff --git a/api.md b/api.md index 88e37988..1fc97fdc 100644 --- a/api.md +++ b/api.md @@ -1,23 +1,35 @@ # Apps +## Deployments + +Types: + +- DeploymentCreateResponse + +Methods: + +- client.apps.deployments.create({ ...params }) -> DeploymentCreateResponse + +## Invocations + Types: -- AppDeployResponse -- AppInvokeResponse -- AppRetrieveInvocationResponse +- InvocationCreateResponse +- InvocationRetrieveResponse Methods: -- client.apps.deploy({ ...params }) -> AppDeployResponse -- client.apps.invoke({ ...params }) -> AppInvokeResponse -- client.apps.retrieveInvocation(id) -> AppRetrieveInvocationResponse +- client.apps.invocations.create({ ...params }) -> InvocationCreateResponse +- client.apps.invocations.retrieve(id) -> InvocationRetrieveResponse -# Browser +# Browsers Types: -- BrowserCreateSessionResponse +- BrowserCreateResponse +- BrowserRetrieveResponse Methods: -- client.browser.createSession({ ...params }) -> BrowserCreateSessionResponse +- client.browsers.create({ ...params }) -> BrowserCreateResponse +- client.browsers.retrieve(id) -> BrowserRetrieveResponse diff --git a/src/client.ts b/src/client.ts index 57650a9a..a78cf2de 100644 --- a/src/client.ts +++ b/src/client.ts @@ -21,17 +21,15 @@ import { type Fetch } from './internal/builtin-types'; import { HeadersLike, NullableHeaders, buildHeaders } from './internal/headers'; import { FinalRequestOptions, RequestOptions } from './internal/request-options'; import { - AppDeployParams, - AppDeployResponse, - AppInvokeParams, - AppInvokeResponse, - AppRetrieveInvocationResponse, - Apps, -} from './resources/apps'; -import { Browser, BrowserCreateSessionParams, BrowserCreateSessionResponse } from './resources/browser'; + BrowserCreateParams, + BrowserCreateResponse, + BrowserRetrieveResponse, + Browsers, +} from './resources/browsers'; import { readEnv } from './internal/utils/env'; import { formatRequestDetails, loggerFor } from './internal/utils/log'; import { isEmptyObj } from './internal/utils/values'; +import { Apps } from './resources/apps/apps'; const environments = { production: 'https://api.onkernel.com/', @@ -724,25 +722,19 @@ export class Kernel { static toFile = Uploads.toFile; apps: API.Apps = new API.Apps(this); - browser: API.Browser = new API.Browser(this); + browsers: API.Browsers = new API.Browsers(this); } Kernel.Apps = Apps; -Kernel.Browser = Browser; +Kernel.Browsers = Browsers; export declare namespace Kernel { export type RequestOptions = Opts.RequestOptions; - export { - Apps as Apps, - type AppDeployResponse as AppDeployResponse, - type AppInvokeResponse as AppInvokeResponse, - type AppRetrieveInvocationResponse as AppRetrieveInvocationResponse, - type AppDeployParams as AppDeployParams, - type AppInvokeParams as AppInvokeParams, - }; + export { Apps as Apps }; export { - Browser as Browser, - type BrowserCreateSessionResponse as BrowserCreateSessionResponse, - type BrowserCreateSessionParams as BrowserCreateSessionParams, + Browsers as Browsers, + type BrowserCreateResponse as BrowserCreateResponse, + type BrowserRetrieveResponse as BrowserRetrieveResponse, + type BrowserCreateParams as BrowserCreateParams, }; } diff --git a/src/resources/apps.ts b/src/resources/apps.ts index ddf6f55a..c368b826 100644 --- a/src/resources/apps.ts +++ b/src/resources/apps.ts @@ -1,187 +1,3 @@ // 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 { type Uploadable } from '../core/uploads'; -import { RequestOptions } from '../internal/request-options'; -import { multipartFormRequestOptions } from '../internal/uploads'; -import { path } from '../internal/utils/path'; - -export class Apps extends APIResource { - /** - * Deploy a new application - * - * @example - * ```ts - * const response = await client.apps.deploy({ - * entrypointRelPath: 'app.py', - * file: fs.createReadStream('path/to/file'), - * }); - * ``` - */ - deploy(body: AppDeployParams, options?: RequestOptions): APIPromise { - return this._client.post('/apps/deploy', multipartFormRequestOptions({ body, ...options }, this._client)); - } - - /** - * Invoke an application - * - * @example - * ```ts - * const response = await client.apps.invoke({ - * actionName: 'analyze', - * appName: 'my-awesome-app', - * payload: { data: 'example input' }, - * version: '1.0.0', - * }); - * ``` - */ - invoke(body: AppInvokeParams, options?: RequestOptions): APIPromise { - return this._client.post('/apps/invoke', { body, ...options }); - } - - /** - * Get an app invocation by id - * - * @example - * ```ts - * const response = await client.apps.retrieveInvocation( - * 'ckqwer3o20000jb9s7abcdef', - * ); - * ``` - */ - retrieveInvocation(id: string, options?: RequestOptions): APIPromise { - return this._client.get(path`/apps/invocations/${id}`, options); - } -} - -export interface AppDeployResponse { - apps: Array; - - /** - * Success message - */ - message: string; - - /** - * Status of the deployment - */ - success: boolean; -} - -export namespace AppDeployResponse { - export interface App { - /** - * ID for the app version deployed - */ - id: string; - - actions: Array; - - /** - * Name of the app - */ - name: string; - } - - export namespace App { - export interface Action { - /** - * Name of the action - */ - name: string; - } - } -} - -export interface AppInvokeResponse { - /** - * ID of the invocation - */ - id: string; - - /** - * Status of the invocation - */ - status: 'QUEUED' | 'RUNNING' | 'SUCCEEDED' | 'FAILED'; - - /** - * Output from the invocation (if available) - */ - output?: string; -} - -export interface AppRetrieveInvocationResponse { - id: string; - - appName: string; - - finishedAt: string | null; - - input: string; - - output: string; - - startedAt: string; - - status: string; -} - -export interface AppDeployParams { - /** - * Relative path to the entrypoint of the application - */ - entrypointRelPath: string; - - /** - * ZIP file containing the application source directory - */ - file: Uploadable; - - /** - * Allow overwriting an existing app version - */ - force?: 'true' | 'false'; - - /** - * Region for deployment. Currently we only support "aws.us-east-1a" - */ - region?: 'aws.us-east-1a'; - - /** - * Version of the application. Can be any string. - */ - version?: string; -} - -export interface AppInvokeParams { - /** - * Name of the action to invoke - */ - actionName: string; - - /** - * Name of the application - */ - appName: string; - - /** - * Input data for the application - */ - payload: unknown; - - /** - * Version of the application - */ - version: string; -} - -export declare namespace Apps { - export { - type AppDeployResponse as AppDeployResponse, - type AppInvokeResponse as AppInvokeResponse, - type AppRetrieveInvocationResponse as AppRetrieveInvocationResponse, - type AppDeployParams as AppDeployParams, - type AppInvokeParams as AppInvokeParams, - }; -} +export * from './apps/index'; diff --git a/src/resources/apps/apps.ts b/src/resources/apps/apps.ts new file mode 100644 index 00000000..fe32c1ee --- /dev/null +++ b/src/resources/apps/apps.ts @@ -0,0 +1,35 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../core/resource'; +import * as DeploymentsAPI from './deployments'; +import { DeploymentCreateParams, DeploymentCreateResponse, Deployments } from './deployments'; +import * as InvocationsAPI from './invocations'; +import { + InvocationCreateParams, + InvocationCreateResponse, + InvocationRetrieveResponse, + Invocations, +} from './invocations'; + +export class Apps extends APIResource { + deployments: DeploymentsAPI.Deployments = new DeploymentsAPI.Deployments(this._client); + invocations: InvocationsAPI.Invocations = new InvocationsAPI.Invocations(this._client); +} + +Apps.Deployments = Deployments; +Apps.Invocations = Invocations; + +export declare namespace Apps { + export { + Deployments as Deployments, + type DeploymentCreateResponse as DeploymentCreateResponse, + type DeploymentCreateParams as DeploymentCreateParams, + }; + + export { + Invocations as Invocations, + type InvocationCreateResponse as InvocationCreateResponse, + type InvocationRetrieveResponse as InvocationRetrieveResponse, + type InvocationCreateParams as InvocationCreateParams, + }; +} diff --git a/src/resources/apps/deployments.ts b/src/resources/apps/deployments.ts new file mode 100644 index 00000000..abd96550 --- /dev/null +++ b/src/resources/apps/deployments.ts @@ -0,0 +1,103 @@ +// 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 { type Uploadable } from '../../core/uploads'; +import { RequestOptions } from '../../internal/request-options'; +import { multipartFormRequestOptions } from '../../internal/uploads'; + +export class Deployments extends APIResource { + /** + * Deploy a new application + * + * @example + * ```ts + * const deployment = await client.apps.deployments.create({ + * entrypoint_rel_path: 'src/app.py', + * file: fs.createReadStream('path/to/file'), + * }); + * ``` + */ + create(body: DeploymentCreateParams, options?: RequestOptions): APIPromise { + return this._client.post('/deploy', multipartFormRequestOptions({ body, ...options }, this._client)); + } +} + +export interface DeploymentCreateResponse { + /** + * List of apps deployed + */ + apps: Array; + + /** + * Current status of the deployment + */ + status: 'queued' | 'deploying' | 'succeeded' | 'failed'; + + /** + * Status reason + */ + status_reason?: string; +} + +export namespace DeploymentCreateResponse { + export interface App { + /** + * ID for the app version deployed + */ + id: string; + + /** + * List of actions available on the app + */ + actions: Array; + + /** + * Name of the app + */ + name: string; + } + + export namespace App { + export interface Action { + /** + * Name of the action + */ + name: string; + } + } +} + +export interface DeploymentCreateParams { + /** + * Relative path to the entrypoint of the application + */ + entrypoint_rel_path: string; + + /** + * ZIP file containing the application source directory + */ + file: Uploadable; + + /** + * Allow overwriting an existing app version + */ + force?: boolean; + + /** + * Region for deployment. Currently we only support "aws.us-east-1a" + */ + region?: 'aws.us-east-1a'; + + /** + * Version of the application. Can be any string. + */ + version?: string; +} + +export declare namespace Deployments { + export { + type DeploymentCreateResponse as DeploymentCreateResponse, + type DeploymentCreateParams as DeploymentCreateParams, + }; +} diff --git a/src/resources/apps/index.ts b/src/resources/apps/index.ts new file mode 100644 index 00000000..1703ae2c --- /dev/null +++ b/src/resources/apps/index.ts @@ -0,0 +1,10 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export { Apps } from './apps'; +export { Deployments, type DeploymentCreateResponse, type DeploymentCreateParams } from './deployments'; +export { + Invocations, + type InvocationCreateResponse, + type InvocationRetrieveResponse, + type InvocationCreateParams, +} from './invocations'; diff --git a/src/resources/apps/invocations.ts b/src/resources/apps/invocations.ts new file mode 100644 index 00000000..fee4db3e --- /dev/null +++ b/src/resources/apps/invocations.ts @@ -0,0 +1,140 @@ +// 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 { RequestOptions } from '../../internal/request-options'; +import { path } from '../../internal/utils/path'; + +export class Invocations extends APIResource { + /** + * Invoke an application + * + * @example + * ```ts + * const invocation = await client.apps.invocations.create({ + * action_name: 'analyze', + * app_name: 'my-app', + * version: '1.0.0', + * }); + * ``` + */ + create(body: InvocationCreateParams, options?: RequestOptions): APIPromise { + return this._client.post('/invocations', { body, ...options }); + } + + /** + * Get an app invocation by id + * + * @example + * ```ts + * const invocation = await client.apps.invocations.retrieve( + * 'ckqwer3o20000jb9s7abcdef', + * ); + * ``` + */ + retrieve(id: string, options?: RequestOptions): APIPromise { + return this._client.get(path`/invocations/${id}`, options); + } +} + +export interface InvocationCreateResponse { + /** + * ID of the invocation + */ + id: string; + + /** + * Status of the invocation + */ + status: 'queued' | 'running' | 'succeeded' | 'failed'; + + /** + * The return value of the action that was invoked, rendered as a JSON string. This + * could be: string, number, boolean, array, object, or null. + */ + output?: string; + + /** + * Status reason + */ + status_reason?: string; +} + +export interface InvocationRetrieveResponse { + /** + * ID of the invocation + */ + id: string; + + /** + * Name of the action invoked + */ + action_name: string; + + /** + * Name of the application + */ + app_name: string; + + /** + * RFC 3339 Nanoseconds timestamp when the invocation started + */ + started_at: string; + + /** + * Status of the invocation + */ + status: 'queued' | 'running' | 'succeeded' | 'failed'; + + /** + * RFC 3339 Nanoseconds timestamp when the invocation finished (null if still + * running) + */ + finished_at?: string | null; + + /** + * Output produced by the action, rendered as a JSON string. This could be: string, + * number, boolean, array, object, or null. + */ + output?: string; + + /** + * Payload provided to the invocation. This is a string that can be parsed as JSON. + */ + payload?: string; + + /** + * Status reason + */ + status_reason?: string; +} + +export interface InvocationCreateParams { + /** + * Name of the action to invoke + */ + action_name: string; + + /** + * Name of the application + */ + app_name: string; + + /** + * Version of the application + */ + version: string; + + /** + * Input data for the action, sent as a JSON string. + */ + payload?: string; +} + +export declare namespace Invocations { + export { + type InvocationCreateResponse as InvocationCreateResponse, + type InvocationRetrieveResponse as InvocationRetrieveResponse, + type InvocationCreateParams as InvocationCreateParams, + }; +} diff --git a/src/resources/browser.ts b/src/resources/browser.ts deleted file mode 100644 index 2b434f57..00000000 --- a/src/resources/browser.ts +++ /dev/null @@ -1,48 +0,0 @@ -// 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 { RequestOptions } from '../internal/request-options'; - -export class Browser extends APIResource { - /** - * Create Browser Session - */ - createSession( - body: BrowserCreateSessionParams, - options?: RequestOptions, - ): APIPromise { - return this._client.post('/browser', { body, ...options }); - } -} - -export interface BrowserCreateSessionResponse { - /** - * Websocket URL for Chrome DevTools Protocol connections to the browser session - */ - cdp_ws_url: string; - - /** - * Remote URL for live viewing the browser session - */ - remote_url: string; - - /** - * Unique identifier for the browser session - */ - sessionId: string; -} - -export interface BrowserCreateSessionParams { - /** - * Kernel App invocation ID - */ - invocationId: string; -} - -export declare namespace Browser { - export { - type BrowserCreateSessionResponse as BrowserCreateSessionResponse, - type BrowserCreateSessionParams as BrowserCreateSessionParams, - }; -} diff --git a/src/resources/browsers.ts b/src/resources/browsers.ts new file mode 100644 index 00000000..febb6d11 --- /dev/null +++ b/src/resources/browsers.ts @@ -0,0 +1,85 @@ +// 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 { RequestOptions } from '../internal/request-options'; +import { path } from '../internal/utils/path'; + +export class Browsers extends APIResource { + /** + * Create Browser Session + * + * @example + * ```ts + * const browser = await client.browsers.create({ + * invocation_id: 'ckqwer3o20000jb9s7abcdef', + * }); + * ``` + */ + create(body: BrowserCreateParams, options?: RequestOptions): APIPromise { + return this._client.post('/browsers', { body, ...options }); + } + + /** + * Get Browser Session by ID + * + * @example + * ```ts + * const browser = await client.browsers.retrieve( + * 'e5bf36fe-9247-4e2b-8b5a-2f594cc1c073', + * ); + * ``` + */ + retrieve(id: string, options?: RequestOptions): APIPromise { + return this._client.get(path`/browsers/${id}`, options); + } +} + +export interface BrowserCreateResponse { + /** + * Remote URL for live viewing the browser session + */ + browser_live_view_url: string; + + /** + * Websocket URL for Chrome DevTools Protocol connections to the browser session + */ + cdp_ws_url: string; + + /** + * Unique identifier for the browser session + */ + session_id: string; +} + +export interface BrowserRetrieveResponse { + /** + * Remote URL for live viewing the browser session + */ + browser_live_view_url: string; + + /** + * Websocket URL for Chrome DevTools Protocol connections to the browser session + */ + cdp_ws_url: string; + + /** + * Unique identifier for the browser session + */ + session_id: string; +} + +export interface BrowserCreateParams { + /** + * action invocation ID + */ + invocation_id: string; +} + +export declare namespace Browsers { + export { + type BrowserCreateResponse as BrowserCreateResponse, + type BrowserRetrieveResponse as BrowserRetrieveResponse, + type BrowserCreateParams as BrowserCreateParams, + }; +} diff --git a/src/resources/index.ts b/src/resources/index.ts index bf366e62..d8d49aef 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -1,11 +1,9 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +export { Apps } from './apps/apps'; export { - Apps, - type AppDeployResponse, - type AppInvokeResponse, - type AppRetrieveInvocationResponse, - type AppDeployParams, - type AppInvokeParams, -} from './apps'; -export { Browser, type BrowserCreateSessionResponse, type BrowserCreateSessionParams } from './browser'; + Browsers, + type BrowserCreateResponse, + type BrowserRetrieveResponse, + type BrowserCreateParams, +} from './browsers'; diff --git a/tests/api-resources/apps.test.ts b/tests/api-resources/apps.test.ts deleted file mode 100644 index 974e97b6..00000000 --- a/tests/api-resources/apps.test.ts +++ /dev/null @@ -1,75 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import Kernel, { toFile } 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 apps', () => { - // skipped: tests are disabled for the time being - test.skip('deploy: only required params', async () => { - const responsePromise = client.apps.deploy({ - entrypointRelPath: 'app.py', - file: await toFile(Buffer.from('# my file contents'), 'README.md'), - }); - 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('deploy: required and optional params', async () => { - const response = await client.apps.deploy({ - entrypointRelPath: 'app.py', - file: await toFile(Buffer.from('# my file contents'), 'README.md'), - force: 'false', - region: 'aws.us-east-1a', - version: '1.0.0', - }); - }); - - // skipped: tests are disabled for the time being - test.skip('invoke: only required params', async () => { - const responsePromise = client.apps.invoke({ - actionName: 'analyze', - appName: 'my-awesome-app', - payload: { data: 'example input' }, - version: '1.0.0', - }); - 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('invoke: required and optional params', async () => { - const response = await client.apps.invoke({ - actionName: 'analyze', - appName: 'my-awesome-app', - payload: { data: 'example input' }, - version: '1.0.0', - }); - }); - - // skipped: tests are disabled for the time being - test.skip('retrieveInvocation', async () => { - const responsePromise = client.apps.retrieveInvocation('ckqwer3o20000jb9s7abcdef'); - 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); - }); -}); diff --git a/tests/api-resources/browser.test.ts b/tests/api-resources/apps/deployments.test.ts similarity index 52% rename from tests/api-resources/browser.test.ts rename to tests/api-resources/apps/deployments.test.ts index 012e207c..5e6c43c2 100644 --- a/tests/api-resources/browser.test.ts +++ b/tests/api-resources/apps/deployments.test.ts @@ -1,16 +1,19 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Kernel from '@onkernel/sdk'; +import Kernel, { toFile } 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 browser', () => { +describe('resource deployments', () => { // skipped: tests are disabled for the time being - test.skip('createSession: only required params', async () => { - const responsePromise = client.browser.createSession({ invocationId: 'invocationId' }); + test.skip('create: only required params', async () => { + const responsePromise = client.apps.deployments.create({ + entrypoint_rel_path: 'src/app.py', + file: await toFile(Buffer.from('# my file contents'), 'README.md'), + }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -21,7 +24,13 @@ describe('resource browser', () => { }); // skipped: tests are disabled for the time being - test.skip('createSession: required and optional params', async () => { - const response = await client.browser.createSession({ invocationId: 'invocationId' }); + test.skip('create: required and optional params', async () => { + const response = await client.apps.deployments.create({ + entrypoint_rel_path: 'src/app.py', + file: await toFile(Buffer.from('# my file contents'), 'README.md'), + force: false, + region: 'aws.us-east-1a', + version: '1.0.0', + }); }); }); diff --git a/tests/api-resources/apps/invocations.test.ts b/tests/api-resources/apps/invocations.test.ts new file mode 100644 index 00000000..3bafc763 --- /dev/null +++ b/tests/api-resources/apps/invocations.test.ts @@ -0,0 +1,48 @@ +// 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 invocations', () => { + // skipped: tests are disabled for the time being + test.skip('create: only required params', async () => { + const responsePromise = client.apps.invocations.create({ + action_name: 'analyze', + app_name: 'my-app', + version: '1.0.0', + }); + 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('create: required and optional params', async () => { + const response = await client.apps.invocations.create({ + action_name: 'analyze', + app_name: 'my-app', + version: '1.0.0', + payload: '{"data":"example input"}', + }); + }); + + // skipped: tests are disabled for the time being + test.skip('retrieve', async () => { + const responsePromise = client.apps.invocations.retrieve('ckqwer3o20000jb9s7abcdef'); + 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); + }); +}); diff --git a/tests/api-resources/browsers.test.ts b/tests/api-resources/browsers.test.ts new file mode 100644 index 00000000..72349779 --- /dev/null +++ b/tests/api-resources/browsers.test.ts @@ -0,0 +1,39 @@ +// 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 browsers', () => { + // skipped: tests are disabled for the time being + test.skip('create: only required params', async () => { + const responsePromise = client.browsers.create({ invocation_id: 'ckqwer3o20000jb9s7abcdef' }); + 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('create: required and optional params', async () => { + const response = await client.browsers.create({ invocation_id: 'ckqwer3o20000jb9s7abcdef' }); + }); + + // skipped: tests are disabled for the time being + test.skip('retrieve', async () => { + const responsePromise = client.browsers.retrieve('e5bf36fe-9247-4e2b-8b5a-2f594cc1c073'); + 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); + }); +}); From 5ab6e59b767aba3b4a05103f66cacd11441f9f2e Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 19 May 2025 18:55:01 +0000 Subject: [PATCH 026/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 931fce1a..acba45e0 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.1.0-alpha.10" + ".": "0.1.0-alpha.11" } diff --git a/package.json b/package.json index dacc7bed..fc5f0a78 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.1.0-alpha.10", + "version": "0.1.0-alpha.11", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 5ed52cd1..51a202a4 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.1.0-alpha.10'; // x-release-please-version +export const VERSION = '0.1.0-alpha.11'; // x-release-please-version From 94f17dc15c9aae2cd20fac638a7141db74afe926 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 19 May 2025 19:44:20 +0000 Subject: [PATCH 027/551] feat(api): update via SDK Studio --- .stats.yml | 4 ++-- src/resources/apps/deployments.ts | 6 ++++++ tests/api-resources/apps/deployments.test.ts | 1 + 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 6f21bcbb..24b7a04f 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 5 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-f40e779e2a48f5e37361f2f4a9879e5c40f2851b8033c23db69ec7b91242bf69.yml -openapi_spec_hash: 2dfa146149e61363f1ec40bf9251eb7c +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-1fe396b957ced73281fc0a61a69b630836aa5c89a8dccce2c5a1716bc9775e80.yml +openapi_spec_hash: 9a0d67fb0781be034b77839584109638 config_hash: 2ddaa85513b6670889b1a56c905423c7 diff --git a/src/resources/apps/deployments.ts b/src/resources/apps/deployments.ts index abd96550..78a1c4d4 100644 --- a/src/resources/apps/deployments.ts +++ b/src/resources/apps/deployments.ts @@ -79,6 +79,12 @@ export interface DeploymentCreateParams { */ file: Uploadable; + /** + * Map of environment variables to set for the deployed application. Each key-value + * pair represents an environment variable. + */ + env_vars?: Record; + /** * Allow overwriting an existing app version */ diff --git a/tests/api-resources/apps/deployments.test.ts b/tests/api-resources/apps/deployments.test.ts index 5e6c43c2..f5762372 100644 --- a/tests/api-resources/apps/deployments.test.ts +++ b/tests/api-resources/apps/deployments.test.ts @@ -28,6 +28,7 @@ describe('resource deployments', () => { const response = await client.apps.deployments.create({ entrypoint_rel_path: 'src/app.py', file: await toFile(Buffer.from('# my file contents'), 'README.md'), + env_vars: { foo: 'string' }, force: false, region: 'aws.us-east-1a', version: '1.0.0', From df3b19a8500a5f5579afee8119368e182158763a Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 19 May 2025 19:47:40 +0000 Subject: [PATCH 028/551] feat(api): update via SDK Studio --- .stats.yml | 2 +- README.md | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index 24b7a04f..4dfbf428 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 5 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-1fe396b957ced73281fc0a61a69b630836aa5c89a8dccce2c5a1716bc9775e80.yml openapi_spec_hash: 9a0d67fb0781be034b77839584109638 -config_hash: 2ddaa85513b6670889b1a56c905423c7 +config_hash: df889df131f7438197abd59faace3c77 diff --git a/README.md b/README.md index 86b14266..d9930749 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,7 @@ async function main() { const deployment = await client.apps.deployments.create({ entrypoint_rel_path: 'main.ts', file: fs.createReadStream('path/to/file'), + env_vars: { OPENAI_API_KEY: 'x' }, version: '1.0.0', }); From c570007f04a1a6dec6c8e37f8984b4b1a59a0628 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 19 May 2025 19:48:50 +0000 Subject: [PATCH 029/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index acba45e0..a0ad4167 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.1.0-alpha.11" + ".": "0.1.0-alpha.12" } diff --git a/package.json b/package.json index fc5f0a78..8534ef83 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.1.0-alpha.11", + "version": "0.1.0-alpha.12", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 51a202a4..de5a5a58 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.1.0-alpha.11'; // x-release-please-version +export const VERSION = '0.1.0-alpha.12'; // x-release-please-version From 880ffcb36264c42bf9406ecfa422dc6ddda4e9c4 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 19 May 2025 20:44:45 +0000 Subject: [PATCH 030/551] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 4dfbf428..6d03c395 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 5 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-1fe396b957ced73281fc0a61a69b630836aa5c89a8dccce2c5a1716bc9775e80.yml -openapi_spec_hash: 9a0d67fb0781be034b77839584109638 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-3b19f5e2b96ede3193aa7a24d3f82d1406b8a16ea25e98ba3956e4a1a2376ad7.yml +openapi_spec_hash: b62a6e73ddcec71674973f795a5790ac config_hash: df889df131f7438197abd59faace3c77 From 0fd9196c2ccd62ba89e727646ae16ac94a23aaad Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 19 May 2025 20:48:10 +0000 Subject: [PATCH 031/551] feat(api): update via SDK Studio --- .stats.yml | 8 +- api.md | 2 + src/core/streaming.ts | 301 +++++++++++++++++++ src/internal/decoders/line.ts | 135 +++++++++ src/internal/parse.ts | 14 + src/internal/request-options.ts | 2 + src/resources/apps/apps.ts | 8 +- src/resources/apps/deployments.ts | 93 ++++++ src/resources/apps/index.ts | 7 +- src/streaming.ts | 2 + tests/api-resources/apps/deployments.test.ts | 12 + tests/internal/decoders/line.test.ts | 128 ++++++++ tests/streaming.test.ts | 219 ++++++++++++++ 13 files changed, 925 insertions(+), 6 deletions(-) create mode 100644 src/core/streaming.ts create mode 100644 src/internal/decoders/line.ts create mode 100644 src/streaming.ts create mode 100644 tests/internal/decoders/line.test.ts create mode 100644 tests/streaming.test.ts diff --git a/.stats.yml b/.stats.yml index 6d03c395..01f342cf 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 5 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-3b19f5e2b96ede3193aa7a24d3f82d1406b8a16ea25e98ba3956e4a1a2376ad7.yml -openapi_spec_hash: b62a6e73ddcec71674973f795a5790ac -config_hash: df889df131f7438197abd59faace3c77 +configured_endpoints: 6 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-19b0d17ba368f32827ee322d15a7f4ff7e1f3bbf66606fad227b3465f8ffc5ab.yml +openapi_spec_hash: 4a3cb766898e8a134ef99fe6c4c87736 +config_hash: 9018b7ff17f8de1bc3e99a0ae2f2df68 diff --git a/api.md b/api.md index 1fc97fdc..d53f92ec 100644 --- a/api.md +++ b/api.md @@ -5,10 +5,12 @@ Types: - DeploymentCreateResponse +- DeploymentFollowResponse Methods: - client.apps.deployments.create({ ...params }) -> DeploymentCreateResponse +- client.apps.deployments.follow(id) -> DeploymentFollowResponse ## Invocations diff --git a/src/core/streaming.ts b/src/core/streaming.ts new file mode 100644 index 00000000..7191ee4c --- /dev/null +++ b/src/core/streaming.ts @@ -0,0 +1,301 @@ +import { KernelError } from './error'; +import { type ReadableStream } from '../internal/shim-types'; +import { makeReadableStream } from '../internal/shims'; +import { findDoubleNewlineIndex, LineDecoder } from '../internal/decoders/line'; +import { ReadableStreamToAsyncIterable } from '../internal/shims'; +import { isAbortError } from '../internal/errors'; +import { encodeUTF8 } from '../internal/utils/bytes'; + +type Bytes = string | ArrayBuffer | Uint8Array | null | undefined; + +export type ServerSentEvent = { + event: string | null; + data: string; + raw: string[]; +}; + +export class Stream implements AsyncIterable { + controller: AbortController; + + constructor( + private iterator: () => AsyncIterator, + controller: AbortController, + ) { + this.controller = controller; + } + + static fromSSEResponse(response: Response, controller: AbortController): Stream { + let consumed = false; + + async function* iterator(): AsyncIterator { + if (consumed) { + throw new KernelError('Cannot iterate over a consumed stream, use `.tee()` to split the stream.'); + } + consumed = true; + let done = false; + try { + for await (const sse of _iterSSEMessages(response, controller)) { + try { + yield JSON.parse(sse.data); + } catch (e) { + console.error(`Could not parse message into JSON:`, sse.data); + console.error(`From chunk:`, sse.raw); + throw e; + } + } + done = true; + } catch (e) { + // If the user calls `stream.controller.abort()`, we should exit without throwing. + if (isAbortError(e)) return; + throw e; + } finally { + // If the user `break`s, abort the ongoing request. + if (!done) controller.abort(); + } + } + + return new Stream(iterator, controller); + } + + /** + * Generates a Stream from a newline-separated ReadableStream + * where each item is a JSON value. + */ + static fromReadableStream(readableStream: ReadableStream, controller: AbortController): Stream { + let consumed = false; + + async function* iterLines(): AsyncGenerator { + const lineDecoder = new LineDecoder(); + + const iter = ReadableStreamToAsyncIterable(readableStream); + for await (const chunk of iter) { + for (const line of lineDecoder.decode(chunk)) { + yield line; + } + } + + for (const line of lineDecoder.flush()) { + yield line; + } + } + + async function* iterator(): AsyncIterator { + if (consumed) { + throw new KernelError('Cannot iterate over a consumed stream, use `.tee()` to split the stream.'); + } + consumed = true; + let done = false; + try { + for await (const line of iterLines()) { + if (done) continue; + if (line) yield JSON.parse(line); + } + done = true; + } catch (e) { + // If the user calls `stream.controller.abort()`, we should exit without throwing. + if (isAbortError(e)) return; + throw e; + } finally { + // If the user `break`s, abort the ongoing request. + if (!done) controller.abort(); + } + } + + return new Stream(iterator, controller); + } + + [Symbol.asyncIterator](): AsyncIterator { + return this.iterator(); + } + + /** + * Splits the stream into two streams which can be + * independently read from at different speeds. + */ + tee(): [Stream, Stream] { + const left: Array>> = []; + const right: Array>> = []; + const iterator = this.iterator(); + + const teeIterator = (queue: Array>>): AsyncIterator => { + return { + next: () => { + if (queue.length === 0) { + const result = iterator.next(); + left.push(result); + right.push(result); + } + return queue.shift()!; + }, + }; + }; + + return [ + new Stream(() => teeIterator(left), this.controller), + new Stream(() => teeIterator(right), this.controller), + ]; + } + + /** + * Converts this stream to a newline-separated ReadableStream of + * JSON stringified values in the stream + * which can be turned back into a Stream with `Stream.fromReadableStream()`. + */ + toReadableStream(): ReadableStream { + const self = this; + let iter: AsyncIterator; + + return makeReadableStream({ + async start() { + iter = self[Symbol.asyncIterator](); + }, + async pull(ctrl: any) { + try { + const { value, done } = await iter.next(); + if (done) return ctrl.close(); + + const bytes = encodeUTF8(JSON.stringify(value) + '\n'); + + ctrl.enqueue(bytes); + } catch (err) { + ctrl.error(err); + } + }, + async cancel() { + await iter.return?.(); + }, + }); + } +} + +export async function* _iterSSEMessages( + response: Response, + controller: AbortController, +): AsyncGenerator { + if (!response.body) { + controller.abort(); + if ( + typeof (globalThis as any).navigator !== 'undefined' && + (globalThis as any).navigator.product === 'ReactNative' + ) { + throw new KernelError( + `The default react-native fetch implementation does not support streaming. Please use expo/fetch: https://docs.expo.dev/versions/latest/sdk/expo/#expofetch-api`, + ); + } + throw new KernelError(`Attempted to iterate over a response with no body`); + } + + const sseDecoder = new SSEDecoder(); + const lineDecoder = new LineDecoder(); + + const iter = ReadableStreamToAsyncIterable(response.body); + for await (const sseChunk of iterSSEChunks(iter)) { + for (const line of lineDecoder.decode(sseChunk)) { + const sse = sseDecoder.decode(line); + if (sse) yield sse; + } + } + + for (const line of lineDecoder.flush()) { + const sse = sseDecoder.decode(line); + if (sse) yield sse; + } +} + +/** + * Given an async iterable iterator, iterates over it and yields full + * SSE chunks, i.e. yields when a double new-line is encountered. + */ +async function* iterSSEChunks(iterator: AsyncIterableIterator): AsyncGenerator { + let data = new Uint8Array(); + + for await (const chunk of iterator) { + if (chunk == null) { + continue; + } + + const binaryChunk = + chunk instanceof ArrayBuffer ? new Uint8Array(chunk) + : typeof chunk === 'string' ? encodeUTF8(chunk) + : chunk; + + let newData = new Uint8Array(data.length + binaryChunk.length); + newData.set(data); + newData.set(binaryChunk, data.length); + data = newData; + + let patternIndex; + while ((patternIndex = findDoubleNewlineIndex(data)) !== -1) { + yield data.slice(0, patternIndex); + data = data.slice(patternIndex); + } + } + + if (data.length > 0) { + yield data; + } +} + +class SSEDecoder { + private data: string[]; + private event: string | null; + private chunks: string[]; + + constructor() { + this.event = null; + this.data = []; + this.chunks = []; + } + + decode(line: string) { + if (line.endsWith('\r')) { + line = line.substring(0, line.length - 1); + } + + if (!line) { + // empty line and we didn't previously encounter any messages + if (!this.event && !this.data.length) return null; + + const sse: ServerSentEvent = { + event: this.event, + data: this.data.join('\n'), + raw: this.chunks, + }; + + this.event = null; + this.data = []; + this.chunks = []; + + return sse; + } + + this.chunks.push(line); + + if (line.startsWith(':')) { + return null; + } + + let [fieldname, _, value] = partition(line, ':'); + + if (value.startsWith(' ')) { + value = value.substring(1); + } + + if (fieldname === 'event') { + this.event = value; + } else if (fieldname === 'data') { + this.data.push(value); + } + + return null; + } +} + +function partition(str: string, delimiter: string): [string, string, string] { + const index = str.indexOf(delimiter); + if (index !== -1) { + return [str.substring(0, index), delimiter, str.substring(index + delimiter.length)]; + } + + return [str, '', '']; +} diff --git a/src/internal/decoders/line.ts b/src/internal/decoders/line.ts new file mode 100644 index 00000000..b3bfa97c --- /dev/null +++ b/src/internal/decoders/line.ts @@ -0,0 +1,135 @@ +import { concatBytes, decodeUTF8, encodeUTF8 } from '../utils/bytes'; + +export type Bytes = string | ArrayBuffer | Uint8Array | null | undefined; + +/** + * A re-implementation of httpx's `LineDecoder` in Python that handles incrementally + * reading lines from text. + * + * https://github.com/encode/httpx/blob/920333ea98118e9cf617f246905d7b202510941c/httpx/_decoders.py#L258 + */ +export class LineDecoder { + // prettier-ignore + static NEWLINE_CHARS = new Set(['\n', '\r']); + static NEWLINE_REGEXP = /\r\n|[\n\r]/g; + + #buffer: Uint8Array; + #carriageReturnIndex: number | null; + + constructor() { + this.#buffer = new Uint8Array(); + this.#carriageReturnIndex = null; + } + + decode(chunk: Bytes): string[] { + if (chunk == null) { + return []; + } + + const binaryChunk = + chunk instanceof ArrayBuffer ? new Uint8Array(chunk) + : typeof chunk === 'string' ? encodeUTF8(chunk) + : chunk; + + this.#buffer = concatBytes([this.#buffer, binaryChunk]); + + const lines: string[] = []; + let patternIndex; + while ((patternIndex = findNewlineIndex(this.#buffer, this.#carriageReturnIndex)) != null) { + if (patternIndex.carriage && this.#carriageReturnIndex == null) { + // skip until we either get a corresponding `\n`, a new `\r` or nothing + this.#carriageReturnIndex = patternIndex.index; + continue; + } + + // we got double \r or \rtext\n + if ( + this.#carriageReturnIndex != null && + (patternIndex.index !== this.#carriageReturnIndex + 1 || patternIndex.carriage) + ) { + lines.push(decodeUTF8(this.#buffer.subarray(0, this.#carriageReturnIndex - 1))); + this.#buffer = this.#buffer.subarray(this.#carriageReturnIndex); + this.#carriageReturnIndex = null; + continue; + } + + const endIndex = + this.#carriageReturnIndex !== null ? patternIndex.preceding - 1 : patternIndex.preceding; + + const line = decodeUTF8(this.#buffer.subarray(0, endIndex)); + lines.push(line); + + this.#buffer = this.#buffer.subarray(patternIndex.index); + this.#carriageReturnIndex = null; + } + + return lines; + } + + flush(): string[] { + if (!this.#buffer.length) { + return []; + } + return this.decode('\n'); + } +} + +/** + * This function searches the buffer for the end patterns, (\r or \n) + * and returns an object with the index preceding the matched newline and the + * index after the newline char. `null` is returned if no new line is found. + * + * ```ts + * findNewLineIndex('abc\ndef') -> { preceding: 2, index: 3 } + * ``` + */ +function findNewlineIndex( + buffer: Uint8Array, + startIndex: number | null, +): { preceding: number; index: number; carriage: boolean } | null { + const newline = 0x0a; // \n + const carriage = 0x0d; // \r + + for (let i = startIndex ?? 0; i < buffer.length; i++) { + if (buffer[i] === newline) { + return { preceding: i, index: i + 1, carriage: false }; + } + + if (buffer[i] === carriage) { + return { preceding: i, index: i + 1, carriage: true }; + } + } + + return null; +} + +export function findDoubleNewlineIndex(buffer: Uint8Array): number { + // This function searches the buffer for the end patterns (\r\r, \n\n, \r\n\r\n) + // and returns the index right after the first occurrence of any pattern, + // or -1 if none of the patterns are found. + const newline = 0x0a; // \n + const carriage = 0x0d; // \r + + for (let i = 0; i < buffer.length - 1; i++) { + if (buffer[i] === newline && buffer[i + 1] === newline) { + // \n\n + return i + 2; + } + if (buffer[i] === carriage && buffer[i + 1] === carriage) { + // \r\r + return i + 2; + } + if ( + buffer[i] === carriage && + buffer[i + 1] === newline && + i + 3 < buffer.length && + buffer[i + 2] === carriage && + buffer[i + 3] === newline + ) { + // \r\n\r\n + return i + 4; + } + } + + return -1; +} diff --git a/src/internal/parse.ts b/src/internal/parse.ts index 53d4b80c..18d0b41f 100644 --- a/src/internal/parse.ts +++ b/src/internal/parse.ts @@ -1,6 +1,7 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. import type { FinalRequestOptions } from './request-options'; +import { Stream } from '../core/streaming'; import { type Kernel } from '../client'; import { formatRequestDetails, loggerFor } from './utils/log'; @@ -16,6 +17,19 @@ export type APIResponseProps = { export async function defaultParseResponse(client: Kernel, props: APIResponseProps): Promise { const { response, requestLogID, retryOfRequestLogID, startTime } = props; const body = await (async () => { + if (props.options.stream) { + loggerFor(client).debug('response', response.status, response.url, response.headers, response.body); + + // Note: there is an invariant here that isn't represented in the type system + // 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 Stream.fromSSEResponse(response, props.controller) as any; + } + // fetch refuses to read the body when the status code is 204. if (response.status === 204) { return null as T; diff --git a/src/internal/request-options.ts b/src/internal/request-options.ts index d2ade9ec..ef099310 100644 --- a/src/internal/request-options.ts +++ b/src/internal/request-options.ts @@ -3,6 +3,7 @@ import { NullableHeaders } from './headers'; import type { BodyInit } from './builtin-types'; +import { Stream } from '../core/streaming'; import type { HTTPMethod, MergedRequestInit } from './types'; import { type HeadersLike } from './headers'; @@ -22,6 +23,7 @@ export type RequestOptions = { idempotencyKey?: string; __binaryResponse?: boolean | undefined; + __streamClass?: typeof Stream; }; export type EncodedContent = { bodyHeaders: HeadersLike; body: BodyInit }; diff --git a/src/resources/apps/apps.ts b/src/resources/apps/apps.ts index fe32c1ee..29434998 100644 --- a/src/resources/apps/apps.ts +++ b/src/resources/apps/apps.ts @@ -2,7 +2,12 @@ import { APIResource } from '../../core/resource'; import * as DeploymentsAPI from './deployments'; -import { DeploymentCreateParams, DeploymentCreateResponse, Deployments } from './deployments'; +import { + DeploymentCreateParams, + DeploymentCreateResponse, + DeploymentFollowResponse, + Deployments, +} from './deployments'; import * as InvocationsAPI from './invocations'; import { InvocationCreateParams, @@ -23,6 +28,7 @@ export declare namespace Apps { export { Deployments as Deployments, type DeploymentCreateResponse as DeploymentCreateResponse, + type DeploymentFollowResponse as DeploymentFollowResponse, type DeploymentCreateParams as DeploymentCreateParams, }; diff --git a/src/resources/apps/deployments.ts b/src/resources/apps/deployments.ts index 78a1c4d4..e4b7811e 100644 --- a/src/resources/apps/deployments.ts +++ b/src/resources/apps/deployments.ts @@ -2,9 +2,12 @@ import { APIResource } from '../../core/resource'; import { APIPromise } from '../../core/api-promise'; +import { Stream } from '../../core/streaming'; import { type Uploadable } from '../../core/uploads'; +import { buildHeaders } from '../../internal/headers'; import { RequestOptions } from '../../internal/request-options'; import { multipartFormRequestOptions } from '../../internal/uploads'; +import { path } from '../../internal/utils/path'; export class Deployments extends APIResource { /** @@ -21,6 +24,24 @@ export class Deployments extends APIResource { create(body: DeploymentCreateParams, options?: RequestOptions): APIPromise { return this._client.post('/deploy', multipartFormRequestOptions({ body, ...options }, this._client)); } + + /** + * Establishes a Server-Sent Events (SSE) stream that delivers real-time logs and + * status updates for a deployed application. The stream terminates automatically + * once the application reaches a terminal state. + * + * @example + * ```ts + * const response = await client.apps.deployments.follow('id'); + * ``` + */ + follow(id: string, options?: RequestOptions): APIPromise> { + return this._client.get(path`/apps/${id}/events`, { + ...options, + headers: buildHeaders([{ Accept: 'text/event-stream' }, options?.headers]), + stream: true, + }) as APIPromise>; + } } export interface DeploymentCreateResponse { @@ -68,6 +89,77 @@ export namespace DeploymentCreateResponse { } } +/** + * A stream of application events (state updates and logs) in SSE format. + */ +export type DeploymentFollowResponse = Array< + | DeploymentFollowResponse.StateEvent + | DeploymentFollowResponse.StateUpdateEvent + | DeploymentFollowResponse.LogEvent +>; + +export namespace DeploymentFollowResponse { + /** + * Initial state of the application, emitted once when subscribing. + */ + export interface StateEvent { + /** + * Event type identifier (always "state"). + */ + event: 'state'; + + /** + * Current application state (e.g., "deploying", "running", "succeeded", "failed"). + */ + state: string; + + /** + * Time the state was reported. + */ + timestamp?: string; + } + + /** + * An update emitted when the application's state changes. + */ + export interface StateUpdateEvent { + /** + * Event type identifier (always "state_update"). + */ + event: 'state_update'; + + /** + * New application state (e.g., "running", "succeeded", "failed"). + */ + state: string; + + /** + * Time the state change occurred. + */ + timestamp?: string; + } + + /** + * A log entry from the application. + */ + export interface LogEvent { + /** + * Event type identifier (always "log"). + */ + event: 'log'; + + /** + * Log message text. + */ + message: string; + + /** + * Time the log entry was produced. + */ + timestamp?: string; + } +} + export interface DeploymentCreateParams { /** * Relative path to the entrypoint of the application @@ -104,6 +196,7 @@ export interface DeploymentCreateParams { export declare namespace Deployments { export { type DeploymentCreateResponse as DeploymentCreateResponse, + type DeploymentFollowResponse as DeploymentFollowResponse, type DeploymentCreateParams as DeploymentCreateParams, }; } diff --git a/src/resources/apps/index.ts b/src/resources/apps/index.ts index 1703ae2c..c2215c03 100644 --- a/src/resources/apps/index.ts +++ b/src/resources/apps/index.ts @@ -1,7 +1,12 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. export { Apps } from './apps'; -export { Deployments, type DeploymentCreateResponse, type DeploymentCreateParams } from './deployments'; +export { + Deployments, + type DeploymentCreateResponse, + type DeploymentFollowResponse, + type DeploymentCreateParams, +} from './deployments'; export { Invocations, type InvocationCreateResponse, diff --git a/src/streaming.ts b/src/streaming.ts new file mode 100644 index 00000000..9e6da106 --- /dev/null +++ b/src/streaming.ts @@ -0,0 +1,2 @@ +/** @deprecated Import from ./core/streaming instead */ +export * from './core/streaming'; diff --git a/tests/api-resources/apps/deployments.test.ts b/tests/api-resources/apps/deployments.test.ts index f5762372..79781984 100644 --- a/tests/api-resources/apps/deployments.test.ts +++ b/tests/api-resources/apps/deployments.test.ts @@ -34,4 +34,16 @@ describe('resource deployments', () => { version: '1.0.0', }); }); + + // skipped: currently no good way to test endpoints with content type text/event-stream, Prism mock server will fail + test.skip('follow', async () => { + const responsePromise = client.apps.deployments.follow('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); + }); }); diff --git a/tests/internal/decoders/line.test.ts b/tests/internal/decoders/line.test.ts new file mode 100644 index 00000000..11466788 --- /dev/null +++ b/tests/internal/decoders/line.test.ts @@ -0,0 +1,128 @@ +import { findDoubleNewlineIndex, LineDecoder } from '@onkernel/sdk/internal/decoders/line'; + +function decodeChunks(chunks: string[], { flush }: { flush: boolean } = { flush: false }): string[] { + const decoder = new LineDecoder(); + const lines: string[] = []; + for (const chunk of chunks) { + lines.push(...decoder.decode(chunk)); + } + + if (flush) { + lines.push(...decoder.flush()); + } + + return lines; +} + +describe('line decoder', () => { + test('basic', () => { + // baz is not included because the line hasn't ended yet + expect(decodeChunks(['foo', ' bar\nbaz'])).toEqual(['foo bar']); + }); + + test('basic with \\r', () => { + expect(decodeChunks(['foo', ' bar\r\nbaz'])).toEqual(['foo bar']); + expect(decodeChunks(['foo', ' bar\r\nbaz'], { flush: true })).toEqual(['foo bar', 'baz']); + }); + + test('trailing new lines', () => { + expect(decodeChunks(['foo', ' bar', 'baz\n', 'thing\n'])).toEqual(['foo barbaz', 'thing']); + }); + + test('trailing new lines with \\r', () => { + expect(decodeChunks(['foo', ' bar', 'baz\r\n', 'thing\r\n'])).toEqual(['foo barbaz', 'thing']); + }); + + test('escaped new lines', () => { + expect(decodeChunks(['foo', ' bar\\nbaz\n'])).toEqual(['foo bar\\nbaz']); + }); + + test('escaped new lines with \\r', () => { + expect(decodeChunks(['foo', ' bar\\r\\nbaz\n'])).toEqual(['foo bar\\r\\nbaz']); + }); + + test('\\r & \\n split across multiple chunks', () => { + expect(decodeChunks(['foo\r', '\n', 'bar'], { flush: true })).toEqual(['foo', 'bar']); + }); + + test('single \\r', () => { + expect(decodeChunks(['foo\r', 'bar'], { flush: true })).toEqual(['foo', 'bar']); + }); + + test('double \\r', () => { + expect(decodeChunks(['foo\r', 'bar\r'], { flush: true })).toEqual(['foo', 'bar']); + expect(decodeChunks(['foo\r', '\r', 'bar'], { flush: true })).toEqual(['foo', '', 'bar']); + // implementation detail that we don't yield the single \r line until a new \r or \n is encountered + expect(decodeChunks(['foo\r', '\r', 'bar'], { flush: false })).toEqual(['foo']); + }); + + test('double \\r then \\r\\n', () => { + expect(decodeChunks(['foo\r', '\r', '\r', '\n', 'bar', '\n'])).toEqual(['foo', '', '', 'bar']); + expect(decodeChunks(['foo\n', '\n', '\n', 'bar', '\n'])).toEqual(['foo', '', '', 'bar']); + }); + + test('double newline', () => { + expect(decodeChunks(['foo\n\nbar'], { flush: true })).toEqual(['foo', '', 'bar']); + expect(decodeChunks(['foo', '\n', '\nbar'], { flush: true })).toEqual(['foo', '', 'bar']); + expect(decodeChunks(['foo\n', '\n', 'bar'], { flush: true })).toEqual(['foo', '', 'bar']); + expect(decodeChunks(['foo', '\n', '\n', 'bar'], { flush: true })).toEqual(['foo', '', 'bar']); + }); + + test('multi-byte characters across chunks', () => { + const decoder = new LineDecoder(); + + // bytes taken from the string 'известни' and arbitrarily split + // so that some multi-byte characters span multiple chunks + expect(decoder.decode(new Uint8Array([0xd0]))).toHaveLength(0); + expect(decoder.decode(new Uint8Array([0xb8, 0xd0, 0xb7, 0xd0]))).toHaveLength(0); + expect( + decoder.decode(new Uint8Array([0xb2, 0xd0, 0xb5, 0xd1, 0x81, 0xd1, 0x82, 0xd0, 0xbd, 0xd0, 0xb8])), + ).toHaveLength(0); + + const decoded = decoder.decode(new Uint8Array([0xa])); + expect(decoded).toEqual(['известни']); + }); + + test('flushing trailing newlines', () => { + expect(decodeChunks(['foo\n', '\nbar'], { flush: true })).toEqual(['foo', '', 'bar']); + }); + + test('flushing empty buffer', () => { + expect(decodeChunks([], { flush: true })).toEqual([]); + }); +}); + +describe('findDoubleNewlineIndex', () => { + test('finds \\n\\n', () => { + expect(findDoubleNewlineIndex(new TextEncoder().encode('foo\n\nbar'))).toBe(5); + expect(findDoubleNewlineIndex(new TextEncoder().encode('\n\nbar'))).toBe(2); + expect(findDoubleNewlineIndex(new TextEncoder().encode('foo\n\n'))).toBe(5); + expect(findDoubleNewlineIndex(new TextEncoder().encode('\n\n'))).toBe(2); + }); + + test('finds \\r\\r', () => { + expect(findDoubleNewlineIndex(new TextEncoder().encode('foo\r\rbar'))).toBe(5); + expect(findDoubleNewlineIndex(new TextEncoder().encode('\r\rbar'))).toBe(2); + expect(findDoubleNewlineIndex(new TextEncoder().encode('foo\r\r'))).toBe(5); + expect(findDoubleNewlineIndex(new TextEncoder().encode('\r\r'))).toBe(2); + }); + + test('finds \\r\\n\\r\\n', () => { + expect(findDoubleNewlineIndex(new TextEncoder().encode('foo\r\n\r\nbar'))).toBe(7); + expect(findDoubleNewlineIndex(new TextEncoder().encode('\r\n\r\nbar'))).toBe(4); + expect(findDoubleNewlineIndex(new TextEncoder().encode('foo\r\n\r\n'))).toBe(7); + expect(findDoubleNewlineIndex(new TextEncoder().encode('\r\n\r\n'))).toBe(4); + }); + + test('returns -1 when no double newline found', () => { + expect(findDoubleNewlineIndex(new TextEncoder().encode('foo\nbar'))).toBe(-1); + expect(findDoubleNewlineIndex(new TextEncoder().encode('foo\rbar'))).toBe(-1); + expect(findDoubleNewlineIndex(new TextEncoder().encode('foo\r\nbar'))).toBe(-1); + expect(findDoubleNewlineIndex(new TextEncoder().encode(''))).toBe(-1); + }); + + test('handles incomplete patterns', () => { + expect(findDoubleNewlineIndex(new TextEncoder().encode('foo\r\n\r'))).toBe(-1); + expect(findDoubleNewlineIndex(new TextEncoder().encode('foo\r\n'))).toBe(-1); + }); +}); diff --git a/tests/streaming.test.ts b/tests/streaming.test.ts new file mode 100644 index 00000000..0124e210 --- /dev/null +++ b/tests/streaming.test.ts @@ -0,0 +1,219 @@ +import assert from 'assert'; +import { _iterSSEMessages } from '@onkernel/sdk/core/streaming'; +import { ReadableStreamFrom } from '@onkernel/sdk/internal/shims'; + +describe('streaming decoding', () => { + test('basic', async () => { + async function* body(): AsyncGenerator { + yield Buffer.from('event: completion\n'); + yield Buffer.from('data: {"foo":true}\n'); + yield Buffer.from('\n'); + } + + const stream = _iterSSEMessages(new Response(ReadableStreamFrom(body())), new AbortController())[ + Symbol.asyncIterator + ](); + + let event = await stream.next(); + assert(event.value); + expect(JSON.parse(event.value.data)).toEqual({ foo: true }); + + event = await stream.next(); + expect(event.done).toBeTruthy(); + }); + + test('data without event', async () => { + async function* body(): AsyncGenerator { + yield Buffer.from('data: {"foo":true}\n'); + yield Buffer.from('\n'); + } + + const stream = _iterSSEMessages(new Response(ReadableStreamFrom(body())), new AbortController())[ + Symbol.asyncIterator + ](); + + let event = await stream.next(); + assert(event.value); + expect(event.value.event).toBeNull(); + expect(JSON.parse(event.value.data)).toEqual({ foo: true }); + + event = await stream.next(); + expect(event.done).toBeTruthy(); + }); + + test('event without data', async () => { + async function* body(): AsyncGenerator { + yield Buffer.from('event: foo\n'); + yield Buffer.from('\n'); + } + + const stream = _iterSSEMessages(new Response(ReadableStreamFrom(body())), new AbortController())[ + Symbol.asyncIterator + ](); + + let event = await stream.next(); + assert(event.value); + expect(event.value.event).toEqual('foo'); + expect(event.value.data).toEqual(''); + + event = await stream.next(); + expect(event.done).toBeTruthy(); + }); + + test('multiple events', async () => { + async function* body(): AsyncGenerator { + yield Buffer.from('event: foo\n'); + yield Buffer.from('\n'); + yield Buffer.from('event: ping\n'); + yield Buffer.from('\n'); + } + + const stream = _iterSSEMessages(new Response(ReadableStreamFrom(body())), new AbortController())[ + Symbol.asyncIterator + ](); + + let event = await stream.next(); + assert(event.value); + expect(event.value.event).toEqual('foo'); + expect(event.value.data).toEqual(''); + + event = await stream.next(); + assert(event.value); + expect(event.value.event).toEqual('ping'); + expect(event.value.data).toEqual(''); + + event = await stream.next(); + expect(event.done).toBeTruthy(); + }); + + test('multiple events with data', async () => { + async function* body(): AsyncGenerator { + yield Buffer.from('event: foo\n'); + yield Buffer.from('data: {"foo":true}\n'); + yield Buffer.from('\n'); + yield Buffer.from('event: ping\n'); + yield Buffer.from('data: {"bar":false}\n'); + yield Buffer.from('\n'); + } + + const stream = _iterSSEMessages(new Response(ReadableStreamFrom(body())), new AbortController())[ + Symbol.asyncIterator + ](); + + let event = await stream.next(); + assert(event.value); + expect(event.value.event).toEqual('foo'); + expect(JSON.parse(event.value.data)).toEqual({ foo: true }); + + event = await stream.next(); + assert(event.value); + expect(event.value.event).toEqual('ping'); + expect(JSON.parse(event.value.data)).toEqual({ bar: false }); + + event = await stream.next(); + expect(event.done).toBeTruthy(); + }); + + test('multiple data lines with empty line', async () => { + async function* body(): AsyncGenerator { + yield Buffer.from('event: ping\n'); + yield Buffer.from('data: {\n'); + yield Buffer.from('data: "foo":\n'); + yield Buffer.from('data: \n'); + yield Buffer.from('data:\n'); + yield Buffer.from('data: true}\n'); + yield Buffer.from('\n\n'); + } + + const stream = _iterSSEMessages(new Response(ReadableStreamFrom(body())), new AbortController())[ + Symbol.asyncIterator + ](); + + let event = await stream.next(); + assert(event.value); + expect(event.value.event).toEqual('ping'); + expect(JSON.parse(event.value.data)).toEqual({ foo: true }); + expect(event.value.data).toEqual('{\n"foo":\n\n\ntrue}'); + + event = await stream.next(); + expect(event.done).toBeTruthy(); + }); + + test('data json escaped double new line', async () => { + async function* body(): AsyncGenerator { + yield Buffer.from('event: ping\n'); + yield Buffer.from('data: {"foo": "my long\\n\\ncontent"}'); + yield Buffer.from('\n\n'); + } + + const stream = _iterSSEMessages(new Response(ReadableStreamFrom(body())), new AbortController())[ + Symbol.asyncIterator + ](); + + let event = await stream.next(); + assert(event.value); + expect(event.value.event).toEqual('ping'); + expect(JSON.parse(event.value.data)).toEqual({ foo: 'my long\n\ncontent' }); + + event = await stream.next(); + expect(event.done).toBeTruthy(); + }); + + test('special new line characters', async () => { + async function* body(): AsyncGenerator { + yield Buffer.from('data: {"content": "culpa "}\n'); + yield Buffer.from('\n'); + yield Buffer.from('data: {"content": "'); + yield Buffer.from([0xe2, 0x80, 0xa8]); + yield Buffer.from('"}\n'); + yield Buffer.from('\n'); + yield Buffer.from('data: {"content": "foo"}\n'); + yield Buffer.from('\n'); + } + + const stream = _iterSSEMessages(new Response(ReadableStreamFrom(body())), new AbortController())[ + Symbol.asyncIterator + ](); + + let event = await stream.next(); + assert(event.value); + expect(JSON.parse(event.value.data)).toEqual({ content: 'culpa ' }); + + event = await stream.next(); + assert(event.value); + expect(JSON.parse(event.value.data)).toEqual({ content: Buffer.from([0xe2, 0x80, 0xa8]).toString() }); + + event = await stream.next(); + assert(event.value); + expect(JSON.parse(event.value.data)).toEqual({ content: 'foo' }); + + event = await stream.next(); + expect(event.done).toBeTruthy(); + }); + + test('multi-byte characters across chunks', async () => { + async function* body(): AsyncGenerator { + yield Buffer.from('event: completion\n'); + yield Buffer.from('data: {"content": "'); + // bytes taken from the string 'известни' and arbitrarily split + // so that some multi-byte characters span multiple chunks + yield Buffer.from([0xd0]); + yield Buffer.from([0xb8, 0xd0, 0xb7, 0xd0]); + yield Buffer.from([0xb2, 0xd0, 0xb5, 0xd1, 0x81, 0xd1, 0x82, 0xd0, 0xbd, 0xd0, 0xb8]); + yield Buffer.from('"}\n'); + yield Buffer.from('\n'); + } + + const stream = _iterSSEMessages(new Response(ReadableStreamFrom(body())), new AbortController())[ + Symbol.asyncIterator + ](); + + let event = await stream.next(); + assert(event.value); + expect(event.value.event).toEqual('completion'); + expect(JSON.parse(event.value.data)).toEqual({ content: 'известни' }); + + event = await stream.next(); + expect(event.done).toBeTruthy(); + }); +}); From 1d029d6c17776202c7136d1777d8dcc92a3e3c67 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 19 May 2025 21:18:27 +0000 Subject: [PATCH 032/551] feat(api): update via SDK Studio --- .stats.yml | 8 ++-- api.md | 8 ++++ src/client.ts | 4 +- src/resources/apps/apps.ts | 63 +++++++++++++++++++++++++++ src/resources/apps/index.ts | 2 +- src/resources/index.ts | 2 +- tests/api-resources/apps/apps.test.ts | 30 +++++++++++++ 7 files changed, 109 insertions(+), 8 deletions(-) create mode 100644 tests/api-resources/apps/apps.test.ts diff --git a/.stats.yml b/.stats.yml index 01f342cf..01c41add 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 6 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-19b0d17ba368f32827ee322d15a7f4ff7e1f3bbf66606fad227b3465f8ffc5ab.yml -openapi_spec_hash: 4a3cb766898e8a134ef99fe6c4c87736 -config_hash: 9018b7ff17f8de1bc3e99a0ae2f2df68 +configured_endpoints: 7 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-c9d64df733f286f09d2203f4e3d820ce57e8d4c629c5e2db4e2bfac91fbc1598.yml +openapi_spec_hash: fa407611fc566d55f403864fbfaa6c23 +config_hash: 7f67c5b95af1e4b39525515240b72275 diff --git a/api.md b/api.md index d53f92ec..93c2c190 100644 --- a/api.md +++ b/api.md @@ -1,5 +1,13 @@ # Apps +Types: + +- AppListResponse + +Methods: + +- client.apps.list({ ...params }) -> AppListResponse + ## Deployments Types: diff --git a/src/client.ts b/src/client.ts index a78cf2de..9abc9a09 100644 --- a/src/client.ts +++ b/src/client.ts @@ -29,7 +29,7 @@ import { import { readEnv } from './internal/utils/env'; import { formatRequestDetails, loggerFor } from './internal/utils/log'; import { isEmptyObj } from './internal/utils/values'; -import { Apps } from './resources/apps/apps'; +import { AppListParams, AppListResponse, Apps } from './resources/apps/apps'; const environments = { production: 'https://api.onkernel.com/', @@ -729,7 +729,7 @@ Kernel.Browsers = Browsers; export declare namespace Kernel { export type RequestOptions = Opts.RequestOptions; - export { Apps as Apps }; + export { Apps as Apps, type AppListResponse as AppListResponse, type AppListParams as AppListParams }; export { Browsers as Browsers, diff --git a/src/resources/apps/apps.ts b/src/resources/apps/apps.ts index 29434998..7db22934 100644 --- a/src/resources/apps/apps.ts +++ b/src/resources/apps/apps.ts @@ -15,16 +15,79 @@ import { InvocationRetrieveResponse, Invocations, } from './invocations'; +import { APIPromise } from '../../core/api-promise'; +import { RequestOptions } from '../../internal/request-options'; export class Apps extends APIResource { deployments: DeploymentsAPI.Deployments = new DeploymentsAPI.Deployments(this._client); invocations: InvocationsAPI.Invocations = new InvocationsAPI.Invocations(this._client); + + /** + * List application versions for the authenticated user. Optionally filter by app + * name and/or version label. + * + * @example + * ```ts + * const apps = await client.apps.list(); + * ``` + */ + list(query: AppListParams | null | undefined = {}, options?: RequestOptions): APIPromise { + return this._client.get('/apps', { query, ...options }); + } +} + +export type AppListResponse = Array; + +export namespace AppListResponse { + /** + * Summary of an application version. + */ + export interface AppListResponseItem { + /** + * Unique identifier for the app version + */ + id: string; + + /** + * Name of the application + */ + app_name: string; + + /** + * Deployment region code + */ + region: string; + + /** + * Version label for the application + */ + version: string; + + /** + * Environment variables configured for this app version + */ + env_vars?: Record; + } +} + +export interface AppListParams { + /** + * Filter results by application name. + */ + app_name?: string; + + /** + * Filter results by version label. + */ + version?: string; } Apps.Deployments = Deployments; Apps.Invocations = Invocations; export declare namespace Apps { + export { type AppListResponse as AppListResponse, type AppListParams as AppListParams }; + export { Deployments as Deployments, type DeploymentCreateResponse as DeploymentCreateResponse, diff --git a/src/resources/apps/index.ts b/src/resources/apps/index.ts index c2215c03..52ecdea6 100644 --- a/src/resources/apps/index.ts +++ b/src/resources/apps/index.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -export { Apps } from './apps'; +export { Apps, type AppListResponse, type AppListParams } from './apps'; export { Deployments, type DeploymentCreateResponse, diff --git a/src/resources/index.ts b/src/resources/index.ts index d8d49aef..ecbf870a 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -export { Apps } from './apps/apps'; +export { Apps, type AppListResponse, type AppListParams } from './apps/apps'; export { Browsers, type BrowserCreateResponse, diff --git a/tests/api-resources/apps/apps.test.ts b/tests/api-resources/apps/apps.test.ts new file mode 100644 index 00000000..6bb4e0d8 --- /dev/null +++ b/tests/api-resources/apps/apps.test.ts @@ -0,0 +1,30 @@ +// 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 apps', () => { + // skipped: tests are disabled for the time being + test.skip('list', async () => { + const responsePromise = client.apps.list(); + 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('list: 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.apps.list({ app_name: 'app_name', version: 'version' }, { path: '/_stainless_unknown_path' }), + ).rejects.toThrow(Kernel.NotFoundError); + }); +}); From 8208f7a4b1ceb0f70566a96eb6bfa82904801c4d Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 19 May 2025 22:08:41 +0000 Subject: [PATCH 033/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index a0ad4167..cdc55ccc 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.1.0-alpha.12" + ".": "0.1.0-alpha.13" } diff --git a/package.json b/package.json index 8534ef83..659707cf 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.1.0-alpha.12", + "version": "0.1.0-alpha.13", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index de5a5a58..97229ce9 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.1.0-alpha.12'; // x-release-please-version +export const VERSION = '0.1.0-alpha.13'; // x-release-please-version From 1c1068549f4b7aeea3c8749bd1382870d5b52f9b Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 20 May 2025 15:58:07 +0000 Subject: [PATCH 034/551] feat(api): update via SDK Studio --- .stats.yml | 8 ++-- api.md | 8 ---- src/client.ts | 4 +- src/resources/apps/apps.ts | 63 --------------------------- src/resources/apps/index.ts | 2 +- src/resources/index.ts | 2 +- tests/api-resources/apps/apps.test.ts | 30 ------------- 7 files changed, 8 insertions(+), 109 deletions(-) delete mode 100644 tests/api-resources/apps/apps.test.ts diff --git a/.stats.yml b/.stats.yml index 01c41add..f0d8544e 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 7 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-c9d64df733f286f09d2203f4e3d820ce57e8d4c629c5e2db4e2bfac91fbc1598.yml -openapi_spec_hash: fa407611fc566d55f403864fbfaa6c23 -config_hash: 7f67c5b95af1e4b39525515240b72275 +configured_endpoints: 6 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-19b0d17ba368f32827ee322d15a7f4ff7e1f3bbf66606fad227b3465f8ffc5ab.yml +openapi_spec_hash: 4a3cb766898e8a134ef99fe6c4c87736 +config_hash: 4dfa4d870ce0e23e31ce33ab6a53dd21 diff --git a/api.md b/api.md index 93c2c190..d53f92ec 100644 --- a/api.md +++ b/api.md @@ -1,13 +1,5 @@ # Apps -Types: - -- AppListResponse - -Methods: - -- client.apps.list({ ...params }) -> AppListResponse - ## Deployments Types: diff --git a/src/client.ts b/src/client.ts index 9abc9a09..a78cf2de 100644 --- a/src/client.ts +++ b/src/client.ts @@ -29,7 +29,7 @@ import { import { readEnv } from './internal/utils/env'; import { formatRequestDetails, loggerFor } from './internal/utils/log'; import { isEmptyObj } from './internal/utils/values'; -import { AppListParams, AppListResponse, Apps } from './resources/apps/apps'; +import { Apps } from './resources/apps/apps'; const environments = { production: 'https://api.onkernel.com/', @@ -729,7 +729,7 @@ Kernel.Browsers = Browsers; export declare namespace Kernel { export type RequestOptions = Opts.RequestOptions; - export { Apps as Apps, type AppListResponse as AppListResponse, type AppListParams as AppListParams }; + export { Apps as Apps }; export { Browsers as Browsers, diff --git a/src/resources/apps/apps.ts b/src/resources/apps/apps.ts index 7db22934..29434998 100644 --- a/src/resources/apps/apps.ts +++ b/src/resources/apps/apps.ts @@ -15,79 +15,16 @@ import { InvocationRetrieveResponse, Invocations, } from './invocations'; -import { APIPromise } from '../../core/api-promise'; -import { RequestOptions } from '../../internal/request-options'; export class Apps extends APIResource { deployments: DeploymentsAPI.Deployments = new DeploymentsAPI.Deployments(this._client); invocations: InvocationsAPI.Invocations = new InvocationsAPI.Invocations(this._client); - - /** - * List application versions for the authenticated user. Optionally filter by app - * name and/or version label. - * - * @example - * ```ts - * const apps = await client.apps.list(); - * ``` - */ - list(query: AppListParams | null | undefined = {}, options?: RequestOptions): APIPromise { - return this._client.get('/apps', { query, ...options }); - } -} - -export type AppListResponse = Array; - -export namespace AppListResponse { - /** - * Summary of an application version. - */ - export interface AppListResponseItem { - /** - * Unique identifier for the app version - */ - id: string; - - /** - * Name of the application - */ - app_name: string; - - /** - * Deployment region code - */ - region: string; - - /** - * Version label for the application - */ - version: string; - - /** - * Environment variables configured for this app version - */ - env_vars?: Record; - } -} - -export interface AppListParams { - /** - * Filter results by application name. - */ - app_name?: string; - - /** - * Filter results by version label. - */ - version?: string; } Apps.Deployments = Deployments; Apps.Invocations = Invocations; export declare namespace Apps { - export { type AppListResponse as AppListResponse, type AppListParams as AppListParams }; - export { Deployments as Deployments, type DeploymentCreateResponse as DeploymentCreateResponse, diff --git a/src/resources/apps/index.ts b/src/resources/apps/index.ts index 52ecdea6..c2215c03 100644 --- a/src/resources/apps/index.ts +++ b/src/resources/apps/index.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -export { Apps, type AppListResponse, type AppListParams } from './apps'; +export { Apps } from './apps'; export { Deployments, type DeploymentCreateResponse, diff --git a/src/resources/index.ts b/src/resources/index.ts index ecbf870a..d8d49aef 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -export { Apps, type AppListResponse, type AppListParams } from './apps/apps'; +export { Apps } from './apps/apps'; export { Browsers, type BrowserCreateResponse, diff --git a/tests/api-resources/apps/apps.test.ts b/tests/api-resources/apps/apps.test.ts deleted file mode 100644 index 6bb4e0d8..00000000 --- a/tests/api-resources/apps/apps.test.ts +++ /dev/null @@ -1,30 +0,0 @@ -// 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 apps', () => { - // skipped: tests are disabled for the time being - test.skip('list', async () => { - const responsePromise = client.apps.list(); - 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('list: 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.apps.list({ app_name: 'app_name', version: 'version' }, { path: '/_stainless_unknown_path' }), - ).rejects.toThrow(Kernel.NotFoundError); - }); -}); From 0ae3966788fdc2d48d6b1095fe0c793a2753188b Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 20 May 2025 16:02:21 +0000 Subject: [PATCH 035/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index cdc55ccc..abc263a5 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.1.0-alpha.13" + ".": "0.1.0-alpha.14" } diff --git a/package.json b/package.json index 659707cf..169baf89 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.1.0-alpha.13", + "version": "0.1.0-alpha.14", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 97229ce9..c36bf82c 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.1.0-alpha.13'; // x-release-please-version +export const VERSION = '0.1.0-alpha.14'; // x-release-please-version From e1fc1ef104ef2860ec80f4e495c4ef42b5982f93 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 20 May 2025 16:59:01 +0000 Subject: [PATCH 036/551] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index f0d8544e..f8cfc706 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 6 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-19b0d17ba368f32827ee322d15a7f4ff7e1f3bbf66606fad227b3465f8ffc5ab.yml openapi_spec_hash: 4a3cb766898e8a134ef99fe6c4c87736 -config_hash: 4dfa4d870ce0e23e31ce33ab6a53dd21 +config_hash: 5b3919927cba9bf9dcc80458c199318d From 26b17ec56684c598f62ffb8345926aef6b1bb1f4 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 20 May 2025 17:00:47 +0000 Subject: [PATCH 037/551] feat(api): update via SDK Studio --- .stats.yml | 8 ++-- api.md | 8 ++++ src/client.ts | 4 +- src/resources/apps/apps.ts | 63 +++++++++++++++++++++++++++ src/resources/apps/index.ts | 2 +- src/resources/index.ts | 2 +- tests/api-resources/apps/apps.test.ts | 30 +++++++++++++ 7 files changed, 109 insertions(+), 8 deletions(-) create mode 100644 tests/api-resources/apps/apps.test.ts diff --git a/.stats.yml b/.stats.yml index f8cfc706..2b23cedd 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 6 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-19b0d17ba368f32827ee322d15a7f4ff7e1f3bbf66606fad227b3465f8ffc5ab.yml -openapi_spec_hash: 4a3cb766898e8a134ef99fe6c4c87736 -config_hash: 5b3919927cba9bf9dcc80458c199318d +configured_endpoints: 7 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-c9d64df733f286f09d2203f4e3d820ce57e8d4c629c5e2db4e2bfac91fbc1598.yml +openapi_spec_hash: fa407611fc566d55f403864fbfaa6c23 +config_hash: 4dfa4d870ce0e23e31ce33ab6a53dd21 diff --git a/api.md b/api.md index d53f92ec..93c2c190 100644 --- a/api.md +++ b/api.md @@ -1,5 +1,13 @@ # Apps +Types: + +- AppListResponse + +Methods: + +- client.apps.list({ ...params }) -> AppListResponse + ## Deployments Types: diff --git a/src/client.ts b/src/client.ts index a78cf2de..9abc9a09 100644 --- a/src/client.ts +++ b/src/client.ts @@ -29,7 +29,7 @@ import { import { readEnv } from './internal/utils/env'; import { formatRequestDetails, loggerFor } from './internal/utils/log'; import { isEmptyObj } from './internal/utils/values'; -import { Apps } from './resources/apps/apps'; +import { AppListParams, AppListResponse, Apps } from './resources/apps/apps'; const environments = { production: 'https://api.onkernel.com/', @@ -729,7 +729,7 @@ Kernel.Browsers = Browsers; export declare namespace Kernel { export type RequestOptions = Opts.RequestOptions; - export { Apps as Apps }; + export { Apps as Apps, type AppListResponse as AppListResponse, type AppListParams as AppListParams }; export { Browsers as Browsers, diff --git a/src/resources/apps/apps.ts b/src/resources/apps/apps.ts index 29434998..7db22934 100644 --- a/src/resources/apps/apps.ts +++ b/src/resources/apps/apps.ts @@ -15,16 +15,79 @@ import { InvocationRetrieveResponse, Invocations, } from './invocations'; +import { APIPromise } from '../../core/api-promise'; +import { RequestOptions } from '../../internal/request-options'; export class Apps extends APIResource { deployments: DeploymentsAPI.Deployments = new DeploymentsAPI.Deployments(this._client); invocations: InvocationsAPI.Invocations = new InvocationsAPI.Invocations(this._client); + + /** + * List application versions for the authenticated user. Optionally filter by app + * name and/or version label. + * + * @example + * ```ts + * const apps = await client.apps.list(); + * ``` + */ + list(query: AppListParams | null | undefined = {}, options?: RequestOptions): APIPromise { + return this._client.get('/apps', { query, ...options }); + } +} + +export type AppListResponse = Array; + +export namespace AppListResponse { + /** + * Summary of an application version. + */ + export interface AppListResponseItem { + /** + * Unique identifier for the app version + */ + id: string; + + /** + * Name of the application + */ + app_name: string; + + /** + * Deployment region code + */ + region: string; + + /** + * Version label for the application + */ + version: string; + + /** + * Environment variables configured for this app version + */ + env_vars?: Record; + } +} + +export interface AppListParams { + /** + * Filter results by application name. + */ + app_name?: string; + + /** + * Filter results by version label. + */ + version?: string; } Apps.Deployments = Deployments; Apps.Invocations = Invocations; export declare namespace Apps { + export { type AppListResponse as AppListResponse, type AppListParams as AppListParams }; + export { Deployments as Deployments, type DeploymentCreateResponse as DeploymentCreateResponse, diff --git a/src/resources/apps/index.ts b/src/resources/apps/index.ts index c2215c03..52ecdea6 100644 --- a/src/resources/apps/index.ts +++ b/src/resources/apps/index.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -export { Apps } from './apps'; +export { Apps, type AppListResponse, type AppListParams } from './apps'; export { Deployments, type DeploymentCreateResponse, diff --git a/src/resources/index.ts b/src/resources/index.ts index d8d49aef..ecbf870a 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -export { Apps } from './apps/apps'; +export { Apps, type AppListResponse, type AppListParams } from './apps/apps'; export { Browsers, type BrowserCreateResponse, diff --git a/tests/api-resources/apps/apps.test.ts b/tests/api-resources/apps/apps.test.ts new file mode 100644 index 00000000..6bb4e0d8 --- /dev/null +++ b/tests/api-resources/apps/apps.test.ts @@ -0,0 +1,30 @@ +// 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 apps', () => { + // skipped: tests are disabled for the time being + test.skip('list', async () => { + const responsePromise = client.apps.list(); + 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('list: 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.apps.list({ app_name: 'app_name', version: 'version' }, { path: '/_stainless_unknown_path' }), + ).rejects.toThrow(Kernel.NotFoundError); + }); +}); From ee8f561c293aaf5f3389690b03156ad8c5e8bfad Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 20 May 2025 17:02:42 +0000 Subject: [PATCH 038/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index abc263a5..54cfe49d 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.1.0-alpha.14" + ".": "0.1.0-alpha.15" } diff --git a/package.json b/package.json index 169baf89..6eac080d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.1.0-alpha.14", + "version": "0.1.0-alpha.15", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index c36bf82c..9872581b 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.1.0-alpha.14'; // x-release-please-version +export const VERSION = '0.1.0-alpha.15'; // x-release-please-version From 4b177c899a0d0899268a0eeb8fa16bfac0c1abad Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 20 May 2025 18:19:10 +0000 Subject: [PATCH 039/551] feat(api): update via SDK Studio --- .stats.yml | 4 +- api.md | 2 +- src/resources/apps/deployments.ts | 68 +------------------------------ 3 files changed, 4 insertions(+), 70 deletions(-) diff --git a/.stats.yml b/.stats.yml index 2b23cedd..e44b3a1a 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 7 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-c9d64df733f286f09d2203f4e3d820ce57e8d4c629c5e2db4e2bfac91fbc1598.yml -openapi_spec_hash: fa407611fc566d55f403864fbfaa6c23 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-aa34ccb9b2ee8e81ef56881ff7474ea2d69a059d5c1dbb7d0ec94e28a0b68559.yml +openapi_spec_hash: c573fcd85b195ebe809a1039634652d6 config_hash: 4dfa4d870ce0e23e31ce33ab6a53dd21 diff --git a/api.md b/api.md index 93c2c190..36603453 100644 --- a/api.md +++ b/api.md @@ -18,7 +18,7 @@ Types: Methods: - client.apps.deployments.create({ ...params }) -> DeploymentCreateResponse -- client.apps.deployments.follow(id) -> DeploymentFollowResponse +- client.apps.deployments.follow(id) -> unknown ## Invocations diff --git a/src/resources/apps/deployments.ts b/src/resources/apps/deployments.ts index e4b7811e..a81aea68 100644 --- a/src/resources/apps/deployments.ts +++ b/src/resources/apps/deployments.ts @@ -92,73 +92,7 @@ export namespace DeploymentCreateResponse { /** * A stream of application events (state updates and logs) in SSE format. */ -export type DeploymentFollowResponse = Array< - | DeploymentFollowResponse.StateEvent - | DeploymentFollowResponse.StateUpdateEvent - | DeploymentFollowResponse.LogEvent ->; - -export namespace DeploymentFollowResponse { - /** - * Initial state of the application, emitted once when subscribing. - */ - export interface StateEvent { - /** - * Event type identifier (always "state"). - */ - event: 'state'; - - /** - * Current application state (e.g., "deploying", "running", "succeeded", "failed"). - */ - state: string; - - /** - * Time the state was reported. - */ - timestamp?: string; - } - - /** - * An update emitted when the application's state changes. - */ - export interface StateUpdateEvent { - /** - * Event type identifier (always "state_update"). - */ - event: 'state_update'; - - /** - * New application state (e.g., "running", "succeeded", "failed"). - */ - state: string; - - /** - * Time the state change occurred. - */ - timestamp?: string; - } - - /** - * A log entry from the application. - */ - export interface LogEvent { - /** - * Event type identifier (always "log"). - */ - event: 'log'; - - /** - * Log message text. - */ - message: string; - - /** - * Time the log entry was produced. - */ - timestamp?: string; - } -} +export type DeploymentFollowResponse = unknown; export interface DeploymentCreateParams { /** From 910cdaa48456b12aea644fd69cee3b8ea0887b5f Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 20 May 2025 18:20:35 +0000 Subject: [PATCH 040/551] feat(api): update via SDK Studio --- .stats.yml | 4 +- api.md | 2 +- src/resources/apps/deployments.ts | 70 ++++++++++++++++++++++++++++++- 3 files changed, 71 insertions(+), 5 deletions(-) diff --git a/.stats.yml b/.stats.yml index e44b3a1a..24a77a34 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 7 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-aa34ccb9b2ee8e81ef56881ff7474ea2d69a059d5c1dbb7d0ec94e28a0b68559.yml -openapi_spec_hash: c573fcd85b195ebe809a1039634652d6 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-39aa058a60035c34a636e7f580b4b9c76b05400ae401ef04a761572b20a5425b.yml +openapi_spec_hash: bb79a204f9edb6b6ccfe783a0a82a423 config_hash: 4dfa4d870ce0e23e31ce33ab6a53dd21 diff --git a/api.md b/api.md index 36603453..93c2c190 100644 --- a/api.md +++ b/api.md @@ -18,7 +18,7 @@ Types: Methods: - client.apps.deployments.create({ ...params }) -> DeploymentCreateResponse -- client.apps.deployments.follow(id) -> unknown +- client.apps.deployments.follow(id) -> DeploymentFollowResponse ## Invocations diff --git a/src/resources/apps/deployments.ts b/src/resources/apps/deployments.ts index a81aea68..30fa7ca4 100644 --- a/src/resources/apps/deployments.ts +++ b/src/resources/apps/deployments.ts @@ -90,9 +90,75 @@ export namespace DeploymentCreateResponse { } /** - * A stream of application events (state updates and logs) in SSE format. + * Union type representing any application event. Actual schema is determined by + * the 'event' field. */ -export type DeploymentFollowResponse = unknown; +export type DeploymentFollowResponse = + | DeploymentFollowResponse.StateEvent + | DeploymentFollowResponse.StateUpdateEvent + | DeploymentFollowResponse.LogEvent; + +export namespace DeploymentFollowResponse { + /** + * Initial state of the application, emitted once when subscribing. + */ + export interface StateEvent { + /** + * Event type identifier (always "state"). + */ + event: 'state'; + + /** + * Current application state (e.g., "deploying", "running", "succeeded", "failed"). + */ + state: string; + + /** + * Time the state was reported. + */ + timestamp?: string; + } + + /** + * An update emitted when the application's state changes. + */ + export interface StateUpdateEvent { + /** + * Event type identifier (always "state_update"). + */ + event: 'state_update'; + + /** + * New application state (e.g., "running", "succeeded", "failed"). + */ + state: string; + + /** + * Time the state change occurred. + */ + timestamp?: string; + } + + /** + * A log entry from the application. + */ + export interface LogEvent { + /** + * Event type identifier (always "log"). + */ + event: 'log'; + + /** + * Log message text. + */ + message: string; + + /** + * Time the log entry was produced. + */ + timestamp?: string; + } +} export interface DeploymentCreateParams { /** From 97b262a00b8e51cc77bf9eb2b2886a87ab14ffb9 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 20 May 2025 18:22:36 +0000 Subject: [PATCH 041/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 54cfe49d..47736a5c 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.1.0-alpha.15" + ".": "0.1.0-alpha.16" } diff --git a/package.json b/package.json index 6eac080d..941fb0d3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.1.0-alpha.15", + "version": "0.1.0-alpha.16", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 9872581b..baebd9dd 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.1.0-alpha.15'; // x-release-please-version +export const VERSION = '0.1.0-alpha.16'; // x-release-please-version From 6164449d2b4890c490745d256e6e635553ef30bb Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 21 May 2025 17:59:55 +0000 Subject: [PATCH 042/551] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index 24a77a34..b26bed31 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 7 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-39aa058a60035c34a636e7f580b4b9c76b05400ae401ef04a761572b20a5425b.yml openapi_spec_hash: bb79a204f9edb6b6ccfe783a0a82a423 -config_hash: 4dfa4d870ce0e23e31ce33ab6a53dd21 +config_hash: 3eb1ed1dd0067258984b31d53a0dab48 From 8092791cac8a6a3cad9abadd14c3d08ccc276b42 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 21 May 2025 18:02:24 +0000 Subject: [PATCH 043/551] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index b26bed31..b30a9668 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 7 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-39aa058a60035c34a636e7f580b4b9c76b05400ae401ef04a761572b20a5425b.yml -openapi_spec_hash: bb79a204f9edb6b6ccfe783a0a82a423 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-b594ec244fa0dd448274eb91c93f8c43f19b5056415e457e1e90fa9df749b52a.yml +openapi_spec_hash: 6bd4844a6e85289bea205723dbafff58 config_hash: 3eb1ed1dd0067258984b31d53a0dab48 From 7542121172af8d8a0d29e91dc7c3b573d0212681 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 21 May 2025 18:04:18 +0000 Subject: [PATCH 044/551] feat(api): update via SDK Studio --- .stats.yml | 6 +++--- README.md | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.stats.yml b/.stats.yml index b30a9668..bf7a9321 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 7 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-b594ec244fa0dd448274eb91c93f8c43f19b5056415e457e1e90fa9df749b52a.yml -openapi_spec_hash: 6bd4844a6e85289bea205723dbafff58 -config_hash: 3eb1ed1dd0067258984b31d53a0dab48 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-39aa058a60035c34a636e7f580b4b9c76b05400ae401ef04a761572b20a5425b.yml +openapi_spec_hash: bb79a204f9edb6b6ccfe783a0a82a423 +config_hash: 5c90b7df80e8f222bb945b14b8d1fec0 diff --git a/README.md b/README.md index d9930749..dcc6113b 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ async function main() { const deployment = await client.apps.deployments.create({ entrypoint_rel_path: 'main.ts', file: fs.createReadStream('path/to/file'), - env_vars: { OPENAI_API_KEY: 'x' }, + env_vars: { OPENAI_API_KEY: 'x', LOG_LEVEL: 'debug' }, version: '1.0.0', }); From 90e342f1dcc0be3a8adb41e77276c5388680431d Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 21 May 2025 18:07:15 +0000 Subject: [PATCH 045/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 47736a5c..466df71c 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.1.0-alpha.16" + ".": "0.1.0" } diff --git a/package.json b/package.json index 941fb0d3..aaa63229 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.1.0-alpha.16", + "version": "0.1.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index baebd9dd..1baa2286 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.1.0-alpha.16'; // x-release-please-version +export const VERSION = '0.1.0'; // x-release-please-version From 645745a38772808523143ee566ae4c35e2aca1ae Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 21 May 2025 18:11:13 +0000 Subject: [PATCH 046/551] feat(api): update via SDK Studio --- .stats.yml | 2 +- README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index bf7a9321..b26bed31 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 7 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-39aa058a60035c34a636e7f580b4b9c76b05400ae401ef04a761572b20a5425b.yml openapi_spec_hash: bb79a204f9edb6b6ccfe783a0a82a423 -config_hash: 5c90b7df80e8f222bb945b14b8d1fec0 +config_hash: 3eb1ed1dd0067258984b31d53a0dab48 diff --git a/README.md b/README.md index dcc6113b..d9930749 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ async function main() { const deployment = await client.apps.deployments.create({ entrypoint_rel_path: 'main.ts', file: fs.createReadStream('path/to/file'), - env_vars: { OPENAI_API_KEY: 'x', LOG_LEVEL: 'debug' }, + env_vars: { OPENAI_API_KEY: 'x' }, version: '1.0.0', }); From e0d63cf42af72c19cba6c816770e9170b6d2f4c2 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 21 May 2025 18:12:49 +0000 Subject: [PATCH 047/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 466df71c..2be9c43c 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.1.0" + ".": "0.2.0" } diff --git a/package.json b/package.json index aaa63229..7e328ae2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.1.0", + "version": "0.2.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 1baa2286..bade2ffc 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.1.0'; // x-release-please-version +export const VERSION = '0.2.0'; // x-release-please-version From 2fcc09c4e12218d12eb56f105e51173823619b62 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 22 May 2025 02:32:36 +0000 Subject: [PATCH 048/551] chore(docs): grammar improvements --- SECURITY.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SECURITY.md b/SECURITY.md index bd2ba47d..0c6c32d1 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -16,7 +16,7 @@ before making any information public. ## Reporting Non-SDK Related Security Issues If you encounter security issues that are not directly related to SDKs but pertain to the services -or products provided by Kernel please follow the respective company's security reporting guidelines. +or products provided by Kernel, please follow the respective company's security reporting guidelines. --- From 2b6d0aa81595ab5d87bffc500d769da63dad5c46 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 22 May 2025 15:25:47 +0000 Subject: [PATCH 049/551] feat(api): update via SDK Studio --- .stats.yml | 4 +-- src/resources/browsers.ts | 51 ++++++++++++++++++++++++++++ tests/api-resources/browsers.test.ts | 5 ++- 3 files changed, 57 insertions(+), 3 deletions(-) diff --git a/.stats.yml b/.stats.yml index b26bed31..36c603b5 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 7 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-39aa058a60035c34a636e7f580b4b9c76b05400ae401ef04a761572b20a5425b.yml -openapi_spec_hash: bb79a204f9edb6b6ccfe783a0a82a423 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-2813f659cb4e9e81cd3d9c94df748fd6c54f966fd6fd4881da369394aa981ace.yml +openapi_spec_hash: facb760f50156c700b5c016087a70d64 config_hash: 3eb1ed1dd0067258984b31d53a0dab48 diff --git a/src/resources/browsers.ts b/src/resources/browsers.ts index febb6d11..0cb2de9d 100644 --- a/src/resources/browsers.ts +++ b/src/resources/browsers.ts @@ -50,6 +50,23 @@ export interface BrowserCreateResponse { * Unique identifier for the browser session */ session_id: string; + + /** + * Optional persistence configuration for the browser session. + */ + persistence?: BrowserCreateResponse.Persistence; +} + +export namespace BrowserCreateResponse { + /** + * Optional persistence configuration for the browser session. + */ + export interface Persistence { + /** + * Unique identifier for the persistent browser session. + */ + id: string; + } } export interface BrowserRetrieveResponse { @@ -67,6 +84,23 @@ export interface BrowserRetrieveResponse { * Unique identifier for the browser session */ session_id: string; + + /** + * Optional persistence configuration for the browser session. + */ + persistence?: BrowserRetrieveResponse.Persistence; +} + +export namespace BrowserRetrieveResponse { + /** + * Optional persistence configuration for the browser session. + */ + export interface Persistence { + /** + * Unique identifier for the persistent browser session. + */ + id: string; + } } export interface BrowserCreateParams { @@ -74,6 +108,23 @@ export interface BrowserCreateParams { * action invocation ID */ invocation_id: string; + + /** + * Optional persistence configuration for the browser session. + */ + persistence?: BrowserCreateParams.Persistence; +} + +export namespace BrowserCreateParams { + /** + * Optional persistence configuration for the browser session. + */ + export interface Persistence { + /** + * Unique identifier for the persistent browser session. + */ + id: string; + } } export declare namespace Browsers { diff --git a/tests/api-resources/browsers.test.ts b/tests/api-resources/browsers.test.ts index 72349779..04c0d3f0 100644 --- a/tests/api-resources/browsers.test.ts +++ b/tests/api-resources/browsers.test.ts @@ -22,7 +22,10 @@ describe('resource browsers', () => { // skipped: tests are disabled for the time being test.skip('create: required and optional params', async () => { - const response = await client.browsers.create({ invocation_id: 'ckqwer3o20000jb9s7abcdef' }); + const response = await client.browsers.create({ + invocation_id: 'ckqwer3o20000jb9s7abcdef', + persistence: { id: 'my-shared-browser' }, + }); }); // skipped: tests are disabled for the time being From 0031e2d342ff5a981f6b43214a99144cf49eab7d Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 22 May 2025 16:43:02 +0000 Subject: [PATCH 050/551] feat(api): update via SDK Studio --- .stats.yml | 8 +- api.md | 5 ++ src/client.ts | 6 ++ src/resources/browsers.ts | 120 ++++++++++++++++++++------- src/resources/index.ts | 3 + tests/api-resources/browsers.test.ts | 41 +++++++++ 6 files changed, 149 insertions(+), 34 deletions(-) diff --git a/.stats.yml b/.stats.yml index 36c603b5..77c3857b 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 7 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-2813f659cb4e9e81cd3d9c94df748fd6c54f966fd6fd4881da369394aa981ace.yml -openapi_spec_hash: facb760f50156c700b5c016087a70d64 -config_hash: 3eb1ed1dd0067258984b31d53a0dab48 +configured_endpoints: 10 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-ffefc234d11c041cadab66fa6e7c379cebbd9422d38f2b1b1019e425ae19bbd8.yml +openapi_spec_hash: aa04a371ff95b44847450d657ad0a920 +config_hash: f33cc77a9c01e879ad127194c897a988 diff --git a/api.md b/api.md index 93c2c190..6c5f238b 100644 --- a/api.md +++ b/api.md @@ -36,10 +36,15 @@ Methods: Types: +- 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 diff --git a/src/client.ts b/src/client.ts index 9abc9a09..84b00f00 100644 --- a/src/client.ts +++ b/src/client.ts @@ -23,6 +23,9 @@ import { FinalRequestOptions, RequestOptions } from './internal/request-options' import { BrowserCreateParams, BrowserCreateResponse, + BrowserDeleteParams, + BrowserListResponse, + BrowserPersistence, BrowserRetrieveResponse, Browsers, } from './resources/browsers'; @@ -733,8 +736,11 @@ export declare namespace Kernel { export { Browsers as Browsers, + type BrowserPersistence as BrowserPersistence, type BrowserCreateResponse as BrowserCreateResponse, type BrowserRetrieveResponse as BrowserRetrieveResponse, + type BrowserListResponse as BrowserListResponse, type BrowserCreateParams as BrowserCreateParams, + type BrowserDeleteParams as BrowserDeleteParams, }; } diff --git a/src/resources/browsers.ts b/src/resources/browsers.ts index 0cb2de9d..1c3be71c 100644 --- a/src/resources/browsers.ts +++ b/src/resources/browsers.ts @@ -1,7 +1,9 @@ // 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'; @@ -33,6 +35,64 @@ export class Browsers extends APIResource { retrieve(id: string, options?: RequestOptions): APIPromise { return this._client.get(path`/browsers/${id}`, options); } + + /** + * List active browser sessions for the authenticated user + * + * @example + * ```ts + * const browsers = await client.browsers.list(); + * ``` + */ + list(options?: RequestOptions): APIPromise { + return this._client.get('/browsers', options); + } + + /** + * Delete a persistent browser session by persistent_id query parameter. + * + * @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 Browser Session by ID + * + * @example + * ```ts + * await client.browsers.deleteByID( + * 'e5bf36fe-9247-4e2b-8b5a-2f594cc1c073', + * ); + * ``` + */ + 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 { @@ -54,19 +114,7 @@ export interface BrowserCreateResponse { /** * Optional persistence configuration for the browser session. */ - persistence?: BrowserCreateResponse.Persistence; -} - -export namespace BrowserCreateResponse { - /** - * Optional persistence configuration for the browser session. - */ - export interface Persistence { - /** - * Unique identifier for the persistent browser session. - */ - id: string; - } + persistence?: BrowserPersistence; } export interface BrowserRetrieveResponse { @@ -88,18 +136,32 @@ export interface BrowserRetrieveResponse { /** * Optional persistence configuration for the browser session. */ - persistence?: BrowserRetrieveResponse.Persistence; + persistence?: BrowserPersistence; } -export namespace BrowserRetrieveResponse { - /** - * Optional persistence configuration for the browser session. - */ - export interface Persistence { +export type BrowserListResponse = Array; + +export namespace BrowserListResponse { + export interface BrowserListResponseItem { + /** + * Remote URL for live viewing the browser session + */ + browser_live_view_url: string; + + /** + * Websocket URL for Chrome DevTools Protocol connections to the browser session + */ + cdp_ws_url: string; + /** - * Unique identifier for the persistent browser session. + * Unique identifier for the browser session */ - id: string; + session_id: string; + + /** + * Optional persistence configuration for the browser session. + */ + persistence?: BrowsersAPI.BrowserPersistence; } } @@ -112,25 +174,23 @@ export interface BrowserCreateParams { /** * Optional persistence configuration for the browser session. */ - persistence?: BrowserCreateParams.Persistence; + persistence?: BrowserPersistence; } -export namespace BrowserCreateParams { +export interface BrowserDeleteParams { /** - * Optional persistence configuration for the browser session. + * Persistent browser identifier */ - export interface Persistence { - /** - * Unique identifier for the persistent browser session. - */ - id: string; - } + 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, }; } diff --git a/src/resources/index.ts b/src/resources/index.ts index ecbf870a..5faf2a53 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -3,7 +3,10 @@ export { Apps, type AppListResponse, type AppListParams } from './apps/apps'; export { Browsers, + type BrowserPersistence, type BrowserCreateResponse, type BrowserRetrieveResponse, + type BrowserListResponse, type BrowserCreateParams, + type BrowserDeleteParams, } from './browsers'; diff --git a/tests/api-resources/browsers.test.ts b/tests/api-resources/browsers.test.ts index 04c0d3f0..1e9e0256 100644 --- a/tests/api-resources/browsers.test.ts +++ b/tests/api-resources/browsers.test.ts @@ -39,4 +39,45 @@ describe('resource browsers', () => { expect(dataAndResponse.data).toBe(response); expect(dataAndResponse.response).toBe(rawResponse); }); + + // skipped: tests are disabled for the time being + test.skip('list', async () => { + const responsePromise = client.browsers.list(); + 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('delete: only required params', async () => { + const responsePromise = client.browsers.delete({ persistent_id: 'persistent_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('delete: required and optional params', async () => { + const response = await client.browsers.delete({ persistent_id: 'persistent_id' }); + }); + + // skipped: tests are disabled for the time being + test.skip('deleteByID', async () => { + const responsePromise = client.browsers.deleteByID('e5bf36fe-9247-4e2b-8b5a-2f594cc1c073'); + 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); + }); }); From 0ae4c75ff3e434c5549341f7cb485c99ccb0643e Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 22 May 2025 16:51:14 +0000 Subject: [PATCH 051/551] feat(api): update via SDK Studio --- .stats.yml | 4 ++-- src/resources/apps/invocations.ts | 2 +- src/resources/browsers.ts | 6 +++--- tests/api-resources/apps/invocations.test.ts | 2 +- tests/api-resources/browsers.test.ts | 10 +++++----- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/.stats.yml b/.stats.yml index 77c3857b..c728bcd7 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 10 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-ffefc234d11c041cadab66fa6e7c379cebbd9422d38f2b1b1019e425ae19bbd8.yml -openapi_spec_hash: aa04a371ff95b44847450d657ad0a920 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-3edc7a0eef4a0d4495782efbdb0d9b777a55aee058dab119f90de56019441326.yml +openapi_spec_hash: dff0b1efa1c1614cf770ed8327cefab2 config_hash: f33cc77a9c01e879ad127194c897a988 diff --git a/src/resources/apps/invocations.ts b/src/resources/apps/invocations.ts index fee4db3e..3f1e23ab 100644 --- a/src/resources/apps/invocations.ts +++ b/src/resources/apps/invocations.ts @@ -28,7 +28,7 @@ export class Invocations extends APIResource { * @example * ```ts * const invocation = await client.apps.invocations.retrieve( - * 'ckqwer3o20000jb9s7abcdef', + * 'rr33xuugxj9h0bkf1rdt2bet', * ); * ``` */ diff --git a/src/resources/browsers.ts b/src/resources/browsers.ts index 1c3be71c..b66c68f9 100644 --- a/src/resources/browsers.ts +++ b/src/resources/browsers.ts @@ -14,7 +14,7 @@ export class Browsers extends APIResource { * @example * ```ts * const browser = await client.browsers.create({ - * invocation_id: 'ckqwer3o20000jb9s7abcdef', + * invocation_id: 'rr33xuugxj9h0bkf1rdt2bet', * }); * ``` */ @@ -28,7 +28,7 @@ export class Browsers extends APIResource { * @example * ```ts * const browser = await client.browsers.retrieve( - * 'e5bf36fe-9247-4e2b-8b5a-2f594cc1c073', + * 'htzv5orfit78e1m2biiifpbv', * ); * ``` */ @@ -73,7 +73,7 @@ export class Browsers extends APIResource { * @example * ```ts * await client.browsers.deleteByID( - * 'e5bf36fe-9247-4e2b-8b5a-2f594cc1c073', + * 'htzv5orfit78e1m2biiifpbv', * ); * ``` */ diff --git a/tests/api-resources/apps/invocations.test.ts b/tests/api-resources/apps/invocations.test.ts index 3bafc763..4d76cc87 100644 --- a/tests/api-resources/apps/invocations.test.ts +++ b/tests/api-resources/apps/invocations.test.ts @@ -36,7 +36,7 @@ describe('resource invocations', () => { // skipped: tests are disabled for the time being test.skip('retrieve', async () => { - const responsePromise = client.apps.invocations.retrieve('ckqwer3o20000jb9s7abcdef'); + const responsePromise = client.apps.invocations.retrieve('rr33xuugxj9h0bkf1rdt2bet'); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; diff --git a/tests/api-resources/browsers.test.ts b/tests/api-resources/browsers.test.ts index 1e9e0256..8bb89aa9 100644 --- a/tests/api-resources/browsers.test.ts +++ b/tests/api-resources/browsers.test.ts @@ -10,7 +10,7 @@ const client = new Kernel({ describe('resource browsers', () => { // skipped: tests are disabled for the time being test.skip('create: only required params', async () => { - const responsePromise = client.browsers.create({ invocation_id: 'ckqwer3o20000jb9s7abcdef' }); + const responsePromise = client.browsers.create({ invocation_id: 'rr33xuugxj9h0bkf1rdt2bet' }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -23,14 +23,14 @@ describe('resource browsers', () => { // skipped: tests are disabled for the time being test.skip('create: required and optional params', async () => { const response = await client.browsers.create({ - invocation_id: 'ckqwer3o20000jb9s7abcdef', - persistence: { id: 'my-shared-browser' }, + invocation_id: 'rr33xuugxj9h0bkf1rdt2bet', + persistence: { id: 'my-awesome-browser-for-user-1234' }, }); }); // skipped: tests are disabled for the time being test.skip('retrieve', async () => { - const responsePromise = client.browsers.retrieve('e5bf36fe-9247-4e2b-8b5a-2f594cc1c073'); + const responsePromise = client.browsers.retrieve('htzv5orfit78e1m2biiifpbv'); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -71,7 +71,7 @@ describe('resource browsers', () => { // skipped: tests are disabled for the time being test.skip('deleteByID', async () => { - const responsePromise = client.browsers.deleteByID('e5bf36fe-9247-4e2b-8b5a-2f594cc1c073'); + const responsePromise = client.browsers.deleteByID('htzv5orfit78e1m2biiifpbv'); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; From 75eb2b70ca43f1ade347b3991be57e6ba6e37ec1 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 22 May 2025 16:54:07 +0000 Subject: [PATCH 052/551] feat(api): update via SDK Studio --- .stats.yml | 2 +- README.md | 35 +++++++++++++++++++++-------------- 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/.stats.yml b/.stats.yml index c728bcd7..d4463c35 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 10 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-3edc7a0eef4a0d4495782efbdb0d9b777a55aee058dab119f90de56019441326.yml openapi_spec_hash: dff0b1efa1c1614cf770ed8327cefab2 -config_hash: f33cc77a9c01e879ad127194c897a988 +config_hash: cb04a4d88ee9f530b303ca57ff7090b3 diff --git a/README.md b/README.md index d9930749..8db99d17 100644 --- a/README.md +++ b/README.md @@ -55,7 +55,10 @@ const client = new Kernel({ }); async function main() { - const params: Kernel.BrowserCreateParams = { invocation_id: 'REPLACE_ME' }; + const params: Kernel.BrowserCreateParams = { + invocation_id: 'REPLACE_ME', + persistence: { id: 'browser-for-user-1234' }, + }; const browser: Kernel.BrowserCreateResponse = await client.browsers.create(params); } @@ -117,15 +120,17 @@ a subclass of `APIError` will be thrown: ```ts async function main() { - const browser = await client.browsers.create({ invocation_id: 'REPLACE_ME' }).catch(async (err) => { - if (err instanceof Kernel.APIError) { - console.log(err.status); // 400 - console.log(err.name); // BadRequestError - console.log(err.headers); // {server: 'nginx', ...} - } else { - throw err; - } - }); + const browser = await client.browsers + .create({ invocation_id: 'REPLACE_ME', persistence: { id: 'browser-for-user-1234' } }) + .catch(async (err) => { + if (err instanceof Kernel.APIError) { + console.log(err.status); // 400 + console.log(err.name); // BadRequestError + console.log(err.headers); // {server: 'nginx', ...} + } else { + throw err; + } + }); } main(); @@ -160,7 +165,7 @@ const client = new Kernel({ }); // Or, configure per-request: -await client.browsers.create({ invocation_id: 'REPLACE_ME' }, { +await client.browsers.create({ invocation_id: 'REPLACE_ME', persistence: { id: 'browser-for-user-1234' } }, { maxRetries: 5, }); ``` @@ -177,7 +182,7 @@ const client = new Kernel({ }); // Override per-request: -await client.browsers.create({ invocation_id: 'REPLACE_ME' }, { +await client.browsers.create({ invocation_id: 'REPLACE_ME', persistence: { id: 'browser-for-user-1234' } }, { timeout: 5 * 1000, }); ``` @@ -200,12 +205,14 @@ Unlike `.asResponse()` this method consumes the body, returning once it is parse ```ts const client = new Kernel(); -const response = await client.browsers.create({ invocation_id: 'REPLACE_ME' }).asResponse(); +const response = await client.browsers + .create({ invocation_id: 'REPLACE_ME', persistence: { id: 'browser-for-user-1234' } }) + .asResponse(); console.log(response.headers.get('X-My-Header')); console.log(response.statusText); // access the underlying Response object const { data: browser, response: raw } = await client.browsers - .create({ invocation_id: 'REPLACE_ME' }) + .create({ invocation_id: 'REPLACE_ME', persistence: { id: 'browser-for-user-1234' } }) .withResponse(); console.log(raw.headers.get('X-My-Header')); console.log(browser.session_id); From a2a1775f8865fae8a77130c68404864c17152a3d Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 22 May 2025 20:24:23 +0000 Subject: [PATCH 053/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 2be9c43c..0ee8c012 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.2.0" + ".": "0.3.0" } diff --git a/package.json b/package.json index 7e328ae2..c5ebe610 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.2.0", + "version": "0.3.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index bade2ffc..88f4d403 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.2.0'; // x-release-please-version +export const VERSION = '0.3.0'; // x-release-please-version From 4922e101b93a7fcbe3a021ee2a903d59a094f9d1 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 28 May 2025 02:11:22 +0000 Subject: [PATCH 054/551] feat(api): update via SDK Studio --- .stats.yml | 8 +- api.md | 2 + src/resources/apps/apps.ts | 4 + src/resources/apps/index.ts | 2 + src/resources/apps/invocations.ts | 88 ++++++++++++++++++++ tests/api-resources/apps/invocations.test.ts | 18 ++++ 6 files changed, 118 insertions(+), 4 deletions(-) diff --git a/.stats.yml b/.stats.yml index d4463c35..be606c6d 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 10 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-3edc7a0eef4a0d4495782efbdb0d9b777a55aee058dab119f90de56019441326.yml -openapi_spec_hash: dff0b1efa1c1614cf770ed8327cefab2 -config_hash: cb04a4d88ee9f530b303ca57ff7090b3 +configured_endpoints: 11 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-64ccdff4ca5d73d79d89e817fe83ccfd3d529696df3e6818c3c75e586ae00801.yml +openapi_spec_hash: 21c7b8757fc0cc9415cda1bc06251de6 +config_hash: b3fcacd707da56b21d31ce0baf4fb87d diff --git a/api.md b/api.md index 6c5f238b..6cef9804 100644 --- a/api.md +++ b/api.md @@ -26,11 +26,13 @@ Types: - InvocationCreateResponse - InvocationRetrieveResponse +- InvocationUpdateResponse Methods: - client.apps.invocations.create({ ...params }) -> InvocationCreateResponse - client.apps.invocations.retrieve(id) -> InvocationRetrieveResponse +- client.apps.invocations.update(id, { ...params }) -> InvocationUpdateResponse # Browsers diff --git a/src/resources/apps/apps.ts b/src/resources/apps/apps.ts index 7db22934..dbccad89 100644 --- a/src/resources/apps/apps.ts +++ b/src/resources/apps/apps.ts @@ -13,6 +13,8 @@ import { InvocationCreateParams, InvocationCreateResponse, InvocationRetrieveResponse, + InvocationUpdateParams, + InvocationUpdateResponse, Invocations, } from './invocations'; import { APIPromise } from '../../core/api-promise'; @@ -99,6 +101,8 @@ export declare namespace Apps { Invocations as Invocations, type InvocationCreateResponse as InvocationCreateResponse, type InvocationRetrieveResponse as InvocationRetrieveResponse, + type InvocationUpdateResponse as InvocationUpdateResponse, type InvocationCreateParams as InvocationCreateParams, + type InvocationUpdateParams as InvocationUpdateParams, }; } diff --git a/src/resources/apps/index.ts b/src/resources/apps/index.ts index 52ecdea6..29751c0a 100644 --- a/src/resources/apps/index.ts +++ b/src/resources/apps/index.ts @@ -11,5 +11,7 @@ export { Invocations, type InvocationCreateResponse, type InvocationRetrieveResponse, + type InvocationUpdateResponse, type InvocationCreateParams, + type InvocationUpdateParams, } from './invocations'; diff --git a/src/resources/apps/invocations.ts b/src/resources/apps/invocations.ts index 3f1e23ab..dabbdb6b 100644 --- a/src/resources/apps/invocations.ts +++ b/src/resources/apps/invocations.ts @@ -35,6 +35,25 @@ export class Invocations extends APIResource { retrieve(id: string, options?: RequestOptions): APIPromise { return this._client.get(path`/invocations/${id}`, options); } + + /** + * Update invocation status or output + * + * @example + * ```ts + * const invocation = await client.apps.invocations.update( + * 'id', + * { status: 'succeeded' }, + * ); + * ``` + */ + update( + id: string, + body: InvocationUpdateParams, + options?: RequestOptions, + ): APIPromise { + return this._client.patch(path`/invocations/${id}`, { body, ...options }); + } } export interface InvocationCreateResponse { @@ -109,6 +128,55 @@ export interface InvocationRetrieveResponse { status_reason?: string; } +export interface InvocationUpdateResponse { + /** + * ID of the invocation + */ + id: string; + + /** + * Name of the action invoked + */ + action_name: string; + + /** + * Name of the application + */ + app_name: string; + + /** + * RFC 3339 Nanoseconds timestamp when the invocation started + */ + started_at: string; + + /** + * Status of the invocation + */ + status: 'queued' | 'running' | 'succeeded' | 'failed'; + + /** + * RFC 3339 Nanoseconds timestamp when the invocation finished (null if still + * running) + */ + finished_at?: string | null; + + /** + * Output produced by the action, rendered as a JSON string. This could be: string, + * number, boolean, array, object, or null. + */ + output?: string; + + /** + * Payload provided to the invocation. This is a string that can be parsed as JSON. + */ + payload?: string; + + /** + * Status reason + */ + status_reason?: string; +} + export interface InvocationCreateParams { /** * Name of the action to invoke @@ -125,16 +193,36 @@ export interface InvocationCreateParams { */ version: string; + /** + * If true, invoke asynchronously. When set, the API responds 202 Accepted with + * status "queued". + */ + async?: boolean; + /** * Input data for the action, sent as a JSON string. */ payload?: string; } +export interface InvocationUpdateParams { + /** + * New status for the invocation. + */ + status: 'succeeded' | 'failed'; + + /** + * Updated output of the invocation rendered as JSON string. + */ + output?: string; +} + export declare namespace Invocations { export { type InvocationCreateResponse as InvocationCreateResponse, type InvocationRetrieveResponse as InvocationRetrieveResponse, + type InvocationUpdateResponse as InvocationUpdateResponse, type InvocationCreateParams as InvocationCreateParams, + type InvocationUpdateParams as InvocationUpdateParams, }; } diff --git a/tests/api-resources/apps/invocations.test.ts b/tests/api-resources/apps/invocations.test.ts index 4d76cc87..9a1b028e 100644 --- a/tests/api-resources/apps/invocations.test.ts +++ b/tests/api-resources/apps/invocations.test.ts @@ -30,6 +30,7 @@ describe('resource invocations', () => { action_name: 'analyze', app_name: 'my-app', version: '1.0.0', + async: true, payload: '{"data":"example input"}', }); }); @@ -45,4 +46,21 @@ describe('resource invocations', () => { expect(dataAndResponse.data).toBe(response); expect(dataAndResponse.response).toBe(rawResponse); }); + + // skipped: tests are disabled for the time being + test.skip('update: only required params', async () => { + const responsePromise = client.apps.invocations.update('id', { status: 'succeeded' }); + 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('update: required and optional params', async () => { + const response = await client.apps.invocations.update('id', { status: 'succeeded', output: 'output' }); + }); }); From d17ac2f16636a443c802e305b4003f500a6a8150 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 28 May 2025 03:41:18 +0000 Subject: [PATCH 055/551] chore: improve publish-npm script --latest tag logic --- bin/publish-npm | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/bin/publish-npm b/bin/publish-npm index 4c21181b..2505deca 100644 --- a/bin/publish-npm +++ b/bin/publish-npm @@ -4,19 +4,35 @@ set -eux npm config set '//registry.npmjs.org/:_authToken' "$NPM_TOKEN" -# Build the project yarn build - -# Navigate to the dist directory cd dist -# Get the version from package.json +# Get latest version from npm +# +# If the package doesn't exist, yarn will return +# {"type":"error","data":"Received invalid response from npm."} +# where .data.version doesn't exist so LAST_VERSION will be an empty string. +LAST_VERSION="$(yarn info --json 2> /dev/null | jq -r '.data.version')" + +# Get current version from package.json VERSION="$(node -p "require('./package.json').version")" -# Extract the pre-release tag if it exists +# Check if current version is pre-release (e.g. alpha / beta / rc) +CURRENT_IS_PRERELEASE=false if [[ "$VERSION" =~ -([a-zA-Z]+) ]]; then - # Extract the part before any dot in the pre-release identifier - TAG="${BASH_REMATCH[1]}" + CURRENT_IS_PRERELEASE=true + CURRENT_TAG="${BASH_REMATCH[1]}" +fi + +# Check if last version is a stable release +LAST_IS_STABLE_RELEASE=true +if [[ -z "$LAST_VERSION" || "$LAST_VERSION" =~ -([a-zA-Z]+) ]]; then + LAST_IS_STABLE_RELEASE=false +fi + +# Use a corresponding alpha/beta tag if there already is a stable release and we're publishing a prerelease. +if $CURRENT_IS_PRERELEASE && $LAST_IS_STABLE_RELEASE; then + TAG="$CURRENT_TAG" else TAG="latest" fi From 148c4459862f0a5a75d5f0bd406851bda56402e2 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 28 May 2025 18:45:05 +0000 Subject: [PATCH 056/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- bin/publish-npm | 30 +++++++----------------------- package.json | 2 +- src/version.ts | 2 +- 4 files changed, 10 insertions(+), 26 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 0ee8c012..2537c1f1 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.3.0" + ".": "0.4.0" } diff --git a/bin/publish-npm b/bin/publish-npm index 2505deca..4c21181b 100644 --- a/bin/publish-npm +++ b/bin/publish-npm @@ -4,35 +4,19 @@ set -eux npm config set '//registry.npmjs.org/:_authToken' "$NPM_TOKEN" +# Build the project yarn build -cd dist -# Get latest version from npm -# -# If the package doesn't exist, yarn will return -# {"type":"error","data":"Received invalid response from npm."} -# where .data.version doesn't exist so LAST_VERSION will be an empty string. -LAST_VERSION="$(yarn info --json 2> /dev/null | jq -r '.data.version')" +# Navigate to the dist directory +cd dist -# Get current version from package.json +# Get the version from package.json VERSION="$(node -p "require('./package.json').version")" -# Check if current version is pre-release (e.g. alpha / beta / rc) -CURRENT_IS_PRERELEASE=false +# Extract the pre-release tag if it exists if [[ "$VERSION" =~ -([a-zA-Z]+) ]]; then - CURRENT_IS_PRERELEASE=true - CURRENT_TAG="${BASH_REMATCH[1]}" -fi - -# Check if last version is a stable release -LAST_IS_STABLE_RELEASE=true -if [[ -z "$LAST_VERSION" || "$LAST_VERSION" =~ -([a-zA-Z]+) ]]; then - LAST_IS_STABLE_RELEASE=false -fi - -# Use a corresponding alpha/beta tag if there already is a stable release and we're publishing a prerelease. -if $CURRENT_IS_PRERELEASE && $LAST_IS_STABLE_RELEASE; then - TAG="$CURRENT_TAG" + # Extract the part before any dot in the pre-release identifier + TAG="${BASH_REMATCH[1]}" else TAG="latest" fi diff --git a/package.json b/package.json index c5ebe610..a5f5e931 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.3.0", + "version": "0.4.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 88f4d403..4e7f788e 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.3.0'; // x-release-please-version +export const VERSION = '0.4.0'; // x-release-please-version From 7efa6d2528e70db95dcedf45e3e589d9196dc8b5 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 29 May 2025 02:11:48 +0000 Subject: [PATCH 057/551] chore(internal): codegen related update --- bin/publish-npm | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/bin/publish-npm b/bin/publish-npm index 4c21181b..2505deca 100644 --- a/bin/publish-npm +++ b/bin/publish-npm @@ -4,19 +4,35 @@ set -eux npm config set '//registry.npmjs.org/:_authToken' "$NPM_TOKEN" -# Build the project yarn build - -# Navigate to the dist directory cd dist -# Get the version from package.json +# Get latest version from npm +# +# If the package doesn't exist, yarn will return +# {"type":"error","data":"Received invalid response from npm."} +# where .data.version doesn't exist so LAST_VERSION will be an empty string. +LAST_VERSION="$(yarn info --json 2> /dev/null | jq -r '.data.version')" + +# Get current version from package.json VERSION="$(node -p "require('./package.json').version")" -# Extract the pre-release tag if it exists +# Check if current version is pre-release (e.g. alpha / beta / rc) +CURRENT_IS_PRERELEASE=false if [[ "$VERSION" =~ -([a-zA-Z]+) ]]; then - # Extract the part before any dot in the pre-release identifier - TAG="${BASH_REMATCH[1]}" + CURRENT_IS_PRERELEASE=true + CURRENT_TAG="${BASH_REMATCH[1]}" +fi + +# Check if last version is a stable release +LAST_IS_STABLE_RELEASE=true +if [[ -z "$LAST_VERSION" || "$LAST_VERSION" =~ -([a-zA-Z]+) ]]; then + LAST_IS_STABLE_RELEASE=false +fi + +# Use a corresponding alpha/beta tag if there already is a stable release and we're publishing a prerelease. +if $CURRENT_IS_PRERELEASE && $LAST_IS_STABLE_RELEASE; then + TAG="$CURRENT_TAG" else TAG="latest" fi From 7e63744cbc079d1c3ee05e7cffd53e9830be6116 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 30 May 2025 02:59:32 +0000 Subject: [PATCH 058/551] fix: compat with more runtimes --- src/internal/detect-platform.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/internal/detect-platform.ts b/src/internal/detect-platform.ts index c5e273b9..e82d95c9 100644 --- a/src/internal/detect-platform.ts +++ b/src/internal/detect-platform.ts @@ -85,10 +85,10 @@ const getPlatformProperties = (): PlatformProperties => { return { 'X-Stainless-Lang': 'js', 'X-Stainless-Package-Version': VERSION, - 'X-Stainless-OS': normalizePlatform((globalThis as any).process.platform), - 'X-Stainless-Arch': normalizeArch((globalThis as any).process.arch), + 'X-Stainless-OS': normalizePlatform((globalThis as any).process.platform ?? 'unknown'), + 'X-Stainless-Arch': normalizeArch((globalThis as any).process.arch ?? 'unknown'), 'X-Stainless-Runtime': 'node', - 'X-Stainless-Runtime-Version': (globalThis as any).process.version, + 'X-Stainless-Runtime-Version': (globalThis as any).process.version ?? 'unknown', }; } From d1921ea6aab3a3d9aa74ae4b2d28fc875569f374 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 30 May 2025 12:30:14 +0000 Subject: [PATCH 059/551] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index be606c6d..449c1d2c 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 11 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-64ccdff4ca5d73d79d89e817fe83ccfd3d529696df3e6818c3c75e586ae00801.yml openapi_spec_hash: 21c7b8757fc0cc9415cda1bc06251de6 -config_hash: b3fcacd707da56b21d31ce0baf4fb87d +config_hash: f03f4ba5576f016fbd430540e2e78804 From 810288164a2f98727152b23413749ba87394618f Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 30 May 2025 13:52:00 +0000 Subject: [PATCH 060/551] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index 449c1d2c..928da34d 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 11 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-64ccdff4ca5d73d79d89e817fe83ccfd3d529696df3e6818c3c75e586ae00801.yml openapi_spec_hash: 21c7b8757fc0cc9415cda1bc06251de6 -config_hash: f03f4ba5576f016fbd430540e2e78804 +config_hash: 4bc202cdd2df5cd211fa97e999498052 From 8867846741ca924daa6081766079a08a17b9f38c Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 30 May 2025 13:52:30 +0000 Subject: [PATCH 061/551] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index 928da34d..cd344247 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 11 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-64ccdff4ca5d73d79d89e817fe83ccfd3d529696df3e6818c3c75e586ae00801.yml openapi_spec_hash: 21c7b8757fc0cc9415cda1bc06251de6 -config_hash: 4bc202cdd2df5cd211fa97e999498052 +config_hash: c6bab7ac8da570a5abbcfb19db119b6b From 6099c819813731b2c760d7c9f3600018ccb30f9b Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 30 May 2025 14:39:05 +0000 Subject: [PATCH 062/551] feat(api): update via SDK Studio --- .stats.yml | 4 ++-- src/resources/apps/apps.ts | 3 +-- src/resources/apps/deployments.ts | 2 +- src/resources/apps/invocations.ts | 6 +++--- src/resources/browsers.ts | 10 +++++----- 5 files changed, 12 insertions(+), 13 deletions(-) diff --git a/.stats.yml b/.stats.yml index cd344247..dbb369ac 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 11 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-64ccdff4ca5d73d79d89e817fe83ccfd3d529696df3e6818c3c75e586ae00801.yml -openapi_spec_hash: 21c7b8757fc0cc9415cda1bc06251de6 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-1f7397b87108a992979b665f45bf0aee5b10387e8124f4768c4c7852ba0b23d7.yml +openapi_spec_hash: e5460337788e7eab0d8f05ef2f55086e config_hash: c6bab7ac8da570a5abbcfb19db119b6b diff --git a/src/resources/apps/apps.ts b/src/resources/apps/apps.ts index dbccad89..2b982f6a 100644 --- a/src/resources/apps/apps.ts +++ b/src/resources/apps/apps.ts @@ -25,8 +25,7 @@ export class Apps extends APIResource { invocations: InvocationsAPI.Invocations = new InvocationsAPI.Invocations(this._client); /** - * List application versions for the authenticated user. Optionally filter by app - * name and/or version label. + * List applications. Optionally filter by app name and/or version label. * * @example * ```ts diff --git a/src/resources/apps/deployments.ts b/src/resources/apps/deployments.ts index 30fa7ca4..a5cf4639 100644 --- a/src/resources/apps/deployments.ts +++ b/src/resources/apps/deployments.ts @@ -11,7 +11,7 @@ import { path } from '../../internal/utils/path'; export class Deployments extends APIResource { /** - * Deploy a new application + * Deploy a new application and associated actions to Kernel. * * @example * ```ts diff --git a/src/resources/apps/invocations.ts b/src/resources/apps/invocations.ts index dabbdb6b..74795509 100644 --- a/src/resources/apps/invocations.ts +++ b/src/resources/apps/invocations.ts @@ -7,7 +7,7 @@ import { path } from '../../internal/utils/path'; export class Invocations extends APIResource { /** - * Invoke an application + * Invoke an action. * * @example * ```ts @@ -23,7 +23,7 @@ export class Invocations extends APIResource { } /** - * Get an app invocation by id + * Get details about an invocation's status and output. * * @example * ```ts @@ -37,7 +37,7 @@ export class Invocations extends APIResource { } /** - * Update invocation status or output + * Update an invocation's status or output. * * @example * ```ts diff --git a/src/resources/browsers.ts b/src/resources/browsers.ts index b66c68f9..8d043c88 100644 --- a/src/resources/browsers.ts +++ b/src/resources/browsers.ts @@ -9,7 +9,7 @@ import { path } from '../internal/utils/path'; export class Browsers extends APIResource { /** - * Create Browser Session + * Create a new browser session from within an action. * * @example * ```ts @@ -23,7 +23,7 @@ export class Browsers extends APIResource { } /** - * Get Browser Session by ID + * Get information about a browser session. * * @example * ```ts @@ -37,7 +37,7 @@ export class Browsers extends APIResource { } /** - * List active browser sessions for the authenticated user + * List active browser sessions * * @example * ```ts @@ -49,7 +49,7 @@ export class Browsers extends APIResource { } /** - * Delete a persistent browser session by persistent_id query parameter. + * Delete a persistent browser session by its persistent_id. * * @example * ```ts @@ -68,7 +68,7 @@ export class Browsers extends APIResource { } /** - * Delete Browser Session by ID + * Delete a browser session by ID * * @example * ```ts From 9c9825d7e225db18624ba00d0461600520d5ffa7 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 30 May 2025 14:43:37 +0000 Subject: [PATCH 063/551] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index dbb369ac..03ed9444 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 11 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-1f7397b87108a992979b665f45bf0aee5b10387e8124f4768c4c7852ba0b23d7.yml -openapi_spec_hash: e5460337788e7eab0d8f05ef2f55086e +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-7af0ef1d19efb9231c098855b72668646401afd5e00400953aca0728f7ceadb7.yml +openapi_spec_hash: fb160fe8ee0cda0a1ce9766c8195ee68 config_hash: c6bab7ac8da570a5abbcfb19db119b6b From 04de8bfe47320e35ecdda96fb79c65724b6a74a3 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 30 May 2025 17:24:19 +0000 Subject: [PATCH 064/551] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 03ed9444..a9ddb6d5 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 11 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-7af0ef1d19efb9231c098855b72668646401afd5e00400953aca0728f7ceadb7.yml -openapi_spec_hash: fb160fe8ee0cda0a1ce9766c8195ee68 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-b91d95f8e40f28d0e455d749b86c4d864ac15a264dcc2c5b317f626ff605ce2c.yml +openapi_spec_hash: befc3a683593ad7d832cfa9f0db941aa config_hash: c6bab7ac8da570a5abbcfb19db119b6b From a768b3fd12a5aa501bbd1b82b089a029b2ba1a1e Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 31 May 2025 03:10:23 +0000 Subject: [PATCH 065/551] chore(deps): bump eslint-plugin-prettier --- package.json | 5 +---- yarn.lock | 34 ++++++++++++++-------------------- 2 files changed, 15 insertions(+), 24 deletions(-) diff --git a/package.json b/package.json index a5f5e931..b9272424 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,7 @@ "@typescript-eslint/eslint-plugin": "8.31.1", "@typescript-eslint/parser": "8.31.1", "eslint": "^9.20.1", - "eslint-plugin-prettier": "^5.2.3", + "eslint-plugin-prettier": "^5.4.1", "eslint-plugin-unused-imports": "^4.1.4", "iconv-lite": "^0.6.3", "jest": "^29.4.0", @@ -46,9 +46,6 @@ "tsconfig-paths": "^4.0.0", "typescript": "5.8.3" }, - "resolutions": { - "synckit": "0.8.8" - }, "imports": { "@onkernel/sdk": ".", "@onkernel/sdk/*": "./src/*" diff --git a/yarn.lock b/yarn.lock index 43da555d..49d3eb8f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -714,10 +714,10 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" -"@pkgr/core@^0.1.0": - version "0.1.1" - resolved "https://registry.yarnpkg.com/@pkgr/core/-/core-0.1.1.tgz#1ec17e2edbec25c8306d424ecfbf13c7de1aaa31" - integrity sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA== +"@pkgr/core@^0.2.4": + version "0.2.4" + resolved "https://registry.yarnpkg.com/@pkgr/core/-/core-0.2.4.tgz#d897170a2b0ba51f78a099edccd968f7b103387c" + integrity sha512-ROFF39F6ZrnzSUEmQQZUar0Jt4xVoP9WnDRdWwF4NNcXs3xBTLgBUDoOwW141y1jP+S8nahIbdxbFC7IShw9Iw== "@sinclair/typebox@^0.27.8": version "0.27.8" @@ -1547,13 +1547,13 @@ escape-string-regexp@^4.0.0: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== -eslint-plugin-prettier@^5.2.3: - version "5.2.3" - resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.3.tgz#c4af01691a6fa9905207f0fbba0d7bea0902cce5" - integrity sha512-qJ+y0FfCp/mQYQ/vWQ3s7eUlFEL4PyKfAJxsnYTJ4YT73nsJBWqmEpFryxV9OeUiqmsTsYJ5Y+KDNaeP31wrRw== +eslint-plugin-prettier@^5.4.1: + version "5.4.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-5.4.1.tgz#99b55d7dd70047886b2222fdd853665f180b36af" + integrity sha512-9dF+KuU/Ilkq27A8idRP7N2DH8iUR6qXcjF3FR2wETY21PZdBrIjwCau8oboyGj9b7etWmTGEeM8e7oOed6ZWg== dependencies: prettier-linter-helpers "^1.0.0" - synckit "^0.9.1" + synckit "^0.11.7" eslint-plugin-unused-imports@^4.1.4: version "4.1.4" @@ -3198,13 +3198,12 @@ supports-preserve-symlinks-flag@^1.0.0: resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== -synckit@0.8.8, synckit@^0.9.1: - version "0.8.8" - resolved "https://registry.yarnpkg.com/synckit/-/synckit-0.8.8.tgz#fe7fe446518e3d3d49f5e429f443cf08b6edfcd7" - integrity sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ== +synckit@^0.11.7: + version "0.11.8" + resolved "https://registry.yarnpkg.com/synckit/-/synckit-0.11.8.tgz#b2aaae998a4ef47ded60773ad06e7cb821f55457" + integrity sha512-+XZ+r1XGIJGeQk3VvXhT6xx/VpbHsRzsTkGgF6E5RX9TTXD0118l87puaEBZ566FhqblC6U0d4XnubznJDm30A== dependencies: - "@pkgr/core" "^0.1.0" - tslib "^2.6.2" + "@pkgr/core" "^0.2.4" test-exclude@^6.0.0: version "6.0.0" @@ -3308,11 +3307,6 @@ tsconfig-paths@^4.0.0: minimist "^1.2.6" strip-bom "^3.0.0" -tslib@^2.6.2: - version "2.6.2" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" - integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== - tslib@^2.8.1: version "2.8.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" From 059ba2dac91393402f08ce18f3b23945c717dc7c Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 31 May 2025 03:22:57 +0000 Subject: [PATCH 066/551] chore(internal): update jest config --- jest.config.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/jest.config.ts b/jest.config.ts index a3ef35c7..f21115cf 100644 --- a/jest.config.ts +++ b/jest.config.ts @@ -15,6 +15,7 @@ const config: JestConfigWithTsJest = { '/dist/', '/deno/', '/deno_tests/', + '/packages/', ], testPathIgnorePatterns: ['scripts'], }; From c1a208c8d35d1240fd4bfeffbb352835032a95ae Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 3 Jun 2025 04:43:52 +0000 Subject: [PATCH 067/551] chore: adjust eslint.config.mjs ignore pattern --- eslint.config.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eslint.config.mjs b/eslint.config.mjs index 4d61d875..341aac52 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -10,7 +10,7 @@ export default tseslint.config( parserOptions: { sourceType: 'module' }, }, files: ['**/*.ts', '**/*.mts', '**/*.cts', '**/*.js', '**/*.mjs', '**/*.cjs'], - ignores: ['dist/**'], + ignores: ['dist/'], plugins: { '@typescript-eslint': tseslint.plugin, 'unused-imports': unusedImports, From bd1d71888574ec14b02d66e75ced2ac85f5325c8 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 3 Jun 2025 19:42:54 +0000 Subject: [PATCH 068/551] feat(api): update via SDK Studio --- .stats.yml | 4 ++-- src/resources/browsers.ts | 6 ++++++ tests/api-resources/browsers.test.ts | 1 + 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index a9ddb6d5..d6546666 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 11 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-b91d95f8e40f28d0e455d749b86c4d864ac15a264dcc2c5b317f626ff605ce2c.yml -openapi_spec_hash: befc3a683593ad7d832cfa9f0db941aa +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-4502c65bef0843a6ae96d23bba075433af6bab49b55b544b1522f63e7881c00c.yml +openapi_spec_hash: 3e67b77bbc8cd6155b8f66f3271f2643 config_hash: c6bab7ac8da570a5abbcfb19db119b6b diff --git a/src/resources/browsers.ts b/src/resources/browsers.ts index 8d043c88..adc075f2 100644 --- a/src/resources/browsers.ts +++ b/src/resources/browsers.ts @@ -175,6 +175,12 @@ export interface BrowserCreateParams { * 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 { diff --git a/tests/api-resources/browsers.test.ts b/tests/api-resources/browsers.test.ts index 8bb89aa9..c6f09675 100644 --- a/tests/api-resources/browsers.test.ts +++ b/tests/api-resources/browsers.test.ts @@ -25,6 +25,7 @@ describe('resource browsers', () => { const response = await client.browsers.create({ invocation_id: 'rr33xuugxj9h0bkf1rdt2bet', persistence: { id: 'my-awesome-browser-for-user-1234' }, + stealth: true, }); }); From a97410d47eb656586b3e7516e398de127aa373b9 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 4 Jun 2025 03:55:50 +0000 Subject: [PATCH 069/551] chore(docs): use top-level-await in example snippets --- README.md | 58 ++++++++++++++++++++++--------------------------------- 1 file changed, 23 insertions(+), 35 deletions(-) diff --git a/README.md b/README.md index 8db99d17..22327b87 100644 --- a/README.md +++ b/README.md @@ -27,18 +27,14 @@ const client = new Kernel({ environment: 'development', // defaults to 'production' }); -async function main() { - const deployment = await client.apps.deployments.create({ - entrypoint_rel_path: 'main.ts', - file: fs.createReadStream('path/to/file'), - env_vars: { OPENAI_API_KEY: 'x' }, - version: '1.0.0', - }); - - console.log(deployment.apps); -} +const deployment = await client.apps.deployments.create({ + entrypoint_rel_path: 'main.ts', + file: fs.createReadStream('path/to/file'), + env_vars: { OPENAI_API_KEY: 'x' }, + version: '1.0.0', +}); -main(); +console.log(deployment.apps); ``` ### Request & Response types @@ -54,15 +50,11 @@ const client = new Kernel({ environment: 'development', // defaults to 'production' }); -async function main() { - const params: Kernel.BrowserCreateParams = { - invocation_id: 'REPLACE_ME', - persistence: { id: 'browser-for-user-1234' }, - }; - const browser: Kernel.BrowserCreateResponse = await client.browsers.create(params); -} - -main(); +const params: Kernel.BrowserCreateParams = { + invocation_id: 'REPLACE_ME', + persistence: { id: 'browser-for-user-1234' }, +}; +const browser: Kernel.BrowserCreateResponse = await client.browsers.create(params); ``` Documentation for each method, request param, and response field are available in docstrings and will appear on hover in most modern editors. @@ -119,21 +111,17 @@ a subclass of `APIError` will be thrown: ```ts -async function main() { - const browser = await client.browsers - .create({ invocation_id: 'REPLACE_ME', persistence: { id: 'browser-for-user-1234' } }) - .catch(async (err) => { - if (err instanceof Kernel.APIError) { - console.log(err.status); // 400 - console.log(err.name); // BadRequestError - console.log(err.headers); // {server: 'nginx', ...} - } else { - throw err; - } - }); -} - -main(); +const browser = await client.browsers + .create({ invocation_id: 'REPLACE_ME', persistence: { id: 'browser-for-user-1234' } }) + .catch(async (err) => { + if (err instanceof Kernel.APIError) { + console.log(err.status); // 400 + console.log(err.name); // BadRequestError + console.log(err.headers); // {server: 'nginx', ...} + } else { + throw err; + } + }); ``` Error codes are as follows: From 8bc20c70feef51a156ff4d5b947668b926fa293e Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 4 Jun 2025 04:25:56 +0000 Subject: [PATCH 070/551] chore(internal): fix readablestream types in node 20 --- scripts/build | 2 -- src/internal/shim-types.d.ts | 28 ---------------------------- src/internal/shim-types.ts | 26 ++++++++++++++++++++++++++ src/internal/shims.ts | 4 ++-- 4 files changed, 28 insertions(+), 32 deletions(-) delete mode 100644 src/internal/shim-types.d.ts create mode 100644 src/internal/shim-types.ts diff --git a/scripts/build b/scripts/build index 6a52f04a..b2ad914b 100755 --- a/scripts/build +++ b/scripts/build @@ -37,8 +37,6 @@ npm exec tsc-multi # when building .mjs node scripts/utils/fix-index-exports.cjs cp tsconfig.dist-src.json dist/src/tsconfig.json -cp src/internal/shim-types.d.ts dist/internal/shim-types.d.ts -cp src/internal/shim-types.d.ts dist/internal/shim-types.d.mts node scripts/utils/postprocess-files.cjs diff --git a/src/internal/shim-types.d.ts b/src/internal/shim-types.d.ts deleted file mode 100644 index fe48144f..00000000 --- a/src/internal/shim-types.d.ts +++ /dev/null @@ -1,28 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -/** - * Shims for types that we can't always rely on being available globally. - * - * Note: these only exist at the type-level, there is no corresponding runtime - * version for any of these symbols. - */ - -/** - * In order to properly access the global `NodeJS` type, if it's available, we - * need to make use of declaration shadowing. Without this, any checks for the - * presence of `NodeJS.ReadableStream` will fail. - */ -declare namespace NodeJS { - interface ReadableStream {} -} - -type HasProperties = keyof T extends never ? false : true; - -// @ts-ignore -type _ReadableStream = - // @ts-ignore - HasProperties extends true ? NodeJS.ReadableStream : ReadableStream; - -// @ts-ignore -declare const _ReadableStream: unknown extends typeof ReadableStream ? never : typeof ReadableStream; -export { _ReadableStream as ReadableStream }; diff --git a/src/internal/shim-types.ts b/src/internal/shim-types.ts new file mode 100644 index 00000000..8ddf7b0a --- /dev/null +++ b/src/internal/shim-types.ts @@ -0,0 +1,26 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +/** + * Shims for types that we can't always rely on being available globally. + * + * Note: these only exist at the type-level, there is no corresponding runtime + * version for any of these symbols. + */ + +type NeverToAny = T extends never ? any : T; + +/** @ts-ignore */ +type _DOMReadableStream = globalThis.ReadableStream; + +/** @ts-ignore */ +type _NodeReadableStream = import('stream/web').ReadableStream; + +type _ConditionalNodeReadableStream = + typeof globalThis extends { ReadableStream: any } ? never : _NodeReadableStream; + +type _ReadableStream = NeverToAny< + | ([0] extends [1 & _DOMReadableStream] ? never : _DOMReadableStream) + | ([0] extends [1 & _ConditionalNodeReadableStream] ? never : _ConditionalNodeReadableStream) +>; + +export type { _ReadableStream as ReadableStream }; diff --git a/src/internal/shims.ts b/src/internal/shims.ts index 9b04cd93..006524fe 100644 --- a/src/internal/shims.ts +++ b/src/internal/shims.ts @@ -7,8 +7,8 @@ * messages in cases where an environment isn't fully supported. */ -import { type Fetch } from './builtin-types'; -import { type ReadableStream } from './shim-types'; +import type { Fetch } from './builtin-types'; +import type { ReadableStream } from './shim-types'; export function getDefaultFetch(): Fetch { if (typeof fetch !== 'undefined') { From 60fa4966e1539d672c2a2b5f5dd0aa99f042d7b0 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 5 Jun 2025 14:39:34 +0000 Subject: [PATCH 071/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 2537c1f1..f1c1e588 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.4.0" + ".": "0.5.0" } diff --git a/package.json b/package.json index b9272424..6b06ec5d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.4.0", + "version": "0.5.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 4e7f788e..1f5d1586 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.4.0'; // x-release-please-version +export const VERSION = '0.5.0'; // x-release-please-version From 9ba11ba1a5c2afb2e9a1fede3b7a77a2f2a31e6d Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 7 Jun 2025 03:29:18 +0000 Subject: [PATCH 072/551] chore: avoid type error in certain environments --- src/internal/uploads.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/internal/uploads.ts b/src/internal/uploads.ts index a708afa3..4c04463f 100644 --- a/src/internal/uploads.ts +++ b/src/internal/uploads.ts @@ -138,7 +138,7 @@ export const createForm = async >( // We check for Blob not File because Bun.File doesn't inherit from File, // but they both inherit from Blob and have a `name` property at runtime. -const isNamedBlob = (value: object) => value instanceof Blob && 'name' in value; +const isNamedBlob = (value: unknown) => value instanceof Blob && 'name' in value; const isUploadable = (value: unknown) => typeof value === 'object' && From 164fad12da257aa7d0edb1c1ed380087be0b4e6d Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 14 Jun 2025 02:25:06 +0000 Subject: [PATCH 073/551] =?UTF-8?q?fix:=20publish=20script=20=E2=80=94=20h?= =?UTF-8?q?andle=20NPM=20errors=20correctly?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bin/publish-npm | 34 +++++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/bin/publish-npm b/bin/publish-npm index 2505deca..fa2243d2 100644 --- a/bin/publish-npm +++ b/bin/publish-npm @@ -7,15 +7,35 @@ npm config set '//registry.npmjs.org/:_authToken' "$NPM_TOKEN" yarn build cd dist +# Get package name and version from package.json +PACKAGE_NAME="$(jq -r -e '.name' ./package.json)" +VERSION="$(jq -r -e '.version' ./package.json)" + # Get latest version from npm # -# If the package doesn't exist, yarn will return -# {"type":"error","data":"Received invalid response from npm."} -# where .data.version doesn't exist so LAST_VERSION will be an empty string. -LAST_VERSION="$(yarn info --json 2> /dev/null | jq -r '.data.version')" - -# Get current version from package.json -VERSION="$(node -p "require('./package.json').version")" +# If the package doesn't exist, npm will return: +# { +# "error": { +# "code": "E404", +# "summary": "Unpublished on 2025-06-05T09:54:53.528Z", +# "detail": "'the_package' is not in this registry..." +# } +# } +NPM_INFO="$(npm view "$PACKAGE_NAME" version --json 2>/dev/null || true)" + +# Check if we got an E404 error +if echo "$NPM_INFO" | jq -e '.error.code == "E404"' > /dev/null 2>&1; then + # Package doesn't exist yet, no last version + LAST_VERSION="" +elif echo "$NPM_INFO" | jq -e '.error' > /dev/null 2>&1; then + # Report other errors + echo "ERROR: npm returned unexpected data:" + echo "$NPM_INFO" + exit 1 +else + # Success - get the version + LAST_VERSION=$(echo "$NPM_INFO" | jq -r '.') # strip quotes +fi # Check if current version is pre-release (e.g. alpha / beta / rc) CURRENT_IS_PRERELEASE=false From 00267c920b7fda0f00ad600322faba32f6ab8e7a Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 14 Jun 2025 02:38:55 +0000 Subject: [PATCH 074/551] chore(internal): add pure annotations, make base APIResource abstract --- package.json | 2 +- scripts/build | 2 +- src/core/resource.ts | 2 +- src/internal/headers.ts | 10 +++++----- src/internal/uploads.ts | 2 +- src/internal/utils/log.ts | 2 +- src/internal/utils/path.ts | 2 +- src/internal/utils/values.ts | 3 +++ tsc-multi.json | 12 ++++++++++-- yarn.lock | 6 +++--- 10 files changed, 27 insertions(+), 16 deletions(-) diff --git a/package.json b/package.json index 6b06ec5d..13306fb8 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,7 @@ "publint": "^0.2.12", "ts-jest": "^29.1.0", "ts-node": "^10.5.0", - "tsc-multi": "https://github.com/stainless-api/tsc-multi/releases/download/v1.1.4/tsc-multi-1.1.4.tgz", + "tsc-multi": "https://github.com/stainless-api/tsc-multi/releases/download/v1.1.7/tsc-multi.tgz", "tsconfig-paths": "^4.0.0", "typescript": "5.8.3" }, diff --git a/scripts/build b/scripts/build index b2ad914b..a008cb00 100755 --- a/scripts/build +++ b/scripts/build @@ -31,7 +31,7 @@ fi node scripts/utils/make-dist-package-json.cjs > dist/package.json # build to .js/.mjs/.d.ts files -npm exec tsc-multi +./node_modules/.bin/tsc-multi # we need to patch index.js so that `new module.exports()` works for cjs backwards # compat. No way to get that from index.ts because it would cause compile errors # when building .mjs diff --git a/src/core/resource.ts b/src/core/resource.ts index b8cfaddc..f1dd8034 100644 --- a/src/core/resource.ts +++ b/src/core/resource.ts @@ -2,7 +2,7 @@ import type { Kernel } from '../client'; -export class APIResource { +export abstract class APIResource { protected _client: Kernel; constructor(client: Kernel) { diff --git a/src/internal/headers.ts b/src/internal/headers.ts index 5cc03ce3..c724a9d2 100644 --- a/src/internal/headers.ts +++ b/src/internal/headers.ts @@ -1,5 +1,7 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +import { isReadonlyArray } from './utils/values'; + type HeaderValue = string | undefined | null; export type HeadersLike = | Headers @@ -9,7 +11,7 @@ export type HeadersLike = | null | NullableHeaders; -const brand_privateNullableHeaders = Symbol('brand.privateNullableHeaders'); +const brand_privateNullableHeaders = /* @__PURE__ */ Symbol('brand.privateNullableHeaders'); /** * @internal @@ -25,8 +27,6 @@ export type NullableHeaders = { nulls: Set; }; -const isArray = Array.isArray as (val: unknown) => val is readonly unknown[]; - function* iterateHeaders(headers: HeadersLike): IterableIterator { if (!headers) return; @@ -43,7 +43,7 @@ function* iterateHeaders(headers: HeadersLike): IterableIterator; if (headers instanceof Headers) { iter = headers.entries(); - } else if (isArray(headers)) { + } else if (isReadonlyArray(headers)) { iter = headers; } else { shouldClear = true; @@ -52,7 +52,7 @@ function* iterateHeaders(headers: HeadersLike): IterableIterator>(); +const supportsFormDataMap = /** @__PURE__ */ new WeakMap>(); /** * node-fetch doesn't support the global FormData object in recent node versions. Instead of sending diff --git a/src/internal/utils/log.ts b/src/internal/utils/log.ts index 48652621..44d8f651 100644 --- a/src/internal/utils/log.ts +++ b/src/internal/utils/log.ts @@ -58,7 +58,7 @@ const noopLogger = { debug: noop, }; -let cachedLoggers = new WeakMap(); +let cachedLoggers = /** @__PURE__ */ new WeakMap(); export function loggerFor(client: Kernel): Logger { const logger = client.logger; diff --git a/src/internal/utils/path.ts b/src/internal/utils/path.ts index e9bcaf52..8abf2784 100644 --- a/src/internal/utils/path.ts +++ b/src/internal/utils/path.ts @@ -60,4 +60,4 @@ export const createPathTagFunction = (pathEncoder = encodeURIPath) => /** * URI-encodes path params and ensures no unsafe /./ or /../ path segments are introduced. */ -export const path = createPathTagFunction(encodeURIPath); +export const path = /* @__PURE__ */ createPathTagFunction(encodeURIPath); diff --git a/src/internal/utils/values.ts b/src/internal/utils/values.ts index 0953aeae..667646d6 100644 --- a/src/internal/utils/values.ts +++ b/src/internal/utils/values.ts @@ -9,6 +9,9 @@ export const isAbsoluteURL = (url: string): boolean => { return startsWithSchemeRegexp.test(url); }; +export let isArray = (val: unknown): val is unknown[] => ((isArray = Array.isArray), isArray(val)); +export let isReadonlyArray = isArray as (val: unknown) => val is readonly unknown[]; + /** Returns an object if the given value isn't an object, otherwise returns as-is */ export function maybeObj(x: unknown): object { if (typeof x !== 'object') { diff --git a/tsc-multi.json b/tsc-multi.json index 170bac7a..384ddac5 100644 --- a/tsc-multi.json +++ b/tsc-multi.json @@ -1,7 +1,15 @@ { "targets": [ - { "extname": ".js", "module": "commonjs", "shareHelpers": "internal/tslib.js" }, - { "extname": ".mjs", "module": "esnext", "shareHelpers": "internal/tslib.mjs" } + { + "extname": ".js", + "module": "commonjs", + "shareHelpers": "internal/tslib.js" + }, + { + "extname": ".mjs", + "module": "esnext", + "shareHelpers": "internal/tslib.mjs" + } ], "projects": ["tsconfig.build.json"] } diff --git a/yarn.lock b/yarn.lock index 49d3eb8f..c611c53b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3283,9 +3283,9 @@ ts-node@^10.5.0: v8-compile-cache-lib "^3.0.0" yn "3.1.1" -"tsc-multi@https://github.com/stainless-api/tsc-multi/releases/download/v1.1.4/tsc-multi-1.1.4.tgz": - version "1.1.4" - resolved "https://github.com/stainless-api/tsc-multi/releases/download/v1.1.4/tsc-multi-1.1.4.tgz#cbed459a9e902f5295ec3daaf1c7aa3b10427e55" +"tsc-multi@https://github.com/stainless-api/tsc-multi/releases/download/v1.1.7/tsc-multi.tgz": + version "1.1.7" + resolved "https://github.com/stainless-api/tsc-multi/releases/download/v1.1.7/tsc-multi.tgz#52f40adf8b808bd0b633346d11cc4a8aeea465cd" dependencies: debug "^4.3.7" fast-glob "^3.3.2" From 22b8a4a3bd9d95f7c3baf8d464af80b53a8fa03c Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 14 Jun 2025 19:42:31 +0000 Subject: [PATCH 075/551] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index d6546666..d2422bd1 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 11 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-4502c65bef0843a6ae96d23bba075433af6bab49b55b544b1522f63e7881c00c.yml -openapi_spec_hash: 3e67b77bbc8cd6155b8f66f3271f2643 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-fa302aa17477431aaa82682fe71bdbb519270815fdc917477e1d7e606411be50.yml +openapi_spec_hash: 291cb0245ba582712900f0fb5cf44ee4 config_hash: c6bab7ac8da570a5abbcfb19db119b6b From c6bf002d22b02c8d82bc71ac01134389625d9231 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 14 Jun 2025 19:47:33 +0000 Subject: [PATCH 076/551] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index d2422bd1..8826a54f 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 11 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-fa302aa17477431aaa82682fe71bdbb519270815fdc917477e1d7e606411be50.yml -openapi_spec_hash: 291cb0245ba582712900f0fb5cf44ee4 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-e622f6886b1153050eb4ee9fda37fff8b36b38b52e5d247ea172deb2594bf9d6.yml +openapi_spec_hash: 3fa294f57c68b34e526a52bdd86eb562 config_hash: c6bab7ac8da570a5abbcfb19db119b6b From 53d81cfde2813d379c52904c6c110cd0e7c15034 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 14 Jun 2025 19:59:25 +0000 Subject: [PATCH 077/551] feat(api): update via SDK Studio --- .stats.yml | 8 +- api.md | 14 + src/client.ts | 17 ++ src/resources/deployments.ts | 381 ++++++++++++++++++++++++ src/resources/index.ts | 7 + tests/api-resources/deployments.test.ts | 61 ++++ 6 files changed, 484 insertions(+), 4 deletions(-) create mode 100644 src/resources/deployments.ts create mode 100644 tests/api-resources/deployments.test.ts diff --git a/.stats.yml b/.stats.yml index 8826a54f..f34bfc3d 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 11 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-e622f6886b1153050eb4ee9fda37fff8b36b38b52e5d247ea172deb2594bf9d6.yml -openapi_spec_hash: 3fa294f57c68b34e526a52bdd86eb562 -config_hash: c6bab7ac8da570a5abbcfb19db119b6b +configured_endpoints: 14 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-d2dfee8d576aa73f6075e6da61228571cb2e844b969a06067e34e43eb7898554.yml +openapi_spec_hash: 9981744bf9c27426cdf721f7b27cf093 +config_hash: a085d1b39ddf0b26ee798501a9f47e20 diff --git a/api.md b/api.md index 6cef9804..b27a84af 100644 --- a/api.md +++ b/api.md @@ -1,3 +1,17 @@ +# Deployments + +Types: + +- DeploymentCreateResponse +- DeploymentRetrieveResponse +- DeploymentFollowResponse + +Methods: + +- client.deployments.create({ ...params }) -> DeploymentCreateResponse +- client.deployments.retrieve(id) -> DeploymentRetrieveResponse +- client.deployments.follow(id) -> DeploymentFollowResponse + # Apps Types: diff --git a/src/client.ts b/src/client.ts index 84b00f00..188384af 100644 --- a/src/client.ts +++ b/src/client.ts @@ -29,6 +29,13 @@ import { BrowserRetrieveResponse, Browsers, } from './resources/browsers'; +import { + DeploymentCreateParams, + DeploymentCreateResponse, + DeploymentFollowResponse, + DeploymentRetrieveResponse, + Deployments, +} from './resources/deployments'; import { readEnv } from './internal/utils/env'; import { formatRequestDetails, loggerFor } from './internal/utils/log'; import { isEmptyObj } from './internal/utils/values'; @@ -724,14 +731,24 @@ export class Kernel { static toFile = Uploads.toFile; + deployments: API.Deployments = new API.Deployments(this); apps: API.Apps = new API.Apps(this); browsers: API.Browsers = new API.Browsers(this); } +Kernel.Deployments = Deployments; Kernel.Apps = Apps; Kernel.Browsers = Browsers; export declare namespace Kernel { export type RequestOptions = Opts.RequestOptions; + export { + Deployments as Deployments, + type DeploymentCreateResponse as DeploymentCreateResponse, + type DeploymentRetrieveResponse as DeploymentRetrieveResponse, + type DeploymentFollowResponse as DeploymentFollowResponse, + type DeploymentCreateParams as DeploymentCreateParams, + }; + export { Apps as Apps, type AppListResponse as AppListResponse, type AppListParams as AppListParams }; export { diff --git a/src/resources/deployments.ts b/src/resources/deployments.ts new file mode 100644 index 00000000..f1eec5ea --- /dev/null +++ b/src/resources/deployments.ts @@ -0,0 +1,381 @@ +// 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 { Stream } from '../core/streaming'; +import { type Uploadable } from '../core/uploads'; +import { buildHeaders } from '../internal/headers'; +import { RequestOptions } from '../internal/request-options'; +import { multipartFormRequestOptions } from '../internal/uploads'; +import { path } from '../internal/utils/path'; + +export class Deployments extends APIResource { + /** + * Create a new deployment. + * + * @example + * ```ts + * const deployment = await client.deployments.create({ + * entrypoint_rel_path: 'src/app.py', + * file: fs.createReadStream('path/to/file'), + * }); + * ``` + */ + create(body: DeploymentCreateParams, options?: RequestOptions): APIPromise { + return this._client.post('/deployments', multipartFormRequestOptions({ body, ...options }, this._client)); + } + + /** + * Get information about a deployment's status. + * + * @example + * ```ts + * const deployment = await client.deployments.retrieve('id'); + * ``` + */ + retrieve(id: string, options?: RequestOptions): APIPromise { + return this._client.get(path`/deployments/${id}`, options); + } + + /** + * Establishes a Server-Sent Events (SSE) stream that delivers real-time logs and + * status updates for a deployment. The stream terminates automatically once the + * deployment reaches a terminal state. + * + * @example + * ```ts + * const response = await client.deployments.follow('id'); + * ``` + */ + follow(id: string, options?: RequestOptions): APIPromise> { + return this._client.get(path`/deployments/${id}/events`, { + ...options, + headers: buildHeaders([{ Accept: 'text/event-stream' }, options?.headers]), + stream: true, + }) as APIPromise>; + } +} + +/** + * Deployment record information. + */ +export interface DeploymentCreateResponse { + /** + * Unique identifier for the deployment + */ + id: string; + + /** + * Timestamp when the deployment was created + */ + created_at: string; + + /** + * Deployment region code + */ + region: string; + + /** + * Current status of the deployment + */ + status: 'queued' | 'in_progress' | 'running' | 'failed' | 'stopped'; + + /** + * Relative path to the application entrypoint + */ + entrypoint_rel_path?: string; + + /** + * Environment variables configured for this deployment + */ + env_vars?: Record; + + /** + * Status reason + */ + status_reason?: string; + + /** + * Timestamp when the deployment was last updated + */ + updated_at?: string | null; +} + +/** + * Deployment record information. + */ +export interface DeploymentRetrieveResponse { + /** + * Unique identifier for the deployment + */ + id: string; + + /** + * Timestamp when the deployment was created + */ + created_at: string; + + /** + * Deployment region code + */ + region: string; + + /** + * Current status of the deployment + */ + status: 'queued' | 'in_progress' | 'running' | 'failed' | 'stopped'; + + /** + * Relative path to the application entrypoint + */ + entrypoint_rel_path?: string; + + /** + * Environment variables configured for this deployment + */ + env_vars?: Record; + + /** + * Status reason + */ + status_reason?: string; + + /** + * Timestamp when the deployment was last updated + */ + updated_at?: string | null; +} + +/** + * Union type representing any deployment event. + */ +export type DeploymentFollowResponse = + | DeploymentFollowResponse.LogEvent + | DeploymentFollowResponse.DeploymentStateEvent + | DeploymentFollowResponse.AppVersionSummaryEvent + | DeploymentFollowResponse.ErrorEvent; + +export namespace DeploymentFollowResponse { + /** + * A log entry from the application. + */ + export interface LogEvent { + /** + * Event type identifier (always "log"). + */ + event: 'log'; + + /** + * Log message text. + */ + message: string; + + /** + * Time the log entry was produced. + */ + timestamp?: string; + } + + /** + * An event representing the current state of a deployment. + */ + export interface DeploymentStateEvent { + /** + * Deployment record information. + */ + deployment: DeploymentStateEvent.Deployment; + + /** + * Event type identifier (always "deployment_state"). + */ + event: 'deployment_state'; + + /** + * Time the state was reported. + */ + timestamp?: string; + } + + export namespace DeploymentStateEvent { + /** + * Deployment record information. + */ + export interface Deployment { + /** + * Unique identifier for the deployment + */ + id: string; + + /** + * Timestamp when the deployment was created + */ + created_at: string; + + /** + * Deployment region code + */ + region: string; + + /** + * Current status of the deployment + */ + status: 'queued' | 'in_progress' | 'running' | 'failed' | 'stopped'; + + /** + * Relative path to the application entrypoint + */ + entrypoint_rel_path?: string; + + /** + * Environment variables configured for this deployment + */ + env_vars?: Record; + + /** + * Status reason + */ + status_reason?: string; + + /** + * Timestamp when the deployment was last updated + */ + updated_at?: string | null; + } + } + + /** + * Summary of an application version. + */ + export interface AppVersionSummaryEvent { + /** + * Unique identifier for the app version + */ + id?: string; + + /** + * Name of the application + */ + app_name?: string; + + /** + * Environment variables configured for this app version + */ + env_vars?: Record; + + /** + * Event type identifier (always "app_version_summary"). + */ + event?: 'app_version_summary'; + + /** + * Deployment region code + */ + region?: string; + + /** + * Version label for the application + */ + version?: string; + } + + /** + * An error event from the application. + */ + export interface ErrorEvent { + error?: ErrorEvent.Error; + + /** + * Event type identifier (always "error"). + */ + event?: 'error'; + } + + export namespace ErrorEvent { + export interface Error { + /** + * Application-specific error code (machine-readable) + */ + code: string; + + /** + * Human-readable error description for debugging + */ + message: string; + + /** + * Additional error details (for multiple errors) + */ + details?: Array; + + inner_error?: Error.InnerError; + } + + export namespace Error { + export interface Detail { + /** + * Lower-level error code providing more specific detail + */ + code?: string; + + /** + * Further detail about the error + */ + message?: string; + } + + export interface InnerError { + /** + * Lower-level error code providing more specific detail + */ + code?: string; + + /** + * Further detail about the error + */ + message?: string; + } + } + } +} + +export interface DeploymentCreateParams { + /** + * Relative path to the entrypoint of the application + */ + entrypoint_rel_path: string; + + /** + * ZIP file containing the application source directory + */ + file: Uploadable; + + /** + * Map of environment variables to set for the deployed application. Each key-value + * pair represents an environment variable. + */ + env_vars?: Record; + + /** + * Allow overwriting an existing app version + */ + force?: boolean; + + /** + * Region for deployment. Currently we only support "aws.us-east-1a" + */ + region?: 'aws.us-east-1a'; + + /** + * Version of the application. Can be any string. + */ + version?: string; +} + +export declare namespace Deployments { + export { + type DeploymentCreateResponse as DeploymentCreateResponse, + type DeploymentRetrieveResponse as DeploymentRetrieveResponse, + type DeploymentFollowResponse as DeploymentFollowResponse, + type DeploymentCreateParams as DeploymentCreateParams, + }; +} diff --git a/src/resources/index.ts b/src/resources/index.ts index 5faf2a53..4da34541 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -10,3 +10,10 @@ export { type BrowserCreateParams, type BrowserDeleteParams, } from './browsers'; +export { + Deployments, + type DeploymentCreateResponse, + type DeploymentRetrieveResponse, + type DeploymentFollowResponse, + type DeploymentCreateParams, +} from './deployments'; diff --git a/tests/api-resources/deployments.test.ts b/tests/api-resources/deployments.test.ts new file mode 100644 index 00000000..d8d0b1dc --- /dev/null +++ b/tests/api-resources/deployments.test.ts @@ -0,0 +1,61 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import Kernel, { toFile } 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 deployments', () => { + // skipped: tests are disabled for the time being + test.skip('create: only required params', async () => { + const responsePromise = client.deployments.create({ + entrypoint_rel_path: 'src/app.py', + file: await toFile(Buffer.from('# my file contents'), 'README.md'), + }); + 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('create: required and optional params', async () => { + const response = await client.deployments.create({ + entrypoint_rel_path: 'src/app.py', + file: await toFile(Buffer.from('# my file contents'), 'README.md'), + env_vars: { foo: 'string' }, + force: false, + region: 'aws.us-east-1a', + version: '1.0.0', + }); + }); + + // skipped: tests are disabled for the time being + test.skip('retrieve', async () => { + const responsePromise = client.deployments.retrieve('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: currently no good way to test endpoints with content type text/event-stream, Prism mock server will fail + test.skip('follow', async () => { + const responsePromise = client.deployments.follow('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); + }); +}); From 2f299176d7bbb9e84a7894f21819335f83e17036 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 14 Jun 2025 20:04:04 +0000 Subject: [PATCH 078/551] feat(api): update via SDK Studio --- .stats.yml | 4 ++-- src/resources/apps/deployments.ts | 2 +- src/resources/deployments.ts | 36 ++++++++++++++++++++----------- 3 files changed, 26 insertions(+), 16 deletions(-) diff --git a/.stats.yml b/.stats.yml index f34bfc3d..f219d4b6 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 14 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-d2dfee8d576aa73f6075e6da61228571cb2e844b969a06067e34e43eb7898554.yml -openapi_spec_hash: 9981744bf9c27426cdf721f7b27cf093 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-aec3b879aa30638614c6217afbafcf737f37ac78ef3a51186dbf7b6fbf9e91ef.yml +openapi_spec_hash: 0aba27c707612e35b4068b1d748dc379 config_hash: a085d1b39ddf0b26ee798501a9f47e20 diff --git a/src/resources/apps/deployments.ts b/src/resources/apps/deployments.ts index a5cf4639..e6ee49f9 100644 --- a/src/resources/apps/deployments.ts +++ b/src/resources/apps/deployments.ts @@ -156,7 +156,7 @@ export namespace DeploymentFollowResponse { /** * Time the log entry was produced. */ - timestamp?: string; + timestamp: string; } } diff --git a/src/resources/deployments.ts b/src/resources/deployments.ts index f1eec5ea..735ad573 100644 --- a/src/resources/deployments.ts +++ b/src/resources/deployments.ts @@ -173,7 +173,7 @@ export namespace DeploymentFollowResponse { /** * Time the log entry was produced. */ - timestamp?: string; + timestamp: string; } /** @@ -193,7 +193,7 @@ export namespace DeploymentFollowResponse { /** * Time the state was reported. */ - timestamp?: string; + timestamp: string; } export namespace DeploymentStateEvent { @@ -250,44 +250,54 @@ export namespace DeploymentFollowResponse { /** * Unique identifier for the app version */ - id?: string; + id: string; /** * Name of the application */ - app_name?: string; + app_name: string; /** - * Environment variables configured for this app version + * Event type identifier (always "app_version_summary"). */ - env_vars?: Record; + event: 'app_version_summary'; /** - * Event type identifier (always "app_version_summary"). + * Deployment region code */ - event?: 'app_version_summary'; + region: string; /** - * Deployment region code + * Time the state was reported. */ - region?: string; + timestamp: string; /** * Version label for the application */ - version?: string; + version: string; + + /** + * Environment variables configured for this app version + */ + env_vars?: Record; } /** * An error event from the application. */ export interface ErrorEvent { - error?: ErrorEvent.Error; + error: ErrorEvent.Error; /** * Event type identifier (always "error"). */ - event?: 'error'; + event: 'error'; + + /** + * Time the error occurred. + */ + timestamp: string; } export namespace ErrorEvent { From ee0cae26dfcffa38498a93c731afb0cfa231ea67 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 14 Jun 2025 21:04:32 +0000 Subject: [PATCH 079/551] feat(api): update via SDK Studio --- .stats.yml | 4 ++-- src/resources/deployments.ts | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index f219d4b6..c68e4154 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 14 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-aec3b879aa30638614c6217afbafcf737f37ac78ef3a51186dbf7b6fbf9e91ef.yml -openapi_spec_hash: 0aba27c707612e35b4068b1d748dc379 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-aac74422364f9d25e30fcefd510297580b77be4b84c71416c5b9de5b882e5945.yml +openapi_spec_hash: 4d42a5d93bd82754acf11e32e7438a04 config_hash: a085d1b39ddf0b26ee798501a9f47e20 diff --git a/src/resources/deployments.ts b/src/resources/deployments.ts index 735ad573..5b501ea7 100644 --- a/src/resources/deployments.ts +++ b/src/resources/deployments.ts @@ -277,6 +277,11 @@ export namespace DeploymentFollowResponse { */ version: string; + /** + * List of actions available on the app + */ + actions?: Array; + /** * Environment variables configured for this app version */ From c9a12377595e879c64bdb38cbf1761541ca0b728 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 14 Jun 2025 22:37:37 +0000 Subject: [PATCH 080/551] feat(api): update via SDK Studio --- .stats.yml | 4 ++-- src/resources/apps/apps.ts | 2 +- src/resources/deployments.ts | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.stats.yml b/.stats.yml index c68e4154..3f66d229 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 14 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-aac74422364f9d25e30fcefd510297580b77be4b84c71416c5b9de5b882e5945.yml -openapi_spec_hash: 4d42a5d93bd82754acf11e32e7438a04 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-2fed6c2aef6fb20a2815d0ed36d801c566a73ea11a66db5d892b1533a1fac19e.yml +openapi_spec_hash: 55559a2ca985ed36cb8a13b09f80dcb5 config_hash: a085d1b39ddf0b26ee798501a9f47e20 diff --git a/src/resources/apps/apps.ts b/src/resources/apps/apps.ts index 2b982f6a..b964b335 100644 --- a/src/resources/apps/apps.ts +++ b/src/resources/apps/apps.ts @@ -57,7 +57,7 @@ export namespace AppListResponse { /** * Deployment region code */ - region: string; + region: 'aws.us-east-1a'; /** * Version label for the application diff --git a/src/resources/deployments.ts b/src/resources/deployments.ts index 5b501ea7..3cfb875f 100644 --- a/src/resources/deployments.ts +++ b/src/resources/deployments.ts @@ -73,7 +73,7 @@ export interface DeploymentCreateResponse { /** * Deployment region code */ - region: string; + region: 'aws.us-east-1a'; /** * Current status of the deployment @@ -118,7 +118,7 @@ export interface DeploymentRetrieveResponse { /** * Deployment region code */ - region: string; + region: 'aws.us-east-1a'; /** * Current status of the deployment @@ -214,7 +214,7 @@ export namespace DeploymentFollowResponse { /** * Deployment region code */ - region: string; + region: 'aws.us-east-1a'; /** * Current status of the deployment @@ -265,7 +265,7 @@ export namespace DeploymentFollowResponse { /** * Deployment region code */ - region: string; + region: 'aws.us-east-1a'; /** * Time the state was reported. From 5fd08f4751d03d81b8fbd079a3d09c544dc8633d Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 14 Jun 2025 23:01:18 +0000 Subject: [PATCH 081/551] feat(api): update via SDK Studio --- .stats.yml | 4 ++-- src/resources/deployments.ts | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.stats.yml b/.stats.yml index 3f66d229..4dea91fa 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 14 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-2fed6c2aef6fb20a2815d0ed36d801c566a73ea11a66db5d892b1533a1fac19e.yml -openapi_spec_hash: 55559a2ca985ed36cb8a13b09f80dcb5 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-da3b6999bce525461011a620a559d34d4b4ab1d073758e7add4d2ba09f57a2ba.yml +openapi_spec_hash: 7bec5f31fa27666a3955076653c6ac40 config_hash: a085d1b39ddf0b26ee798501a9f47e20 diff --git a/src/resources/deployments.ts b/src/resources/deployments.ts index 3cfb875f..b4b493ca 100644 --- a/src/resources/deployments.ts +++ b/src/resources/deployments.ts @@ -252,6 +252,11 @@ export namespace DeploymentFollowResponse { */ id: string; + /** + * List of actions available on the app + */ + actions: Array; + /** * Name of the application */ @@ -277,11 +282,6 @@ export namespace DeploymentFollowResponse { */ version: string; - /** - * List of actions available on the app - */ - actions?: Array; - /** * Environment variables configured for this app version */ From 925ccd84b5330a8e14101ecfe36610cf5de8bb67 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 14 Jun 2025 23:12:46 +0000 Subject: [PATCH 082/551] feat(api): update via SDK Studio --- .stats.yml | 4 ++-- src/resources/deployments.ts | 11 ++++++++++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/.stats.yml b/.stats.yml index 4dea91fa..3ea11abf 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 14 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-da3b6999bce525461011a620a559d34d4b4ab1d073758e7add4d2ba09f57a2ba.yml -openapi_spec_hash: 7bec5f31fa27666a3955076653c6ac40 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-b8c3224543bfd828075063a87302ec205b54f8b24658cc869b98aa81d995d855.yml +openapi_spec_hash: 52f5b821303fef54e61bae285f185200 config_hash: a085d1b39ddf0b26ee798501a9f47e20 diff --git a/src/resources/deployments.ts b/src/resources/deployments.ts index b4b493ca..41b7c67d 100644 --- a/src/resources/deployments.ts +++ b/src/resources/deployments.ts @@ -255,7 +255,7 @@ export namespace DeploymentFollowResponse { /** * List of actions available on the app */ - actions: Array; + actions: Array; /** * Name of the application @@ -288,6 +288,15 @@ export namespace DeploymentFollowResponse { env_vars?: Record; } + export namespace AppVersionSummaryEvent { + export interface Action { + /** + * Name of the action + */ + name: string; + } + } + /** * An error event from the application. */ From be912fe4cfa5947ae67c236223234975537f59af Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 14 Jun 2025 23:14:01 +0000 Subject: [PATCH 083/551] feat(api): update via SDK Studio --- .stats.yml | 4 ++-- src/resources/deployments.ts | 5 ++++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/.stats.yml b/.stats.yml index 3ea11abf..3493617f 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 14 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-b8c3224543bfd828075063a87302ec205b54f8b24658cc869b98aa81d995d855.yml -openapi_spec_hash: 52f5b821303fef54e61bae285f185200 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-ba02d679c34c3af5ea47ec2b1a7387785d831e09f35bebfef9f05538ff380c3b.yml +openapi_spec_hash: 7ddbbe7354f65437d4eb567e8b042552 config_hash: a085d1b39ddf0b26ee798501a9f47e20 diff --git a/src/resources/deployments.ts b/src/resources/deployments.ts index 41b7c67d..c885b2fa 100644 --- a/src/resources/deployments.ts +++ b/src/resources/deployments.ts @@ -289,11 +289,14 @@ export namespace DeploymentFollowResponse { } export namespace AppVersionSummaryEvent { + /** + * An action available on the app + */ export interface Action { /** * Name of the action */ - name: string; + name?: string; } } From 3f2b23028ee489016d1aab29681ceb705cda475d Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 14 Jun 2025 23:14:46 +0000 Subject: [PATCH 084/551] feat(api): update via SDK Studio --- .stats.yml | 4 ++-- src/resources/deployments.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.stats.yml b/.stats.yml index 3493617f..bb234450 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 14 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-ba02d679c34c3af5ea47ec2b1a7387785d831e09f35bebfef9f05538ff380c3b.yml -openapi_spec_hash: 7ddbbe7354f65437d4eb567e8b042552 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-f7fa782f119b02d610bac1dbc75bf8355e73169d978997527f643e24036dabdd.yml +openapi_spec_hash: 9543dfe156b1c42a2fe4d3767e6b0778 config_hash: a085d1b39ddf0b26ee798501a9f47e20 diff --git a/src/resources/deployments.ts b/src/resources/deployments.ts index c885b2fa..ae2e487c 100644 --- a/src/resources/deployments.ts +++ b/src/resources/deployments.ts @@ -296,7 +296,7 @@ export namespace DeploymentFollowResponse { /** * Name of the action */ - name?: string; + name: string; } } From 79e170d3b806f95cb530b2b731b4a9fa1f01a8ca Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 17 Jun 2025 03:20:14 +0000 Subject: [PATCH 085/551] chore(client): refactor imports --- src/client.ts | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/client.ts b/src/client.ts index 188384af..fdba863e 100644 --- a/src/client.ts +++ b/src/client.ts @@ -5,7 +5,6 @@ import type { HTTPMethod, PromiseOrValue, MergedRequestInit, FinalizedRequestIni import { uuid4 } from './internal/utils/uuid'; import { validatePositiveInteger, isAbsoluteURL, safeJSON } from './internal/utils/values'; import { sleep } from './internal/utils/sleep'; -import { type Logger, type LogLevel, parseLogLevel } from './internal/utils/log'; export type { Logger, LogLevel } from './internal/utils/log'; import { castToError, isAbortError } from './internal/errors'; import type { APIResponseProps } from './internal/parse'; @@ -17,9 +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 { type Fetch } from './internal/builtin-types'; -import { HeadersLike, NullableHeaders, buildHeaders } from './internal/headers'; -import { FinalRequestOptions, RequestOptions } from './internal/request-options'; import { BrowserCreateParams, BrowserCreateResponse, @@ -36,10 +32,19 @@ import { DeploymentRetrieveResponse, Deployments, } from './resources/deployments'; +import { AppListParams, AppListResponse, Apps } from './resources/apps/apps'; +import { type Fetch } from './internal/builtin-types'; +import { HeadersLike, NullableHeaders, buildHeaders } from './internal/headers'; +import { FinalRequestOptions, RequestOptions } from './internal/request-options'; import { readEnv } from './internal/utils/env'; -import { formatRequestDetails, loggerFor } from './internal/utils/log'; +import { + type LogLevel, + type Logger, + formatRequestDetails, + loggerFor, + parseLogLevel, +} from './internal/utils/log'; import { isEmptyObj } from './internal/utils/values'; -import { AppListParams, AppListResponse, Apps } from './resources/apps/apps'; const environments = { production: 'https://api.onkernel.com/', From 9472f8b400cf2bb845db0411972e17e8c3879a2c Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 17 Jun 2025 03:58:00 +0000 Subject: [PATCH 086/551] feat(client): add support for endpoint-specific base URLs --- package.json | 2 +- src/client.ts | 20 ++++++++++++++++---- src/internal/request-options.ts | 1 + tests/index.test.ts | 22 ++++++++++++++++++++++ yarn.lock | 6 +++--- 5 files changed, 43 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index 13306fb8..7881f390 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,7 @@ "publint": "^0.2.12", "ts-jest": "^29.1.0", "ts-node": "^10.5.0", - "tsc-multi": "https://github.com/stainless-api/tsc-multi/releases/download/v1.1.7/tsc-multi.tgz", + "tsc-multi": "https://github.com/stainless-api/tsc-multi/releases/download/v1.1.8/tsc-multi.tgz", "tsconfig-paths": "^4.0.0", "typescript": "5.8.3" }, diff --git a/src/client.ts b/src/client.ts index fdba863e..a14073e1 100644 --- a/src/client.ts +++ b/src/client.ts @@ -227,6 +227,13 @@ export class Kernel { }); } + /** + * Check whether the base URL is set to its default. + */ + #baseURLOverridden(): boolean { + return this.baseURL !== environments[this._options.environment || 'production']; + } + protected defaultQuery(): Record | undefined { return this._options.defaultQuery; } @@ -276,11 +283,16 @@ export class Kernel { return Errors.APIError.generate(status, error, message, headers); } - buildURL(path: string, query: Record | null | undefined): string { + buildURL( + path: string, + query: Record | null | undefined, + defaultBaseURL?: string | undefined, + ): string { + const baseURL = (!this.#baseURLOverridden() && defaultBaseURL) || this.baseURL; const url = isAbsoluteURL(path) ? new URL(path) - : new URL(this.baseURL + (this.baseURL.endsWith('/') && path.startsWith('/') ? path.slice(1) : path)); + : new URL(baseURL + (baseURL.endsWith('/') && path.startsWith('/') ? path.slice(1) : path)); const defaultQuery = this.defaultQuery(); if (!isEmptyObj(defaultQuery)) { @@ -621,9 +633,9 @@ export class Kernel { { retryCount = 0 }: { retryCount?: number } = {}, ): { req: FinalizedRequestInit; url: string; timeout: number } { const options = { ...inputOptions }; - const { method, path, query } = options; + const { method, path, query, defaultBaseURL } = options; - const url = this.buildURL(path!, query as Record); + const url = this.buildURL(path!, query as Record, defaultBaseURL); if ('timeout' in options) validatePositiveInteger('timeout', options.timeout); options.timeout = options.timeout ?? this.timeout; const { bodyHeaders, body } = this.buildBody({ options }); diff --git a/src/internal/request-options.ts b/src/internal/request-options.ts index ef099310..ffe01ae0 100644 --- a/src/internal/request-options.ts +++ b/src/internal/request-options.ts @@ -21,6 +21,7 @@ export type RequestOptions = { fetchOptions?: MergedRequestInit; signal?: AbortSignal | undefined | null; idempotencyKey?: string; + defaultBaseURL?: string | undefined; __binaryResponse?: boolean | undefined; __streamClass?: typeof Stream; diff --git a/tests/index.test.ts b/tests/index.test.ts index b452e0f4..5c12c9a5 100644 --- a/tests/index.test.ts +++ b/tests/index.test.ts @@ -323,6 +323,28 @@ describe('instantiate client', () => { const client = new Kernel({ apiKey: 'My API Key', baseURL: null, environment: 'production' }); expect(client.baseURL).toEqual('https://api.onkernel.com/'); }); + + test('in request options', () => { + const client = new Kernel({ apiKey: 'My API Key' }); + expect(client.buildURL('/foo', null, 'http://localhost:5000/option')).toEqual( + 'http://localhost:5000/option/foo', + ); + }); + + test('in request options overridden by client options', () => { + const client = new Kernel({ apiKey: 'My API Key', baseURL: 'http://localhost:5000/client' }); + expect(client.buildURL('/foo', null, 'http://localhost:5000/option')).toEqual( + 'http://localhost:5000/client/foo', + ); + }); + + test('in request options overridden by env variable', () => { + process.env['KERNEL_BASE_URL'] = 'http://localhost:5000/env'; + const client = new Kernel({ apiKey: 'My API Key' }); + expect(client.buildURL('/foo', null, 'http://localhost:5000/option')).toEqual( + 'http://localhost:5000/env/foo', + ); + }); }); test('maxRetries option is correctly set', () => { diff --git a/yarn.lock b/yarn.lock index c611c53b..58c08d5f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3283,9 +3283,9 @@ ts-node@^10.5.0: v8-compile-cache-lib "^3.0.0" yn "3.1.1" -"tsc-multi@https://github.com/stainless-api/tsc-multi/releases/download/v1.1.7/tsc-multi.tgz": - version "1.1.7" - resolved "https://github.com/stainless-api/tsc-multi/releases/download/v1.1.7/tsc-multi.tgz#52f40adf8b808bd0b633346d11cc4a8aeea465cd" +"tsc-multi@https://github.com/stainless-api/tsc-multi/releases/download/v1.1.8/tsc-multi.tgz": + version "1.1.8" + resolved "https://github.com/stainless-api/tsc-multi/releases/download/v1.1.8/tsc-multi.tgz#f544b359b8f05e607771ffacc280e58201476b04" dependencies: debug "^4.3.7" fast-glob "^3.3.2" From c742825a5b1c3596e31cd12aef4ed20e5206b310 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 17 Jun 2025 06:42:52 +0000 Subject: [PATCH 087/551] chore(ci): enable for pull requests --- .github/workflows/ci.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 097e5580..b35fe333 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,6 +7,10 @@ on: - 'integrated/**' - 'stl-preview-head/**' - 'stl-preview-base/**' + pull_request: + branches-ignore: + - 'stl-preview-head/**' + - 'stl-preview-base/**' jobs: lint: From 9e86b87df43b2a1555bd132d4600c05601c298ad Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 17 Jun 2025 15:09:47 +0000 Subject: [PATCH 088/551] feat(api): update via SDK Studio --- .stats.yml | 8 +- api.md | 25 ++- src/client.ts | 28 +++ src/resources/apps/apps.ts | 20 -- src/resources/apps/deployments.ts | 23 +-- src/resources/apps/index.ts | 8 - src/resources/deployments.ts | 190 +++++++----------- src/resources/index.ts | 12 ++ src/resources/{apps => }/invocations.ts | 158 ++++++++++++++- src/resources/shared.ts | 33 +++ .../{apps => }/invocations.test.ts | 22 +- 11 files changed, 335 insertions(+), 192 deletions(-) rename src/resources/{apps => }/invocations.ts (55%) create mode 100644 src/resources/shared.ts rename tests/api-resources/{apps => }/invocations.test.ts (69%) diff --git a/.stats.yml b/.stats.yml index bb234450..b912099a 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 14 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-f7fa782f119b02d610bac1dbc75bf8355e73169d978997527f643e24036dabdd.yml -openapi_spec_hash: 9543dfe156b1c42a2fe4d3767e6b0778 -config_hash: a085d1b39ddf0b26ee798501a9f47e20 +configured_endpoints: 15 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-5d4e11bc46eeecee7363d56a9dfe946acee997d5b352c2b0a50c20e742c54d2d.yml +openapi_spec_hash: 333e53ad9c706296b9afdb8ff73bec8f +config_hash: 4e2f9aebc2153d5caf7bb8b2eb107026 diff --git a/api.md b/api.md index b27a84af..aecd8e95 100644 --- a/api.md +++ b/api.md @@ -1,7 +1,15 @@ +# Shared + +Types: + +- ErrorDetail +- LogEvent + # Deployments Types: +- DeploymentStateEvent - DeploymentCreateResponse - DeploymentRetrieveResponse - DeploymentFollowResponse @@ -34,19 +42,22 @@ Methods: - client.apps.deployments.create({ ...params }) -> DeploymentCreateResponse - client.apps.deployments.follow(id) -> DeploymentFollowResponse -## Invocations +# Invocations Types: -- InvocationCreateResponse -- InvocationRetrieveResponse -- InvocationUpdateResponse +- InvocationStateEvent +- InvocationCreateResponse +- InvocationRetrieveResponse +- InvocationUpdateResponse +- InvocationFollowResponse Methods: -- client.apps.invocations.create({ ...params }) -> InvocationCreateResponse -- client.apps.invocations.retrieve(id) -> InvocationRetrieveResponse -- client.apps.invocations.update(id, { ...params }) -> InvocationUpdateResponse +- client.invocations.create({ ...params }) -> InvocationCreateResponse +- client.invocations.retrieve(id) -> InvocationRetrieveResponse +- client.invocations.update(id, { ...params }) -> InvocationUpdateResponse +- client.invocations.follow(id) -> InvocationFollowResponse # Browsers diff --git a/src/client.ts b/src/client.ts index a14073e1..acc39dd0 100644 --- a/src/client.ts +++ b/src/client.ts @@ -30,8 +30,19 @@ import { DeploymentCreateResponse, DeploymentFollowResponse, DeploymentRetrieveResponse, + DeploymentStateEvent, Deployments, } from './resources/deployments'; +import { + InvocationCreateParams, + InvocationCreateResponse, + InvocationFollowResponse, + InvocationRetrieveResponse, + InvocationStateEvent, + InvocationUpdateParams, + InvocationUpdateResponse, + Invocations, +} from './resources/invocations'; import { AppListParams, AppListResponse, Apps } from './resources/apps/apps'; import { type Fetch } from './internal/builtin-types'; import { HeadersLike, NullableHeaders, buildHeaders } from './internal/headers'; @@ -750,16 +761,19 @@ export class Kernel { deployments: API.Deployments = new API.Deployments(this); apps: API.Apps = new API.Apps(this); + invocations: API.Invocations = new API.Invocations(this); browsers: API.Browsers = new API.Browsers(this); } Kernel.Deployments = Deployments; Kernel.Apps = Apps; +Kernel.Invocations = Invocations; Kernel.Browsers = Browsers; export declare namespace Kernel { export type RequestOptions = Opts.RequestOptions; export { Deployments as Deployments, + type DeploymentStateEvent as DeploymentStateEvent, type DeploymentCreateResponse as DeploymentCreateResponse, type DeploymentRetrieveResponse as DeploymentRetrieveResponse, type DeploymentFollowResponse as DeploymentFollowResponse, @@ -768,6 +782,17 @@ export declare namespace Kernel { export { Apps as Apps, type AppListResponse as AppListResponse, type AppListParams as AppListParams }; + export { + Invocations as Invocations, + type InvocationStateEvent as InvocationStateEvent, + type InvocationCreateResponse as InvocationCreateResponse, + type InvocationRetrieveResponse as InvocationRetrieveResponse, + type InvocationUpdateResponse as InvocationUpdateResponse, + type InvocationFollowResponse as InvocationFollowResponse, + type InvocationCreateParams as InvocationCreateParams, + type InvocationUpdateParams as InvocationUpdateParams, + }; + export { Browsers as Browsers, type BrowserPersistence as BrowserPersistence, @@ -777,4 +802,7 @@ export declare namespace Kernel { type BrowserCreateParams as BrowserCreateParams, type BrowserDeleteParams as BrowserDeleteParams, }; + + export type ErrorDetail = API.ErrorDetail; + export type LogEvent = API.LogEvent; } diff --git a/src/resources/apps/apps.ts b/src/resources/apps/apps.ts index b964b335..7f8831e2 100644 --- a/src/resources/apps/apps.ts +++ b/src/resources/apps/apps.ts @@ -8,21 +8,11 @@ import { DeploymentFollowResponse, Deployments, } from './deployments'; -import * as InvocationsAPI from './invocations'; -import { - InvocationCreateParams, - InvocationCreateResponse, - InvocationRetrieveResponse, - InvocationUpdateParams, - InvocationUpdateResponse, - Invocations, -} from './invocations'; import { APIPromise } from '../../core/api-promise'; import { RequestOptions } from '../../internal/request-options'; export class Apps extends APIResource { deployments: DeploymentsAPI.Deployments = new DeploymentsAPI.Deployments(this._client); - invocations: InvocationsAPI.Invocations = new InvocationsAPI.Invocations(this._client); /** * List applications. Optionally filter by app name and/or version label. @@ -84,7 +74,6 @@ export interface AppListParams { } Apps.Deployments = Deployments; -Apps.Invocations = Invocations; export declare namespace Apps { export { type AppListResponse as AppListResponse, type AppListParams as AppListParams }; @@ -95,13 +84,4 @@ export declare namespace Apps { type DeploymentFollowResponse as DeploymentFollowResponse, type DeploymentCreateParams as DeploymentCreateParams, }; - - export { - Invocations as Invocations, - type InvocationCreateResponse as InvocationCreateResponse, - type InvocationRetrieveResponse as InvocationRetrieveResponse, - type InvocationUpdateResponse as InvocationUpdateResponse, - type InvocationCreateParams as InvocationCreateParams, - type InvocationUpdateParams as InvocationUpdateParams, - }; } diff --git a/src/resources/apps/deployments.ts b/src/resources/apps/deployments.ts index e6ee49f9..1581c8e1 100644 --- a/src/resources/apps/deployments.ts +++ b/src/resources/apps/deployments.ts @@ -1,6 +1,7 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. import { APIResource } from '../../core/resource'; +import * as Shared from '../shared'; import { APIPromise } from '../../core/api-promise'; import { Stream } from '../../core/streaming'; import { type Uploadable } from '../../core/uploads'; @@ -96,7 +97,7 @@ export namespace DeploymentCreateResponse { export type DeploymentFollowResponse = | DeploymentFollowResponse.StateEvent | DeploymentFollowResponse.StateUpdateEvent - | DeploymentFollowResponse.LogEvent; + | Shared.LogEvent; export namespace DeploymentFollowResponse { /** @@ -138,26 +139,6 @@ export namespace DeploymentFollowResponse { */ timestamp?: string; } - - /** - * A log entry from the application. - */ - export interface LogEvent { - /** - * Event type identifier (always "log"). - */ - event: 'log'; - - /** - * Log message text. - */ - message: string; - - /** - * Time the log entry was produced. - */ - timestamp: string; - } } export interface DeploymentCreateParams { diff --git a/src/resources/apps/index.ts b/src/resources/apps/index.ts index 29751c0a..a32f41e6 100644 --- a/src/resources/apps/index.ts +++ b/src/resources/apps/index.ts @@ -7,11 +7,3 @@ export { type DeploymentFollowResponse, type DeploymentCreateParams, } from './deployments'; -export { - Invocations, - type InvocationCreateResponse, - type InvocationRetrieveResponse, - type InvocationUpdateResponse, - type InvocationCreateParams, - type InvocationUpdateParams, -} from './invocations'; diff --git a/src/resources/deployments.ts b/src/resources/deployments.ts index ae2e487c..ef7b3091 100644 --- a/src/resources/deployments.ts +++ b/src/resources/deployments.ts @@ -1,6 +1,7 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. import { APIResource } from '../core/resource'; +import * as Shared from './shared'; import { APIPromise } from '../core/api-promise'; import { Stream } from '../core/streaming'; import { type Uploadable } from '../core/uploads'; @@ -56,6 +57,73 @@ export class Deployments extends APIResource { } } +/** + * An event representing the current state of a deployment. + */ +export interface DeploymentStateEvent { + /** + * Deployment record information. + */ + deployment: DeploymentStateEvent.Deployment; + + /** + * Event type identifier (always "deployment_state"). + */ + event: 'deployment_state'; + + /** + * Time the state was reported. + */ + timestamp: string; +} + +export namespace DeploymentStateEvent { + /** + * Deployment record information. + */ + export interface Deployment { + /** + * Unique identifier for the deployment + */ + id: string; + + /** + * Timestamp when the deployment was created + */ + created_at: string; + + /** + * Deployment region code + */ + region: 'aws.us-east-1a'; + + /** + * Current status of the deployment + */ + status: 'queued' | 'in_progress' | 'running' | 'failed' | 'stopped'; + + /** + * Relative path to the application entrypoint + */ + entrypoint_rel_path?: string; + + /** + * Environment variables configured for this deployment + */ + env_vars?: Record; + + /** + * Status reason + */ + status_reason?: string; + + /** + * Timestamp when the deployment was last updated + */ + updated_at?: string | null; + } +} + /** * Deployment record information. */ @@ -150,99 +218,12 @@ export interface DeploymentRetrieveResponse { * Union type representing any deployment event. */ export type DeploymentFollowResponse = - | DeploymentFollowResponse.LogEvent - | DeploymentFollowResponse.DeploymentStateEvent + | Shared.LogEvent + | DeploymentStateEvent | DeploymentFollowResponse.AppVersionSummaryEvent | DeploymentFollowResponse.ErrorEvent; export namespace DeploymentFollowResponse { - /** - * A log entry from the application. - */ - export interface LogEvent { - /** - * Event type identifier (always "log"). - */ - event: 'log'; - - /** - * Log message text. - */ - message: string; - - /** - * Time the log entry was produced. - */ - timestamp: string; - } - - /** - * An event representing the current state of a deployment. - */ - export interface DeploymentStateEvent { - /** - * Deployment record information. - */ - deployment: DeploymentStateEvent.Deployment; - - /** - * Event type identifier (always "deployment_state"). - */ - event: 'deployment_state'; - - /** - * Time the state was reported. - */ - timestamp: string; - } - - export namespace DeploymentStateEvent { - /** - * Deployment record information. - */ - export interface Deployment { - /** - * Unique identifier for the deployment - */ - id: string; - - /** - * Timestamp when the deployment was created - */ - created_at: string; - - /** - * Deployment region code - */ - region: 'aws.us-east-1a'; - - /** - * Current status of the deployment - */ - status: 'queued' | 'in_progress' | 'running' | 'failed' | 'stopped'; - - /** - * Relative path to the application entrypoint - */ - entrypoint_rel_path?: string; - - /** - * Environment variables configured for this deployment - */ - env_vars?: Record; - - /** - * Status reason - */ - status_reason?: string; - - /** - * Timestamp when the deployment was last updated - */ - updated_at?: string | null; - } - } - /** * Summary of an application version. */ @@ -332,35 +313,9 @@ export namespace DeploymentFollowResponse { /** * Additional error details (for multiple errors) */ - details?: Array; - - inner_error?: Error.InnerError; - } + details?: Array; - export namespace Error { - export interface Detail { - /** - * Lower-level error code providing more specific detail - */ - code?: string; - - /** - * Further detail about the error - */ - message?: string; - } - - export interface InnerError { - /** - * Lower-level error code providing more specific detail - */ - code?: string; - - /** - * Further detail about the error - */ - message?: string; - } + inner_error?: Shared.ErrorDetail; } } } @@ -400,6 +355,7 @@ export interface DeploymentCreateParams { export declare namespace Deployments { export { + type DeploymentStateEvent as DeploymentStateEvent, type DeploymentCreateResponse as DeploymentCreateResponse, type DeploymentRetrieveResponse as DeploymentRetrieveResponse, type DeploymentFollowResponse as DeploymentFollowResponse, diff --git a/src/resources/index.ts b/src/resources/index.ts index 4da34541..8c96ec46 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -1,5 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +export * from './shared'; export { Apps, type AppListResponse, type AppListParams } from './apps/apps'; export { Browsers, @@ -12,8 +13,19 @@ export { } from './browsers'; export { Deployments, + type DeploymentStateEvent, type DeploymentCreateResponse, type DeploymentRetrieveResponse, type DeploymentFollowResponse, type DeploymentCreateParams, } from './deployments'; +export { + Invocations, + type InvocationStateEvent, + type InvocationCreateResponse, + type InvocationRetrieveResponse, + type InvocationUpdateResponse, + type InvocationFollowResponse, + type InvocationCreateParams, + type InvocationUpdateParams, +} from './invocations'; diff --git a/src/resources/apps/invocations.ts b/src/resources/invocations.ts similarity index 55% rename from src/resources/apps/invocations.ts rename to src/resources/invocations.ts index 74795509..0751cc42 100644 --- a/src/resources/apps/invocations.ts +++ b/src/resources/invocations.ts @@ -1,9 +1,12 @@ // 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 { RequestOptions } from '../../internal/request-options'; -import { path } from '../../internal/utils/path'; +import { APIResource } from '../core/resource'; +import * as Shared from './shared'; +import { APIPromise } from '../core/api-promise'; +import { Stream } from '../core/streaming'; +import { buildHeaders } from '../internal/headers'; +import { RequestOptions } from '../internal/request-options'; +import { path } from '../internal/utils/path'; export class Invocations extends APIResource { /** @@ -11,7 +14,7 @@ export class Invocations extends APIResource { * * @example * ```ts - * const invocation = await client.apps.invocations.create({ + * const invocation = await client.invocations.create({ * action_name: 'analyze', * app_name: 'my-app', * version: '1.0.0', @@ -27,7 +30,7 @@ export class Invocations extends APIResource { * * @example * ```ts - * const invocation = await client.apps.invocations.retrieve( + * const invocation = await client.invocations.retrieve( * 'rr33xuugxj9h0bkf1rdt2bet', * ); * ``` @@ -41,10 +44,9 @@ export class Invocations extends APIResource { * * @example * ```ts - * const invocation = await client.apps.invocations.update( - * 'id', - * { status: 'succeeded' }, - * ); + * const invocation = await client.invocations.update('id', { + * status: 'succeeded', + * }); * ``` */ update( @@ -54,6 +56,92 @@ export class Invocations extends APIResource { ): APIPromise { return this._client.patch(path`/invocations/${id}`, { body, ...options }); } + + /** + * Establishes a Server-Sent Events (SSE) stream that delivers real-time logs and + * status updates for an invocation. The stream terminates automatically once the + * invocation reaches a terminal state. + * + * @example + * ```ts + * const response = await client.invocations.follow('id'); + * ``` + */ + follow(id: string, options?: RequestOptions): APIPromise> { + return this._client.get(path`/invocations/${id}/events`, { + ...options, + headers: buildHeaders([{ Accept: 'text/event-stream' }, options?.headers]), + stream: true, + }) as APIPromise>; + } +} + +/** + * An event representing the current state of an invocation. + */ +export interface InvocationStateEvent { + /** + * Event type identifier (always "invocation_state"). + */ + event: 'invocation_state'; + + invocation: InvocationStateEvent.Invocation; + + /** + * Time the state was reported. + */ + timestamp: string; +} + +export namespace InvocationStateEvent { + export interface Invocation { + /** + * ID of the invocation + */ + id: string; + + /** + * Name of the action invoked + */ + action_name: string; + + /** + * Name of the application + */ + app_name: string; + + /** + * RFC 3339 Nanoseconds timestamp when the invocation started + */ + started_at: string; + + /** + * Status of the invocation + */ + status: 'queued' | 'running' | 'succeeded' | 'failed'; + + /** + * RFC 3339 Nanoseconds timestamp when the invocation finished (null if still + * running) + */ + finished_at?: string | null; + + /** + * Output produced by the action, rendered as a JSON string. This could be: string, + * number, boolean, array, object, or null. + */ + output?: string; + + /** + * Payload provided to the invocation. This is a string that can be parsed as JSON. + */ + payload?: string; + + /** + * Status reason + */ + status_reason?: string; + } } export interface InvocationCreateResponse { @@ -177,6 +265,54 @@ export interface InvocationUpdateResponse { status_reason?: string; } +/** + * Union type representing any invocation event. + */ +export type InvocationFollowResponse = + | Shared.LogEvent + | InvocationStateEvent + | InvocationFollowResponse.ErrorEvent; + +export namespace InvocationFollowResponse { + /** + * An error event from the application. + */ + export interface ErrorEvent { + error: ErrorEvent.Error; + + /** + * Event type identifier (always "error"). + */ + event: 'error'; + + /** + * Time the error occurred. + */ + timestamp: string; + } + + export namespace ErrorEvent { + export interface Error { + /** + * Application-specific error code (machine-readable) + */ + code: string; + + /** + * Human-readable error description for debugging + */ + message: string; + + /** + * Additional error details (for multiple errors) + */ + details?: Array; + + inner_error?: Shared.ErrorDetail; + } + } +} + export interface InvocationCreateParams { /** * Name of the action to invoke @@ -219,9 +355,11 @@ export interface InvocationUpdateParams { export declare namespace Invocations { export { + type InvocationStateEvent as InvocationStateEvent, type InvocationCreateResponse as InvocationCreateResponse, type InvocationRetrieveResponse as InvocationRetrieveResponse, type InvocationUpdateResponse as InvocationUpdateResponse, + type InvocationFollowResponse as InvocationFollowResponse, type InvocationCreateParams as InvocationCreateParams, type InvocationUpdateParams as InvocationUpdateParams, }; diff --git a/src/resources/shared.ts b/src/resources/shared.ts new file mode 100644 index 00000000..c56dcb19 --- /dev/null +++ b/src/resources/shared.ts @@ -0,0 +1,33 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export interface ErrorDetail { + /** + * Lower-level error code providing more specific detail + */ + code?: string; + + /** + * Further detail about the error + */ + message?: string; +} + +/** + * A log entry from the application. + */ +export interface LogEvent { + /** + * Event type identifier (always "log"). + */ + event: 'log'; + + /** + * Log message text. + */ + message: string; + + /** + * Time the log entry was produced. + */ + timestamp: string; +} diff --git a/tests/api-resources/apps/invocations.test.ts b/tests/api-resources/invocations.test.ts similarity index 69% rename from tests/api-resources/apps/invocations.test.ts rename to tests/api-resources/invocations.test.ts index 9a1b028e..2201a592 100644 --- a/tests/api-resources/apps/invocations.test.ts +++ b/tests/api-resources/invocations.test.ts @@ -10,7 +10,7 @@ const client = new Kernel({ describe('resource invocations', () => { // skipped: tests are disabled for the time being test.skip('create: only required params', async () => { - const responsePromise = client.apps.invocations.create({ + const responsePromise = client.invocations.create({ action_name: 'analyze', app_name: 'my-app', version: '1.0.0', @@ -26,7 +26,7 @@ describe('resource invocations', () => { // skipped: tests are disabled for the time being test.skip('create: required and optional params', async () => { - const response = await client.apps.invocations.create({ + const response = await client.invocations.create({ action_name: 'analyze', app_name: 'my-app', version: '1.0.0', @@ -37,7 +37,7 @@ describe('resource invocations', () => { // skipped: tests are disabled for the time being test.skip('retrieve', async () => { - const responsePromise = client.apps.invocations.retrieve('rr33xuugxj9h0bkf1rdt2bet'); + const responsePromise = client.invocations.retrieve('rr33xuugxj9h0bkf1rdt2bet'); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -49,7 +49,7 @@ describe('resource invocations', () => { // skipped: tests are disabled for the time being test.skip('update: only required params', async () => { - const responsePromise = client.apps.invocations.update('id', { status: 'succeeded' }); + const responsePromise = client.invocations.update('id', { status: 'succeeded' }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -61,6 +61,18 @@ describe('resource invocations', () => { // skipped: tests are disabled for the time being test.skip('update: required and optional params', async () => { - const response = await client.apps.invocations.update('id', { status: 'succeeded', output: 'output' }); + const response = await client.invocations.update('id', { status: 'succeeded', output: 'output' }); + }); + + // skipped: currently no good way to test endpoints with content type text/event-stream, Prism mock server will fail + test.skip('follow', async () => { + const responsePromise = client.invocations.follow('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); }); }); From fe7b8f47d697059b9320461f7d61a7ad8b3e850b Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 17 Jun 2025 15:20:44 +0000 Subject: [PATCH 089/551] feat(api): update via SDK Studio --- .stats.yml | 6 ++--- api.md | 2 ++ src/client.ts | 2 ++ src/resources/deployments.ts | 40 +------------------------------- src/resources/invocations.ts | 44 +++--------------------------------- src/resources/shared.ts | 36 +++++++++++++++++++++++++++++ 6 files changed, 47 insertions(+), 83 deletions(-) diff --git a/.stats.yml b/.stats.yml index b912099a..763dad39 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 15 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-5d4e11bc46eeecee7363d56a9dfe946acee997d5b352c2b0a50c20e742c54d2d.yml -openapi_spec_hash: 333e53ad9c706296b9afdb8ff73bec8f -config_hash: 4e2f9aebc2153d5caf7bb8b2eb107026 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-b1b412b00906fca75bfa73cff7267dbb5bf975581778072e0a90c73ad7ba9cb1.yml +openapi_spec_hash: 9b7a1b29bcb4963fe6da37005c357d27 +config_hash: df959c379e1145106030a4869b006afe diff --git a/api.md b/api.md index aecd8e95..c7d96d13 100644 --- a/api.md +++ b/api.md @@ -2,7 +2,9 @@ Types: +- Error - ErrorDetail +- ErrorEvent - LogEvent # Deployments diff --git a/src/client.ts b/src/client.ts index acc39dd0..73de7d00 100644 --- a/src/client.ts +++ b/src/client.ts @@ -803,6 +803,8 @@ export declare namespace Kernel { type BrowserDeleteParams as BrowserDeleteParams, }; + export type Error = API.Error; export type ErrorDetail = API.ErrorDetail; + export type ErrorEvent = API.ErrorEvent; export type LogEvent = API.LogEvent; } diff --git a/src/resources/deployments.ts b/src/resources/deployments.ts index ef7b3091..bc247fc7 100644 --- a/src/resources/deployments.ts +++ b/src/resources/deployments.ts @@ -221,7 +221,7 @@ export type DeploymentFollowResponse = | Shared.LogEvent | DeploymentStateEvent | DeploymentFollowResponse.AppVersionSummaryEvent - | DeploymentFollowResponse.ErrorEvent; + | Shared.ErrorEvent; export namespace DeploymentFollowResponse { /** @@ -280,44 +280,6 @@ export namespace DeploymentFollowResponse { name: string; } } - - /** - * An error event from the application. - */ - export interface ErrorEvent { - error: ErrorEvent.Error; - - /** - * Event type identifier (always "error"). - */ - event: 'error'; - - /** - * Time the error occurred. - */ - timestamp: string; - } - - export namespace ErrorEvent { - export interface Error { - /** - * Application-specific error code (machine-readable) - */ - code: string; - - /** - * Human-readable error description for debugging - */ - message: string; - - /** - * Additional error details (for multiple errors) - */ - details?: Array; - - inner_error?: Shared.ErrorDetail; - } - } } export interface DeploymentCreateParams { diff --git a/src/resources/invocations.ts b/src/resources/invocations.ts index 0751cc42..19f44bd5 100644 --- a/src/resources/invocations.ts +++ b/src/resources/invocations.ts @@ -1,6 +1,7 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. import { APIResource } from '../core/resource'; +import * as DeploymentsAPI from './deployments'; import * as Shared from './shared'; import { APIPromise } from '../core/api-promise'; import { Stream } from '../core/streaming'; @@ -270,48 +271,9 @@ export interface InvocationUpdateResponse { */ export type InvocationFollowResponse = | Shared.LogEvent + | DeploymentsAPI.DeploymentStateEvent | InvocationStateEvent - | InvocationFollowResponse.ErrorEvent; - -export namespace InvocationFollowResponse { - /** - * An error event from the application. - */ - export interface ErrorEvent { - error: ErrorEvent.Error; - - /** - * Event type identifier (always "error"). - */ - event: 'error'; - - /** - * Time the error occurred. - */ - timestamp: string; - } - - export namespace ErrorEvent { - export interface Error { - /** - * Application-specific error code (machine-readable) - */ - code: string; - - /** - * Human-readable error description for debugging - */ - message: string; - - /** - * Additional error details (for multiple errors) - */ - details?: Array; - - inner_error?: Shared.ErrorDetail; - } - } -} + | Shared.ErrorEvent; export interface InvocationCreateParams { /** diff --git a/src/resources/shared.ts b/src/resources/shared.ts index c56dcb19..876b2e3e 100644 --- a/src/resources/shared.ts +++ b/src/resources/shared.ts @@ -1,5 +1,24 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +export interface Error { + /** + * Application-specific error code (machine-readable) + */ + code: string; + + /** + * Human-readable error description for debugging + */ + message: string; + + /** + * Additional error details (for multiple errors) + */ + details?: Array; + + inner_error?: ErrorDetail; +} + export interface ErrorDetail { /** * Lower-level error code providing more specific detail @@ -12,6 +31,23 @@ export interface ErrorDetail { message?: string; } +/** + * An error event from the application. + */ +export interface ErrorEvent { + error: Error; + + /** + * Event type identifier (always "error"). + */ + event: 'error'; + + /** + * Time the error occurred. + */ + timestamp: string; +} + /** * A log entry from the application. */ From 5489d7a9f238799f6aaaef5810fb33b550cfb90c Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 17 Jun 2025 15:23:21 +0000 Subject: [PATCH 090/551] feat(api): update via SDK Studio --- .stats.yml | 4 ++-- src/resources/invocations.ts | 7 +------ 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/.stats.yml b/.stats.yml index 763dad39..1e9f62b0 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 15 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-b1b412b00906fca75bfa73cff7267dbb5bf975581778072e0a90c73ad7ba9cb1.yml -openapi_spec_hash: 9b7a1b29bcb4963fe6da37005c357d27 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-5d4e11bc46eeecee7363d56a9dfe946acee997d5b352c2b0a50c20e742c54d2d.yml +openapi_spec_hash: 333e53ad9c706296b9afdb8ff73bec8f config_hash: df959c379e1145106030a4869b006afe diff --git a/src/resources/invocations.ts b/src/resources/invocations.ts index 19f44bd5..40e16b6d 100644 --- a/src/resources/invocations.ts +++ b/src/resources/invocations.ts @@ -1,7 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. import { APIResource } from '../core/resource'; -import * as DeploymentsAPI from './deployments'; import * as Shared from './shared'; import { APIPromise } from '../core/api-promise'; import { Stream } from '../core/streaming'; @@ -269,11 +268,7 @@ export interface InvocationUpdateResponse { /** * Union type representing any invocation event. */ -export type InvocationFollowResponse = - | Shared.LogEvent - | DeploymentsAPI.DeploymentStateEvent - | InvocationStateEvent - | Shared.ErrorEvent; +export type InvocationFollowResponse = Shared.LogEvent | InvocationStateEvent | Shared.ErrorEvent; export interface InvocationCreateParams { /** From 546032dc126099551aa28058fa16ad3ed3524319 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 17 Jun 2025 15:25:21 +0000 Subject: [PATCH 091/551] feat(api): update via SDK Studio --- .stats.yml | 2 +- api.md | 1 - src/client.ts | 1 - src/resources/shared.ts | 42 ++++++++++++++++++++++------------------- 4 files changed, 24 insertions(+), 22 deletions(-) diff --git a/.stats.yml b/.stats.yml index 1e9f62b0..71dae95c 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 15 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-5d4e11bc46eeecee7363d56a9dfe946acee997d5b352c2b0a50c20e742c54d2d.yml openapi_spec_hash: 333e53ad9c706296b9afdb8ff73bec8f -config_hash: df959c379e1145106030a4869b006afe +config_hash: 79af9b3bec53ee798dddcf815befa25d diff --git a/api.md b/api.md index c7d96d13..27523f31 100644 --- a/api.md +++ b/api.md @@ -2,7 +2,6 @@ Types: -- Error - ErrorDetail - ErrorEvent - LogEvent diff --git a/src/client.ts b/src/client.ts index 73de7d00..a1ba3064 100644 --- a/src/client.ts +++ b/src/client.ts @@ -803,7 +803,6 @@ export declare namespace Kernel { type BrowserDeleteParams as BrowserDeleteParams, }; - export type Error = API.Error; export type ErrorDetail = API.ErrorDetail; export type ErrorEvent = API.ErrorEvent; export type LogEvent = API.LogEvent; diff --git a/src/resources/shared.ts b/src/resources/shared.ts index 876b2e3e..55345c30 100644 --- a/src/resources/shared.ts +++ b/src/resources/shared.ts @@ -1,23 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -export interface Error { - /** - * Application-specific error code (machine-readable) - */ - code: string; - - /** - * Human-readable error description for debugging - */ - message: string; - - /** - * Additional error details (for multiple errors) - */ - details?: Array; - - inner_error?: ErrorDetail; -} +import * as Shared from './shared'; export interface ErrorDetail { /** @@ -35,7 +18,7 @@ export interface ErrorDetail { * An error event from the application. */ export interface ErrorEvent { - error: Error; + error: ErrorEvent.Error; /** * Event type identifier (always "error"). @@ -48,6 +31,27 @@ export interface ErrorEvent { timestamp: string; } +export namespace ErrorEvent { + export interface Error { + /** + * Application-specific error code (machine-readable) + */ + code: string; + + /** + * Human-readable error description for debugging + */ + message: string; + + /** + * Additional error details (for multiple errors) + */ + details?: Array; + + inner_error?: Shared.ErrorDetail; + } +} + /** * A log entry from the application. */ From 1c6386e9c8e7587a4bde86884889bb24566b63dc Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 17 Jun 2025 15:26:00 +0000 Subject: [PATCH 092/551] feat(api): update via SDK Studio --- .stats.yml | 2 +- api.md | 1 + src/client.ts | 1 + src/resources/shared.ts | 34 +++++++++++++++------------------- 4 files changed, 18 insertions(+), 20 deletions(-) diff --git a/.stats.yml b/.stats.yml index 71dae95c..ba1c7c95 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 15 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-5d4e11bc46eeecee7363d56a9dfe946acee997d5b352c2b0a50c20e742c54d2d.yml openapi_spec_hash: 333e53ad9c706296b9afdb8ff73bec8f -config_hash: 79af9b3bec53ee798dddcf815befa25d +config_hash: 0fdf285ddd8dee229fd84ea57df9080f diff --git a/api.md b/api.md index 27523f31..2f617073 100644 --- a/api.md +++ b/api.md @@ -4,6 +4,7 @@ Types: - ErrorDetail - ErrorEvent +- ErrorModel - LogEvent # Deployments diff --git a/src/client.ts b/src/client.ts index a1ba3064..0f525a08 100644 --- a/src/client.ts +++ b/src/client.ts @@ -805,5 +805,6 @@ export declare namespace Kernel { export type ErrorDetail = API.ErrorDetail; export type ErrorEvent = API.ErrorEvent; + export type ErrorModel = API.ErrorModel; export type LogEvent = API.LogEvent; } diff --git a/src/resources/shared.ts b/src/resources/shared.ts index 55345c30..1760bd40 100644 --- a/src/resources/shared.ts +++ b/src/resources/shared.ts @@ -1,7 +1,5 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import * as Shared from './shared'; - export interface ErrorDetail { /** * Lower-level error code providing more specific detail @@ -18,7 +16,7 @@ export interface ErrorDetail { * An error event from the application. */ export interface ErrorEvent { - error: ErrorEvent.Error; + error: ErrorModel; /** * Event type identifier (always "error"). @@ -31,25 +29,23 @@ export interface ErrorEvent { timestamp: string; } -export namespace ErrorEvent { - export interface Error { - /** - * Application-specific error code (machine-readable) - */ - code: string; +export interface ErrorModel { + /** + * Application-specific error code (machine-readable) + */ + code: string; - /** - * Human-readable error description for debugging - */ - message: string; + /** + * Human-readable error description for debugging + */ + message: string; - /** - * Additional error details (for multiple errors) - */ - details?: Array; + /** + * Additional error details (for multiple errors) + */ + details?: Array; - inner_error?: Shared.ErrorDetail; - } + inner_error?: ErrorDetail; } /** From 38b19d1abf1725de48357aa5ff1da2ae0303fc32 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 18 Jun 2025 02:12:20 +0000 Subject: [PATCH 093/551] chore(readme): update badges --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 22327b87..4217f0f5 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Kernel TypeScript API Library -[![NPM version](https://img.shields.io/npm/v/@onkernel/sdk.svg)](https://npmjs.org/package/@onkernel/sdk) ![npm bundle size](https://img.shields.io/bundlephobia/minzip/@onkernel/sdk) +[![NPM version]()](https://npmjs.org/package/@onkernel/sdk) ![npm bundle size](https://img.shields.io/bundlephobia/minzip/@onkernel/sdk) This library provides convenient access to the Kernel REST API from server-side TypeScript or JavaScript. From 7b54346851e0f83b3ab182daee806040c6817ab1 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 18 Jun 2025 10:36:29 +0000 Subject: [PATCH 094/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index f1c1e588..bcd05228 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.5.0" + ".": "0.6.0" } diff --git a/package.json b/package.json index 7881f390..05bd20a8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.5.0", + "version": "0.6.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 1f5d1586..30c28175 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.5.0'; // x-release-please-version +export const VERSION = '0.6.0'; // x-release-please-version From d3283e7f60d89439e01dabd4dc58b4952185abfc Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 18 Jun 2025 17:59:04 +0000 Subject: [PATCH 095/551] feat(api): add delete_browsers endpoint --- .stats.yml | 8 ++++---- api.md | 1 + src/resources/invocations.ts | 15 +++++++++++++++ tests/api-resources/invocations.test.ts | 12 ++++++++++++ 4 files changed, 32 insertions(+), 4 deletions(-) diff --git a/.stats.yml b/.stats.yml index ba1c7c95..4a84456e 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 15 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-5d4e11bc46eeecee7363d56a9dfe946acee997d5b352c2b0a50c20e742c54d2d.yml -openapi_spec_hash: 333e53ad9c706296b9afdb8ff73bec8f -config_hash: 0fdf285ddd8dee229fd84ea57df9080f +configured_endpoints: 16 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-b019e469425a59061f37c5fdc7a131a5291c66134ef0627db4f06bb1f4af0b15.yml +openapi_spec_hash: f66a3c2efddb168db9539ba2507b10b8 +config_hash: aae6721b2be9ec8565dfc8f7eadfe105 diff --git a/api.md b/api.md index 2f617073..f81d636b 100644 --- a/api.md +++ b/api.md @@ -59,6 +59,7 @@ Methods: - client.invocations.create({ ...params }) -> InvocationCreateResponse - client.invocations.retrieve(id) -> InvocationRetrieveResponse - client.invocations.update(id, { ...params }) -> InvocationUpdateResponse +- client.invocations.deleteBrowsers(id) -> void - client.invocations.follow(id) -> InvocationFollowResponse # Browsers diff --git a/src/resources/invocations.ts b/src/resources/invocations.ts index 40e16b6d..6b585e46 100644 --- a/src/resources/invocations.ts +++ b/src/resources/invocations.ts @@ -57,6 +57,21 @@ export class Invocations extends APIResource { return this._client.patch(path`/invocations/${id}`, { body, ...options }); } + /** + * Delete all browser sessions created within the specified invocation. + * + * @example + * ```ts + * await client.invocations.deleteBrowsers('id'); + * ``` + */ + deleteBrowsers(id: string, options?: RequestOptions): APIPromise { + return this._client.delete(path`/invocations/${id}/browsers`, { + ...options, + headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), + }); + } + /** * Establishes a Server-Sent Events (SSE) stream that delivers real-time logs and * status updates for an invocation. The stream terminates automatically once the diff --git a/tests/api-resources/invocations.test.ts b/tests/api-resources/invocations.test.ts index 2201a592..e481c152 100644 --- a/tests/api-resources/invocations.test.ts +++ b/tests/api-resources/invocations.test.ts @@ -64,6 +64,18 @@ describe('resource invocations', () => { const response = await client.invocations.update('id', { status: 'succeeded', output: 'output' }); }); + // skipped: tests are disabled for the time being + test.skip('deleteBrowsers', async () => { + const responsePromise = client.invocations.deleteBrowsers('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: currently no good way to test endpoints with content type text/event-stream, Prism mock server will fail test.skip('follow', async () => { const responsePromise = client.invocations.follow('id'); From 9fda253555a68f7da1e53d0997ff35d93fc145b7 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 18 Jun 2025 18:02:33 +0000 Subject: [PATCH 096/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index bcd05228..5d02000a 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.6.0" + ".": "0.6.1" } diff --git a/package.json b/package.json index 05bd20a8..5ff0a3fb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.6.0", + "version": "0.6.1", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 30c28175..3998d8e5 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.6.0'; // x-release-please-version +export const VERSION = '0.6.1'; // x-release-please-version From f2a28be3563e43239a504992ba1e51a85129b753 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 19 Jun 2025 04:36:56 +0000 Subject: [PATCH 097/551] chore(readme): use better example snippet for undocumented params --- README.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 4217f0f5..77ae2733 100644 --- a/README.md +++ b/README.md @@ -283,9 +283,8 @@ parameter. This library doesn't validate at runtime that the request matches the send will be sent as-is. ```ts -client.foo.create({ - foo: 'my_param', - bar: 12, +client.apps.deployments.create({ + // ... // @ts-expect-error baz is not yet public baz: 'undocumented option', }); From 00b546717d50a23b206c2c39f94725fee9892792 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 21 Jun 2025 02:14:46 +0000 Subject: [PATCH 098/551] fix(client): explicitly copy fetch in withOptions --- src/client.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/client.ts b/src/client.ts index 0f525a08..15a0e8aa 100644 --- a/src/client.ts +++ b/src/client.ts @@ -232,6 +232,7 @@ export class Kernel { timeout: this.timeout, logger: this.logger, logLevel: this.logLevel, + fetch: this.fetch, fetchOptions: this.fetchOptions, apiKey: this.apiKey, ...options, From 88cabfaca3aedc112dab77ce66c9b3f2a89f3123 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 24 Jun 2025 04:38:06 +0000 Subject: [PATCH 099/551] refactor(types): replace Record with mapped types --- src/resources/apps/apps.ts | 2 +- src/resources/apps/deployments.ts | 2 +- src/resources/deployments.ts | 10 +++++----- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/resources/apps/apps.ts b/src/resources/apps/apps.ts index 7f8831e2..6e15089e 100644 --- a/src/resources/apps/apps.ts +++ b/src/resources/apps/apps.ts @@ -57,7 +57,7 @@ export namespace AppListResponse { /** * Environment variables configured for this app version */ - env_vars?: Record; + env_vars?: { [key: string]: string }; } } diff --git a/src/resources/apps/deployments.ts b/src/resources/apps/deployments.ts index 1581c8e1..d526bd40 100644 --- a/src/resources/apps/deployments.ts +++ b/src/resources/apps/deployments.ts @@ -156,7 +156,7 @@ export interface DeploymentCreateParams { * Map of environment variables to set for the deployed application. Each key-value * pair represents an environment variable. */ - env_vars?: Record; + env_vars?: { [key: string]: string }; /** * Allow overwriting an existing app version diff --git a/src/resources/deployments.ts b/src/resources/deployments.ts index bc247fc7..5cadabad 100644 --- a/src/resources/deployments.ts +++ b/src/resources/deployments.ts @@ -110,7 +110,7 @@ export namespace DeploymentStateEvent { /** * Environment variables configured for this deployment */ - env_vars?: Record; + env_vars?: { [key: string]: string }; /** * Status reason @@ -156,7 +156,7 @@ export interface DeploymentCreateResponse { /** * Environment variables configured for this deployment */ - env_vars?: Record; + env_vars?: { [key: string]: string }; /** * Status reason @@ -201,7 +201,7 @@ export interface DeploymentRetrieveResponse { /** * Environment variables configured for this deployment */ - env_vars?: Record; + env_vars?: { [key: string]: string }; /** * Status reason @@ -266,7 +266,7 @@ export namespace DeploymentFollowResponse { /** * Environment variables configured for this app version */ - env_vars?: Record; + env_vars?: { [key: string]: string }; } export namespace AppVersionSummaryEvent { @@ -297,7 +297,7 @@ export interface DeploymentCreateParams { * Map of environment variables to set for the deployed application. Each key-value * pair represents an environment variable. */ - env_vars?: Record; + env_vars?: { [key: string]: string }; /** * Allow overwriting an existing app version From 63bf72175f0da260a45c57409671b2dff0a933a0 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 24 Jun 2025 19:49:49 +0000 Subject: [PATCH 100/551] feat(api): add `since` parameter to deployment logs endpoint --- .stats.yml | 6 +++--- api.md | 3 ++- src/client.ts | 3 +++ src/resources/apps/apps.ts | 5 +++++ src/resources/apps/deployments.ts | 3 ++- src/resources/deployments.ts | 18 ++++++++++++++++-- src/resources/index.ts | 1 + src/resources/invocations.ts | 6 +++++- src/resources/shared.ts | 15 +++++++++++++++ tests/api-resources/deployments.test.ts | 12 ++++++++++++ 10 files changed, 64 insertions(+), 8 deletions(-) diff --git a/.stats.yml b/.stats.yml index 4a84456e..b296d07c 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 16 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-b019e469425a59061f37c5fdc7a131a5291c66134ef0627db4f06bb1f4af0b15.yml -openapi_spec_hash: f66a3c2efddb168db9539ba2507b10b8 -config_hash: aae6721b2be9ec8565dfc8f7eadfe105 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-2aec229ccf91f7c1ac95aa675ea2a59bd61af9e363a22c3b49677992f1eeb16a.yml +openapi_spec_hash: c80cd5d52a79cd5366a76d4a825bd27a +config_hash: b8e1fff080fbaa22656ab0a57b591777 diff --git a/api.md b/api.md index f81d636b..a8ada60f 100644 --- a/api.md +++ b/api.md @@ -5,6 +5,7 @@ Types: - ErrorDetail - ErrorEvent - ErrorModel +- HeartbeatEvent - LogEvent # Deployments @@ -20,7 +21,7 @@ Methods: - client.deployments.create({ ...params }) -> DeploymentCreateResponse - client.deployments.retrieve(id) -> DeploymentRetrieveResponse -- client.deployments.follow(id) -> DeploymentFollowResponse +- client.deployments.follow(id, { ...params }) -> DeploymentFollowResponse # Apps diff --git a/src/client.ts b/src/client.ts index 15a0e8aa..a01ed699 100644 --- a/src/client.ts +++ b/src/client.ts @@ -28,6 +28,7 @@ import { import { DeploymentCreateParams, DeploymentCreateResponse, + DeploymentFollowParams, DeploymentFollowResponse, DeploymentRetrieveResponse, DeploymentStateEvent, @@ -779,6 +780,7 @@ export declare namespace Kernel { type DeploymentRetrieveResponse as DeploymentRetrieveResponse, type DeploymentFollowResponse as DeploymentFollowResponse, type DeploymentCreateParams as DeploymentCreateParams, + type DeploymentFollowParams as DeploymentFollowParams, }; export { Apps as Apps, type AppListResponse as AppListResponse, type AppListParams as AppListParams }; @@ -807,5 +809,6 @@ export declare namespace Kernel { export type ErrorDetail = API.ErrorDetail; export type ErrorEvent = API.ErrorEvent; export type ErrorModel = API.ErrorModel; + export type HeartbeatEvent = API.HeartbeatEvent; export type LogEvent = API.LogEvent; } diff --git a/src/resources/apps/apps.ts b/src/resources/apps/apps.ts index 6e15089e..227fba81 100644 --- a/src/resources/apps/apps.ts +++ b/src/resources/apps/apps.ts @@ -44,6 +44,11 @@ export namespace AppListResponse { */ app_name: string; + /** + * Deployment ID + */ + deployment: string; + /** * Deployment region code */ diff --git a/src/resources/apps/deployments.ts b/src/resources/apps/deployments.ts index d526bd40..fc619791 100644 --- a/src/resources/apps/deployments.ts +++ b/src/resources/apps/deployments.ts @@ -97,7 +97,8 @@ export namespace DeploymentCreateResponse { export type DeploymentFollowResponse = | DeploymentFollowResponse.StateEvent | DeploymentFollowResponse.StateUpdateEvent - | Shared.LogEvent; + | Shared.LogEvent + | Shared.HeartbeatEvent; export namespace DeploymentFollowResponse { /** diff --git a/src/resources/deployments.ts b/src/resources/deployments.ts index 5cadabad..33f9dcc2 100644 --- a/src/resources/deployments.ts +++ b/src/resources/deployments.ts @@ -48,8 +48,13 @@ export class Deployments extends APIResource { * const response = await client.deployments.follow('id'); * ``` */ - follow(id: string, options?: RequestOptions): APIPromise> { + follow( + id: string, + query: DeploymentFollowParams | undefined = {}, + options?: RequestOptions, + ): APIPromise> { return this._client.get(path`/deployments/${id}/events`, { + query, ...options, headers: buildHeaders([{ Accept: 'text/event-stream' }, options?.headers]), stream: true, @@ -221,7 +226,8 @@ export type DeploymentFollowResponse = | Shared.LogEvent | DeploymentStateEvent | DeploymentFollowResponse.AppVersionSummaryEvent - | Shared.ErrorEvent; + | Shared.ErrorEvent + | Shared.HeartbeatEvent; export namespace DeploymentFollowResponse { /** @@ -315,6 +321,13 @@ export interface DeploymentCreateParams { version?: string; } +export interface DeploymentFollowParams { + /** + * Show logs since the given time (RFC timestamps or durations like 5m). + */ + since?: string; +} + export declare namespace Deployments { export { type DeploymentStateEvent as DeploymentStateEvent, @@ -322,5 +335,6 @@ export declare namespace Deployments { type DeploymentRetrieveResponse as DeploymentRetrieveResponse, type DeploymentFollowResponse as DeploymentFollowResponse, type DeploymentCreateParams as DeploymentCreateParams, + type DeploymentFollowParams as DeploymentFollowParams, }; } diff --git a/src/resources/index.ts b/src/resources/index.ts index 8c96ec46..b59024df 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -18,6 +18,7 @@ export { type DeploymentRetrieveResponse, type DeploymentFollowResponse, type DeploymentCreateParams, + type DeploymentFollowParams, } from './deployments'; export { Invocations, diff --git a/src/resources/invocations.ts b/src/resources/invocations.ts index 6b585e46..24afed15 100644 --- a/src/resources/invocations.ts +++ b/src/resources/invocations.ts @@ -283,7 +283,11 @@ export interface InvocationUpdateResponse { /** * Union type representing any invocation event. */ -export type InvocationFollowResponse = Shared.LogEvent | InvocationStateEvent | Shared.ErrorEvent; +export type InvocationFollowResponse = + | Shared.LogEvent + | InvocationStateEvent + | Shared.ErrorEvent + | Shared.HeartbeatEvent; export interface InvocationCreateParams { /** diff --git a/src/resources/shared.ts b/src/resources/shared.ts index 1760bd40..d1ac1294 100644 --- a/src/resources/shared.ts +++ b/src/resources/shared.ts @@ -48,6 +48,21 @@ export interface ErrorModel { inner_error?: ErrorDetail; } +/** + * Heartbeat event sent periodically to keep SSE connection alive. + */ +export interface HeartbeatEvent { + /** + * Event type identifier (always "sse_heartbeat"). + */ + event: 'sse_heartbeat'; + + /** + * Time the heartbeat was sent. + */ + timestamp: string; +} + /** * A log entry from the application. */ diff --git a/tests/api-resources/deployments.test.ts b/tests/api-resources/deployments.test.ts index d8d0b1dc..e7fd3eb1 100644 --- a/tests/api-resources/deployments.test.ts +++ b/tests/api-resources/deployments.test.ts @@ -58,4 +58,16 @@ describe('resource deployments', () => { expect(dataAndResponse.data).toBe(response); expect(dataAndResponse.response).toBe(rawResponse); }); + + // skipped: currently no good way to test endpoints with content type text/event-stream, Prism mock server will fail + test.skip('follow: 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.deployments.follow( + 'id', + { since: '2025-06-20T12:00:00Z' }, + { path: '/_stainless_unknown_path' }, + ), + ).rejects.toThrow(Kernel.NotFoundError); + }); }); From bd2483ba96cc7a3fb04ca51421f30e2e65e25fe1 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 24 Jun 2025 19:53:08 +0000 Subject: [PATCH 101/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 5d02000a..bf5f1fb2 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.6.1" + ".": "0.6.2" } diff --git a/package.json b/package.json index 5ff0a3fb..22484c90 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.6.1", + "version": "0.6.2", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 3998d8e5..0d52c9ad 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.6.1'; // x-release-please-version +export const VERSION = '0.6.2'; // x-release-please-version From 13e355b5fc2d44a5a70c304adf3d894e1a7d8c17 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 25 Jun 2025 12:51:14 +0000 Subject: [PATCH 102/551] feat(api): /browsers no longer requires invocation id --- .stats.yml | 4 ++-- src/resources/browsers.ts | 11 ++++++----- tests/api-resources/browsers.test.ts | 22 ++++++++++++++-------- 3 files changed, 22 insertions(+), 15 deletions(-) diff --git a/.stats.yml b/.stats.yml index b296d07c..60f163b9 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 16 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-2aec229ccf91f7c1ac95aa675ea2a59bd61af9e363a22c3b49677992f1eeb16a.yml -openapi_spec_hash: c80cd5d52a79cd5366a76d4a825bd27a +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-ff8ccba8b5409eaa1128df9027582cb63f66e8accd75e511f70b7c27ef26c9ae.yml +openapi_spec_hash: 1dbacc339695a7c78718f90f791d3f01 config_hash: b8e1fff080fbaa22656ab0a57b591777 diff --git a/src/resources/browsers.ts b/src/resources/browsers.ts index adc075f2..ac3ffac2 100644 --- a/src/resources/browsers.ts +++ b/src/resources/browsers.ts @@ -13,12 +13,13 @@ export class Browsers extends APIResource { * * @example * ```ts - * const browser = await client.browsers.create({ - * invocation_id: 'rr33xuugxj9h0bkf1rdt2bet', - * }); + * const browser = await client.browsers.create(); * ``` */ - create(body: BrowserCreateParams, options?: RequestOptions): APIPromise { + create( + body: BrowserCreateParams | null | undefined = {}, + options?: RequestOptions, + ): APIPromise { return this._client.post('/browsers', { body, ...options }); } @@ -169,7 +170,7 @@ export interface BrowserCreateParams { /** * action invocation ID */ - invocation_id: string; + invocation_id?: string; /** * Optional persistence configuration for the browser session. diff --git a/tests/api-resources/browsers.test.ts b/tests/api-resources/browsers.test.ts index c6f09675..24863a99 100644 --- a/tests/api-resources/browsers.test.ts +++ b/tests/api-resources/browsers.test.ts @@ -9,8 +9,8 @@ const client = new Kernel({ describe('resource browsers', () => { // skipped: tests are disabled for the time being - test.skip('create: only required params', async () => { - const responsePromise = client.browsers.create({ invocation_id: 'rr33xuugxj9h0bkf1rdt2bet' }); + test.skip('create', async () => { + const responsePromise = client.browsers.create(); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -21,12 +21,18 @@ describe('resource browsers', () => { }); // skipped: tests are disabled for the time being - test.skip('create: required and optional params', async () => { - const response = await client.browsers.create({ - invocation_id: 'rr33xuugxj9h0bkf1rdt2bet', - persistence: { id: 'my-awesome-browser-for-user-1234' }, - stealth: true, - }); + test.skip('create: 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.create( + { + invocation_id: 'rr33xuugxj9h0bkf1rdt2bet', + persistence: { id: 'my-awesome-browser-for-user-1234' }, + stealth: true, + }, + { path: '/_stainless_unknown_path' }, + ), + ).rejects.toThrow(Kernel.NotFoundError); }); // skipped: tests are disabled for the time being From 6cbb7d8dcee8602224fb7c4ef283bc1a4a8410d1 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 25 Jun 2025 12:54:51 +0000 Subject: [PATCH 103/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index bf5f1fb2..7e23a4f8 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.6.2" + ".": "0.6.3" } diff --git a/package.json b/package.json index 22484c90..2b07af90 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.6.2", + "version": "0.6.3", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 0d52c9ad..ae4dccc6 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.6.2'; // x-release-please-version +export const VERSION = '0.6.3'; // x-release-please-version From 0d2ff8f8e1e0674b161988eaf7c15b66f22e2b19 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 27 Jun 2025 02:34:24 +0000 Subject: [PATCH 104/551] =?UTF-8?q?fix(ci):=20release-doctor=20=E2=80=94?= =?UTF-8?q?=20report=20correct=20token=20name?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bin/check-release-environment | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/check-release-environment b/bin/check-release-environment index 530e8533..e4b6d58e 100644 --- a/bin/check-release-environment +++ b/bin/check-release-environment @@ -3,7 +3,7 @@ errors=() if [ -z "${NPM_TOKEN}" ]; then - errors+=("The KERNEL_NPM_TOKEN secret has not been set. Please set it in either this repository's secrets or your organization secrets") + errors+=("The NPM_TOKEN secret has not been set. Please set it in either this repository's secrets or your organization secrets") fi lenErrors=${#errors[@]} From 6c29e0e49a5615f06be366bdc958986135ceac94 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 27 Jun 2025 05:37:23 +0000 Subject: [PATCH 105/551] fix(client): get fetchOptions type more reliably --- src/internal/types.ts | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/internal/types.ts b/src/internal/types.ts index d7928cd3..b668dfc0 100644 --- a/src/internal/types.ts +++ b/src/internal/types.ts @@ -7,7 +7,7 @@ export type KeysEnum = { [P in keyof Required]: true }; export type FinalizedRequestInit = RequestInit & { headers: Headers }; -type NotAny = [unknown] extends [T] ? never : T; +type NotAny = [0] extends [1 & T] ? never : T; /** * Some environments overload the global fetch function, and Parameters only gets the last signature. @@ -64,13 +64,15 @@ type OverloadedParameters = * [1]: https://www.typescriptlang.org/tsconfig/#typeAcquisition */ /** @ts-ignore For users with \@types/node */ -type UndiciTypesRequestInit = NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny; +type UndiciTypesRequestInit = NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny; /** @ts-ignore For users with undici */ -type UndiciRequestInit = NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny; +type UndiciRequestInit = NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny; /** @ts-ignore For users with \@types/bun */ type BunRequestInit = globalThis.FetchRequestInit; -/** @ts-ignore For users with node-fetch */ -type NodeFetchRequestInit = NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny; +/** @ts-ignore For users with node-fetch@2 */ +type NodeFetch2RequestInit = NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny; +/** @ts-ignore For users with node-fetch@3, doesn't need file extension because types are at ./@types/index.d.ts */ +type NodeFetch3RequestInit = NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny; /** @ts-ignore For users who use Deno */ type FetchRequestInit = NonNullable[1]>; /* eslint-enable */ @@ -79,7 +81,8 @@ type RequestInits = | NotAny | NotAny | NotAny - | NotAny + | NotAny + | NotAny | NotAny | NotAny; From 235c990eebd1f2eaef1437ffc1c1e67ba5db7e7f Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 27 Jun 2025 17:02:27 +0000 Subject: [PATCH 106/551] feat(api): add GET deployments endpoint --- .stats.yml | 8 +-- api.md | 3 + src/client.ts | 5 ++ src/resources/apps/apps.ts | 16 +++-- src/resources/apps/deployments.ts | 11 +--- src/resources/deployments.ts | 87 +++++++++++++++++++++---- src/resources/index.ts | 2 + src/resources/shared.ts | 10 +++ tests/api-resources/deployments.test.ts | 20 ++++++ 9 files changed, 130 insertions(+), 32 deletions(-) diff --git a/.stats.yml b/.stats.yml index 60f163b9..9625f4ef 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 16 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-ff8ccba8b5409eaa1128df9027582cb63f66e8accd75e511f70b7c27ef26c9ae.yml -openapi_spec_hash: 1dbacc339695a7c78718f90f791d3f01 -config_hash: b8e1fff080fbaa22656ab0a57b591777 +configured_endpoints: 17 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-2eeb61205775c5997abf8154cd6f6fe81a1e83870eff10050b17ed415aa7860b.yml +openapi_spec_hash: 63405add4a3f53718f8183cbb8c1a22f +config_hash: 00ec9df250b9dc077f8d3b93a442d252 diff --git a/api.md b/api.md index a8ada60f..736d6e74 100644 --- a/api.md +++ b/api.md @@ -2,6 +2,7 @@ Types: +- AppAction - ErrorDetail - ErrorEvent - ErrorModel @@ -15,12 +16,14 @@ Types: - DeploymentStateEvent - DeploymentCreateResponse - DeploymentRetrieveResponse +- DeploymentListResponse - DeploymentFollowResponse Methods: - client.deployments.create({ ...params }) -> DeploymentCreateResponse - client.deployments.retrieve(id) -> DeploymentRetrieveResponse +- client.deployments.list({ ...params }) -> DeploymentListResponse - client.deployments.follow(id, { ...params }) -> DeploymentFollowResponse # Apps diff --git a/src/client.ts b/src/client.ts index a01ed699..271e14fc 100644 --- a/src/client.ts +++ b/src/client.ts @@ -30,6 +30,8 @@ import { DeploymentCreateResponse, DeploymentFollowParams, DeploymentFollowResponse, + DeploymentListParams, + DeploymentListResponse, DeploymentRetrieveResponse, DeploymentStateEvent, Deployments, @@ -778,8 +780,10 @@ export declare namespace Kernel { type DeploymentStateEvent as DeploymentStateEvent, type DeploymentCreateResponse as DeploymentCreateResponse, type DeploymentRetrieveResponse as DeploymentRetrieveResponse, + type DeploymentListResponse as DeploymentListResponse, type DeploymentFollowResponse as DeploymentFollowResponse, type DeploymentCreateParams as DeploymentCreateParams, + type DeploymentListParams as DeploymentListParams, type DeploymentFollowParams as DeploymentFollowParams, }; @@ -806,6 +810,7 @@ export declare namespace Kernel { type BrowserDeleteParams as BrowserDeleteParams, }; + export type AppAction = API.AppAction; export type ErrorDetail = API.ErrorDetail; export type ErrorEvent = API.ErrorEvent; export type ErrorModel = API.ErrorModel; diff --git a/src/resources/apps/apps.ts b/src/resources/apps/apps.ts index 227fba81..895af238 100644 --- a/src/resources/apps/apps.ts +++ b/src/resources/apps/apps.ts @@ -1,6 +1,7 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. import { APIResource } from '../../core/resource'; +import * as Shared from '../shared'; import * as DeploymentsAPI from './deployments'; import { DeploymentCreateParams, @@ -39,6 +40,11 @@ export namespace AppListResponse { */ id: string; + /** + * List of actions available on the app + */ + actions: Array; + /** * Name of the application */ @@ -49,6 +55,11 @@ export namespace AppListResponse { */ deployment: string; + /** + * Environment variables configured for this app version + */ + env_vars: { [key: string]: string }; + /** * Deployment region code */ @@ -58,11 +69,6 @@ export namespace AppListResponse { * Version label for the application */ version: string; - - /** - * Environment variables configured for this app version - */ - env_vars?: { [key: string]: string }; } } diff --git a/src/resources/apps/deployments.ts b/src/resources/apps/deployments.ts index fc619791..109fa692 100644 --- a/src/resources/apps/deployments.ts +++ b/src/resources/apps/deployments.ts @@ -72,22 +72,13 @@ export namespace DeploymentCreateResponse { /** * List of actions available on the app */ - actions: Array; + actions: Array; /** * Name of the app */ name: string; } - - export namespace App { - export interface Action { - /** - * Name of the action - */ - name: string; - } - } } /** diff --git a/src/resources/deployments.ts b/src/resources/deployments.ts index 33f9dcc2..6cb5672e 100644 --- a/src/resources/deployments.ts +++ b/src/resources/deployments.ts @@ -38,6 +38,21 @@ export class Deployments extends APIResource { return this._client.get(path`/deployments/${id}`, options); } + /** + * List deployments. Optionally filter by application name. + * + * @example + * ```ts + * const deployments = await client.deployments.list(); + * ``` + */ + list( + query: DeploymentListParams | null | undefined = {}, + options?: RequestOptions, + ): APIPromise { + return this._client.get('/deployments', { query, ...options }); + } + /** * Establishes a Server-Sent Events (SSE) stream that delivers real-time logs and * status updates for a deployment. The stream terminates automatically once the @@ -219,6 +234,55 @@ export interface DeploymentRetrieveResponse { updated_at?: string | null; } +export type DeploymentListResponse = Array; + +export namespace DeploymentListResponse { + /** + * Deployment record information. + */ + export interface DeploymentListResponseItem { + /** + * Unique identifier for the deployment + */ + id: string; + + /** + * Timestamp when the deployment was created + */ + created_at: string; + + /** + * Deployment region code + */ + region: 'aws.us-east-1a'; + + /** + * Current status of the deployment + */ + status: 'queued' | 'in_progress' | 'running' | 'failed' | 'stopped'; + + /** + * Relative path to the application entrypoint + */ + entrypoint_rel_path?: string; + + /** + * Environment variables configured for this deployment + */ + env_vars?: { [key: string]: string }; + + /** + * Status reason + */ + status_reason?: string; + + /** + * Timestamp when the deployment was last updated + */ + updated_at?: string | null; + } +} + /** * Union type representing any deployment event. */ @@ -242,7 +306,7 @@ export namespace DeploymentFollowResponse { /** * List of actions available on the app */ - actions: Array; + actions: Array; /** * Name of the application @@ -274,18 +338,6 @@ export namespace DeploymentFollowResponse { */ env_vars?: { [key: string]: string }; } - - export namespace AppVersionSummaryEvent { - /** - * An action available on the app - */ - export interface Action { - /** - * Name of the action - */ - name: string; - } - } } export interface DeploymentCreateParams { @@ -321,6 +373,13 @@ export interface DeploymentCreateParams { version?: string; } +export interface DeploymentListParams { + /** + * Filter results by application name. + */ + app_name?: string; +} + export interface DeploymentFollowParams { /** * Show logs since the given time (RFC timestamps or durations like 5m). @@ -333,8 +392,10 @@ export declare namespace Deployments { type DeploymentStateEvent as DeploymentStateEvent, type DeploymentCreateResponse as DeploymentCreateResponse, type DeploymentRetrieveResponse as DeploymentRetrieveResponse, + type DeploymentListResponse as DeploymentListResponse, type DeploymentFollowResponse as DeploymentFollowResponse, type DeploymentCreateParams as DeploymentCreateParams, + type DeploymentListParams as DeploymentListParams, type DeploymentFollowParams as DeploymentFollowParams, }; } diff --git a/src/resources/index.ts b/src/resources/index.ts index b59024df..b48f0f01 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -16,8 +16,10 @@ export { type DeploymentStateEvent, type DeploymentCreateResponse, type DeploymentRetrieveResponse, + type DeploymentListResponse, type DeploymentFollowResponse, type DeploymentCreateParams, + type DeploymentListParams, type DeploymentFollowParams, } from './deployments'; export { diff --git a/src/resources/shared.ts b/src/resources/shared.ts index d1ac1294..c44734e2 100644 --- a/src/resources/shared.ts +++ b/src/resources/shared.ts @@ -1,5 +1,15 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +/** + * An action available on the app + */ +export interface AppAction { + /** + * Name of the action + */ + name: string; +} + export interface ErrorDetail { /** * Lower-level error code providing more specific detail diff --git a/tests/api-resources/deployments.test.ts b/tests/api-resources/deployments.test.ts index e7fd3eb1..83eb8d76 100644 --- a/tests/api-resources/deployments.test.ts +++ b/tests/api-resources/deployments.test.ts @@ -47,6 +47,26 @@ describe('resource deployments', () => { expect(dataAndResponse.response).toBe(rawResponse); }); + // skipped: tests are disabled for the time being + test.skip('list', async () => { + const responsePromise = client.deployments.list(); + 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('list: 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.deployments.list({ app_name: 'app_name' }, { path: '/_stainless_unknown_path' }), + ).rejects.toThrow(Kernel.NotFoundError); + }); + // skipped: currently no good way to test endpoints with content type text/event-stream, Prism mock server will fail test.skip('follow', async () => { const responsePromise = client.deployments.follow('id'); From f902c83c39951074c131823e308c9e18dddfd4c2 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 27 Jun 2025 17:02:54 +0000 Subject: [PATCH 107/551] feat(api): manual updates --- .stats.yml | 6 +- api.md | 2 - src/client.ts | 4 -- src/resources/apps/apps.ts | 16 ++---- src/resources/apps/deployments.ts | 11 +++- src/resources/deployments.ts | 73 ------------------------- src/resources/index.ts | 2 - tests/api-resources/deployments.test.ts | 20 ------- 8 files changed, 18 insertions(+), 116 deletions(-) diff --git a/.stats.yml b/.stats.yml index 9625f4ef..731478af 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-2eeb61205775c5997abf8154cd6f6fe81a1e83870eff10050b17ed415aa7860b.yml -openapi_spec_hash: 63405add4a3f53718f8183cbb8c1a22f +configured_endpoints: 16 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-ff8ccba8b5409eaa1128df9027582cb63f66e8accd75e511f70b7c27ef26c9ae.yml +openapi_spec_hash: 1dbacc339695a7c78718f90f791d3f01 config_hash: 00ec9df250b9dc077f8d3b93a442d252 diff --git a/api.md b/api.md index 736d6e74..ce737bf8 100644 --- a/api.md +++ b/api.md @@ -16,14 +16,12 @@ Types: - DeploymentStateEvent - DeploymentCreateResponse - DeploymentRetrieveResponse -- DeploymentListResponse - DeploymentFollowResponse Methods: - client.deployments.create({ ...params }) -> DeploymentCreateResponse - client.deployments.retrieve(id) -> DeploymentRetrieveResponse -- client.deployments.list({ ...params }) -> DeploymentListResponse - client.deployments.follow(id, { ...params }) -> DeploymentFollowResponse # Apps diff --git a/src/client.ts b/src/client.ts index 271e14fc..86f4d32c 100644 --- a/src/client.ts +++ b/src/client.ts @@ -30,8 +30,6 @@ import { DeploymentCreateResponse, DeploymentFollowParams, DeploymentFollowResponse, - DeploymentListParams, - DeploymentListResponse, DeploymentRetrieveResponse, DeploymentStateEvent, Deployments, @@ -780,10 +778,8 @@ export declare namespace Kernel { type DeploymentStateEvent as DeploymentStateEvent, type DeploymentCreateResponse as DeploymentCreateResponse, type DeploymentRetrieveResponse as DeploymentRetrieveResponse, - type DeploymentListResponse as DeploymentListResponse, type DeploymentFollowResponse as DeploymentFollowResponse, type DeploymentCreateParams as DeploymentCreateParams, - type DeploymentListParams as DeploymentListParams, type DeploymentFollowParams as DeploymentFollowParams, }; diff --git a/src/resources/apps/apps.ts b/src/resources/apps/apps.ts index 895af238..227fba81 100644 --- a/src/resources/apps/apps.ts +++ b/src/resources/apps/apps.ts @@ -1,7 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. import { APIResource } from '../../core/resource'; -import * as Shared from '../shared'; import * as DeploymentsAPI from './deployments'; import { DeploymentCreateParams, @@ -40,11 +39,6 @@ export namespace AppListResponse { */ id: string; - /** - * List of actions available on the app - */ - actions: Array; - /** * Name of the application */ @@ -55,11 +49,6 @@ export namespace AppListResponse { */ deployment: string; - /** - * Environment variables configured for this app version - */ - env_vars: { [key: string]: string }; - /** * Deployment region code */ @@ -69,6 +58,11 @@ export namespace AppListResponse { * Version label for the application */ version: string; + + /** + * Environment variables configured for this app version + */ + env_vars?: { [key: string]: string }; } } diff --git a/src/resources/apps/deployments.ts b/src/resources/apps/deployments.ts index 109fa692..fc619791 100644 --- a/src/resources/apps/deployments.ts +++ b/src/resources/apps/deployments.ts @@ -72,13 +72,22 @@ export namespace DeploymentCreateResponse { /** * List of actions available on the app */ - actions: Array; + actions: Array; /** * Name of the app */ name: string; } + + export namespace App { + export interface Action { + /** + * Name of the action + */ + name: string; + } + } } /** diff --git a/src/resources/deployments.ts b/src/resources/deployments.ts index 6cb5672e..87fa9904 100644 --- a/src/resources/deployments.ts +++ b/src/resources/deployments.ts @@ -38,21 +38,6 @@ export class Deployments extends APIResource { return this._client.get(path`/deployments/${id}`, options); } - /** - * List deployments. Optionally filter by application name. - * - * @example - * ```ts - * const deployments = await client.deployments.list(); - * ``` - */ - list( - query: DeploymentListParams | null | undefined = {}, - options?: RequestOptions, - ): APIPromise { - return this._client.get('/deployments', { query, ...options }); - } - /** * Establishes a Server-Sent Events (SSE) stream that delivers real-time logs and * status updates for a deployment. The stream terminates automatically once the @@ -234,55 +219,6 @@ export interface DeploymentRetrieveResponse { updated_at?: string | null; } -export type DeploymentListResponse = Array; - -export namespace DeploymentListResponse { - /** - * Deployment record information. - */ - export interface DeploymentListResponseItem { - /** - * Unique identifier for the deployment - */ - id: string; - - /** - * Timestamp when the deployment was created - */ - created_at: string; - - /** - * Deployment region code - */ - region: 'aws.us-east-1a'; - - /** - * Current status of the deployment - */ - status: 'queued' | 'in_progress' | 'running' | 'failed' | 'stopped'; - - /** - * Relative path to the application entrypoint - */ - entrypoint_rel_path?: string; - - /** - * Environment variables configured for this deployment - */ - env_vars?: { [key: string]: string }; - - /** - * Status reason - */ - status_reason?: string; - - /** - * Timestamp when the deployment was last updated - */ - updated_at?: string | null; - } -} - /** * Union type representing any deployment event. */ @@ -373,13 +309,6 @@ export interface DeploymentCreateParams { version?: string; } -export interface DeploymentListParams { - /** - * Filter results by application name. - */ - app_name?: string; -} - export interface DeploymentFollowParams { /** * Show logs since the given time (RFC timestamps or durations like 5m). @@ -392,10 +321,8 @@ export declare namespace Deployments { type DeploymentStateEvent as DeploymentStateEvent, type DeploymentCreateResponse as DeploymentCreateResponse, type DeploymentRetrieveResponse as DeploymentRetrieveResponse, - type DeploymentListResponse as DeploymentListResponse, type DeploymentFollowResponse as DeploymentFollowResponse, type DeploymentCreateParams as DeploymentCreateParams, - type DeploymentListParams as DeploymentListParams, type DeploymentFollowParams as DeploymentFollowParams, }; } diff --git a/src/resources/index.ts b/src/resources/index.ts index b48f0f01..b59024df 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -16,10 +16,8 @@ export { type DeploymentStateEvent, type DeploymentCreateResponse, type DeploymentRetrieveResponse, - type DeploymentListResponse, type DeploymentFollowResponse, type DeploymentCreateParams, - type DeploymentListParams, type DeploymentFollowParams, } from './deployments'; export { diff --git a/tests/api-resources/deployments.test.ts b/tests/api-resources/deployments.test.ts index 83eb8d76..e7fd3eb1 100644 --- a/tests/api-resources/deployments.test.ts +++ b/tests/api-resources/deployments.test.ts @@ -47,26 +47,6 @@ describe('resource deployments', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // skipped: tests are disabled for the time being - test.skip('list', async () => { - const responsePromise = client.deployments.list(); - 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('list: 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.deployments.list({ app_name: 'app_name' }, { path: '/_stainless_unknown_path' }), - ).rejects.toThrow(Kernel.NotFoundError); - }); - // skipped: currently no good way to test endpoints with content type text/event-stream, Prism mock server will fail test.skip('follow', async () => { const responsePromise = client.deployments.follow('id'); From 319a5821db01e956503e5d106e7c3de7fc549c9a Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 27 Jun 2025 17:04:09 +0000 Subject: [PATCH 108/551] feat(api): deployments --- .stats.yml | 6 +- api.md | 2 + src/client.ts | 4 ++ src/resources/apps/apps.ts | 16 ++++-- src/resources/apps/deployments.ts | 11 +--- src/resources/deployments.ts | 73 +++++++++++++++++++++++++ src/resources/index.ts | 2 + tests/api-resources/deployments.test.ts | 20 +++++++ 8 files changed, 116 insertions(+), 18 deletions(-) diff --git a/.stats.yml b/.stats.yml index 731478af..9625f4ef 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 16 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-ff8ccba8b5409eaa1128df9027582cb63f66e8accd75e511f70b7c27ef26c9ae.yml -openapi_spec_hash: 1dbacc339695a7c78718f90f791d3f01 +configured_endpoints: 17 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-2eeb61205775c5997abf8154cd6f6fe81a1e83870eff10050b17ed415aa7860b.yml +openapi_spec_hash: 63405add4a3f53718f8183cbb8c1a22f config_hash: 00ec9df250b9dc077f8d3b93a442d252 diff --git a/api.md b/api.md index ce737bf8..736d6e74 100644 --- a/api.md +++ b/api.md @@ -16,12 +16,14 @@ Types: - DeploymentStateEvent - DeploymentCreateResponse - DeploymentRetrieveResponse +- DeploymentListResponse - DeploymentFollowResponse Methods: - client.deployments.create({ ...params }) -> DeploymentCreateResponse - client.deployments.retrieve(id) -> DeploymentRetrieveResponse +- client.deployments.list({ ...params }) -> DeploymentListResponse - client.deployments.follow(id, { ...params }) -> DeploymentFollowResponse # Apps diff --git a/src/client.ts b/src/client.ts index 86f4d32c..271e14fc 100644 --- a/src/client.ts +++ b/src/client.ts @@ -30,6 +30,8 @@ import { DeploymentCreateResponse, DeploymentFollowParams, DeploymentFollowResponse, + DeploymentListParams, + DeploymentListResponse, DeploymentRetrieveResponse, DeploymentStateEvent, Deployments, @@ -778,8 +780,10 @@ export declare namespace Kernel { type DeploymentStateEvent as DeploymentStateEvent, type DeploymentCreateResponse as DeploymentCreateResponse, type DeploymentRetrieveResponse as DeploymentRetrieveResponse, + type DeploymentListResponse as DeploymentListResponse, type DeploymentFollowResponse as DeploymentFollowResponse, type DeploymentCreateParams as DeploymentCreateParams, + type DeploymentListParams as DeploymentListParams, type DeploymentFollowParams as DeploymentFollowParams, }; diff --git a/src/resources/apps/apps.ts b/src/resources/apps/apps.ts index 227fba81..895af238 100644 --- a/src/resources/apps/apps.ts +++ b/src/resources/apps/apps.ts @@ -1,6 +1,7 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. import { APIResource } from '../../core/resource'; +import * as Shared from '../shared'; import * as DeploymentsAPI from './deployments'; import { DeploymentCreateParams, @@ -39,6 +40,11 @@ export namespace AppListResponse { */ id: string; + /** + * List of actions available on the app + */ + actions: Array; + /** * Name of the application */ @@ -49,6 +55,11 @@ export namespace AppListResponse { */ deployment: string; + /** + * Environment variables configured for this app version + */ + env_vars: { [key: string]: string }; + /** * Deployment region code */ @@ -58,11 +69,6 @@ export namespace AppListResponse { * Version label for the application */ version: string; - - /** - * Environment variables configured for this app version - */ - env_vars?: { [key: string]: string }; } } diff --git a/src/resources/apps/deployments.ts b/src/resources/apps/deployments.ts index fc619791..109fa692 100644 --- a/src/resources/apps/deployments.ts +++ b/src/resources/apps/deployments.ts @@ -72,22 +72,13 @@ export namespace DeploymentCreateResponse { /** * List of actions available on the app */ - actions: Array; + actions: Array; /** * Name of the app */ name: string; } - - export namespace App { - export interface Action { - /** - * Name of the action - */ - name: string; - } - } } /** diff --git a/src/resources/deployments.ts b/src/resources/deployments.ts index 87fa9904..6cb5672e 100644 --- a/src/resources/deployments.ts +++ b/src/resources/deployments.ts @@ -38,6 +38,21 @@ export class Deployments extends APIResource { return this._client.get(path`/deployments/${id}`, options); } + /** + * List deployments. Optionally filter by application name. + * + * @example + * ```ts + * const deployments = await client.deployments.list(); + * ``` + */ + list( + query: DeploymentListParams | null | undefined = {}, + options?: RequestOptions, + ): APIPromise { + return this._client.get('/deployments', { query, ...options }); + } + /** * Establishes a Server-Sent Events (SSE) stream that delivers real-time logs and * status updates for a deployment. The stream terminates automatically once the @@ -219,6 +234,55 @@ export interface DeploymentRetrieveResponse { updated_at?: string | null; } +export type DeploymentListResponse = Array; + +export namespace DeploymentListResponse { + /** + * Deployment record information. + */ + export interface DeploymentListResponseItem { + /** + * Unique identifier for the deployment + */ + id: string; + + /** + * Timestamp when the deployment was created + */ + created_at: string; + + /** + * Deployment region code + */ + region: 'aws.us-east-1a'; + + /** + * Current status of the deployment + */ + status: 'queued' | 'in_progress' | 'running' | 'failed' | 'stopped'; + + /** + * Relative path to the application entrypoint + */ + entrypoint_rel_path?: string; + + /** + * Environment variables configured for this deployment + */ + env_vars?: { [key: string]: string }; + + /** + * Status reason + */ + status_reason?: string; + + /** + * Timestamp when the deployment was last updated + */ + updated_at?: string | null; + } +} + /** * Union type representing any deployment event. */ @@ -309,6 +373,13 @@ export interface DeploymentCreateParams { version?: string; } +export interface DeploymentListParams { + /** + * Filter results by application name. + */ + app_name?: string; +} + export interface DeploymentFollowParams { /** * Show logs since the given time (RFC timestamps or durations like 5m). @@ -321,8 +392,10 @@ export declare namespace Deployments { type DeploymentStateEvent as DeploymentStateEvent, type DeploymentCreateResponse as DeploymentCreateResponse, type DeploymentRetrieveResponse as DeploymentRetrieveResponse, + type DeploymentListResponse as DeploymentListResponse, type DeploymentFollowResponse as DeploymentFollowResponse, type DeploymentCreateParams as DeploymentCreateParams, + type DeploymentListParams as DeploymentListParams, type DeploymentFollowParams as DeploymentFollowParams, }; } diff --git a/src/resources/index.ts b/src/resources/index.ts index b59024df..b48f0f01 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -16,8 +16,10 @@ export { type DeploymentStateEvent, type DeploymentCreateResponse, type DeploymentRetrieveResponse, + type DeploymentListResponse, type DeploymentFollowResponse, type DeploymentCreateParams, + type DeploymentListParams, type DeploymentFollowParams, } from './deployments'; export { diff --git a/tests/api-resources/deployments.test.ts b/tests/api-resources/deployments.test.ts index e7fd3eb1..83eb8d76 100644 --- a/tests/api-resources/deployments.test.ts +++ b/tests/api-resources/deployments.test.ts @@ -47,6 +47,26 @@ describe('resource deployments', () => { expect(dataAndResponse.response).toBe(rawResponse); }); + // skipped: tests are disabled for the time being + test.skip('list', async () => { + const responsePromise = client.deployments.list(); + 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('list: 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.deployments.list({ app_name: 'app_name' }, { path: '/_stainless_unknown_path' }), + ).rejects.toThrow(Kernel.NotFoundError); + }); + // skipped: currently no good way to test endpoints with content type text/event-stream, Prism mock server will fail test.skip('follow', async () => { const responsePromise = client.deployments.follow('id'); From 9b222308196818297b4f85db455161f32746f9f5 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 27 Jun 2025 17:06:28 +0000 Subject: [PATCH 109/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 7e23a4f8..eb5abf78 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.6.3" + ".": "0.6.4" } diff --git a/package.json b/package.json index 2b07af90..da5efcd0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.6.3", + "version": "0.6.4", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index ae4dccc6..67bde7c2 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.6.3'; // x-release-please-version +export const VERSION = '0.6.4'; // x-release-please-version From bd5f6d14a8dca6d6aca269ece490ee103db56922 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 28 Jun 2025 08:46:30 +0000 Subject: [PATCH 110/551] chore(ci): only run for pushes and fork pull requests --- .github/workflows/ci.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b35fe333..cc341d93 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,6 +17,7 @@ jobs: timeout-minutes: 10 name: lint runs-on: ${{ github.repository == 'stainless-sdks/kernel-typescript' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} + if: github.event_name == 'push' || github.event.pull_request.head.repo.fork steps: - uses: actions/checkout@v4 @@ -35,6 +36,7 @@ jobs: timeout-minutes: 5 name: build runs-on: ${{ github.repository == 'stainless-sdks/kernel-typescript' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} + if: github.event_name == 'push' || github.event.pull_request.head.repo.fork permissions: contents: read id-token: write @@ -70,6 +72,7 @@ jobs: timeout-minutes: 10 name: test runs-on: ${{ github.repository == 'stainless-sdks/kernel-typescript' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} + if: github.event_name == 'push' || github.event.pull_request.head.repo.fork steps: - uses: actions/checkout@v4 From 8013dd25d1d9eec3e3a81235e6413141ba300f6d Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 1 Jul 2025 02:11:51 +0000 Subject: [PATCH 111/551] chore(client): improve path param validation --- src/internal/uploads.ts | 2 +- src/internal/utils/log.ts | 2 +- src/internal/utils/path.ts | 39 +++++++-- tests/path.test.ts | 158 +++++++++++++++++++++++++++++++++++-- 4 files changed, 185 insertions(+), 16 deletions(-) diff --git a/src/internal/uploads.ts b/src/internal/uploads.ts index efffd7aa..a4e57acc 100644 --- a/src/internal/uploads.ts +++ b/src/internal/uploads.ts @@ -90,7 +90,7 @@ export const multipartFormRequestOptions = async ( return { ...opts, body: await createForm(opts.body, fetch) }; }; -const supportsFormDataMap = /** @__PURE__ */ new WeakMap>(); +const supportsFormDataMap = /* @__PURE__ */ new WeakMap>(); /** * node-fetch doesn't support the global FormData object in recent node versions. Instead of sending diff --git a/src/internal/utils/log.ts b/src/internal/utils/log.ts index 44d8f651..912b523a 100644 --- a/src/internal/utils/log.ts +++ b/src/internal/utils/log.ts @@ -58,7 +58,7 @@ const noopLogger = { debug: noop, }; -let cachedLoggers = /** @__PURE__ */ new WeakMap(); +let cachedLoggers = /* @__PURE__ */ new WeakMap(); export function loggerFor(client: Kernel): Logger { const logger = client.logger; diff --git a/src/internal/utils/path.ts b/src/internal/utils/path.ts index 8abf2784..9e1e868e 100644 --- a/src/internal/utils/path.ts +++ b/src/internal/utils/path.ts @@ -12,25 +12,43 @@ export function encodeURIPath(str: string) { return str.replace(/[^A-Za-z0-9\-._~!$&'()*+,;=:@]+/g, encodeURIComponent); } +const EMPTY = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.create(null)); + export const createPathTagFunction = (pathEncoder = encodeURIPath) => function path(statics: readonly string[], ...params: readonly unknown[]): string { // If there are no params, no processing is needed. if (statics.length === 1) return statics[0]!; let postPath = false; + const invalidSegments = []; const path = statics.reduce((previousValue, currentValue, index) => { if (/[?#]/.test(currentValue)) { postPath = true; } - return ( - previousValue + - currentValue + - (index === params.length ? '' : (postPath ? encodeURIComponent : pathEncoder)(String(params[index]))) - ); + const value = params[index]; + let encoded = (postPath ? encodeURIComponent : pathEncoder)('' + value); + if ( + index !== params.length && + (value == null || + (typeof value === 'object' && + // handle values from other realms + value.toString === + Object.getPrototypeOf(Object.getPrototypeOf((value as any).hasOwnProperty ?? EMPTY) ?? EMPTY) + ?.toString)) + ) { + encoded = value + ''; + invalidSegments.push({ + start: previousValue.length + currentValue.length, + length: encoded.length, + error: `Value of type ${Object.prototype.toString + .call(value) + .slice(8, -1)} is not a valid path parameter`, + }); + } + return previousValue + currentValue + (index === params.length ? '' : encoded); }, ''); const pathOnly = path.split(/[?#]/, 1)[0]!; - const invalidSegments = []; const invalidSegmentPattern = /(?<=^|\/)(?:\.|%2e){1,2}(?=\/|$)/gi; let match; @@ -39,9 +57,12 @@ export const createPathTagFunction = (pathEncoder = encodeURIPath) => invalidSegments.push({ start: match.index, length: match[0].length, + error: `Value "${match[0]}" can\'t be safely passed as a path parameter`, }); } + invalidSegments.sort((a, b) => a.start - b.start); + if (invalidSegments.length > 0) { let lastEnd = 0; const underline = invalidSegments.reduce((acc, segment) => { @@ -51,7 +72,11 @@ export const createPathTagFunction = (pathEncoder = encodeURIPath) => return acc + spaces + arrows; }, ''); - throw new KernelError(`Path parameters result in path with invalid segments:\n${path}\n${underline}`); + throw new KernelError( + `Path parameters result in path with invalid segments:\n${invalidSegments + .map((e) => e.error) + .join('\n')}\n${path}\n${underline}`, + ); } return path; diff --git a/tests/path.test.ts b/tests/path.test.ts index 6d7177f4..b209e96f 100644 --- a/tests/path.test.ts +++ b/tests/path.test.ts @@ -1,5 +1,6 @@ import { createPathTagFunction, encodeURIPath } from '@onkernel/sdk/internal/utils/path'; import { inspect } from 'node:util'; +import { runInNewContext } from 'node:vm'; describe('path template tag function', () => { test('validates input', () => { @@ -32,9 +33,114 @@ describe('path template tag function', () => { return testParams.flatMap((e) => rest.map((r) => [e, ...r])); } - // we need to test how %2E is handled so we use a custom encoder that does no escaping + // We need to test how %2E is handled, so we use a custom encoder that does no escaping. const rawPath = createPathTagFunction((s) => s); + const emptyObject = {}; + const mathObject = Math; + const numberObject = new Number(); + const stringObject = new String(); + const basicClass = new (class {})(); + const classWithToString = new (class { + toString() { + return 'ok'; + } + })(); + + // Invalid values + expect(() => rawPath`/a/${null}/b`).toThrow( + 'Path parameters result in path with invalid segments:\n' + + 'Value of type Null is not a valid path parameter\n' + + '/a/null/b\n' + + ' ^^^^', + ); + expect(() => rawPath`/a/${undefined}/b`).toThrow( + 'Path parameters result in path with invalid segments:\n' + + 'Value of type Undefined is not a valid path parameter\n' + + '/a/undefined/b\n' + + ' ^^^^^^^^^', + ); + expect(() => rawPath`/a/${emptyObject}/b`).toThrow( + 'Path parameters result in path with invalid segments:\n' + + 'Value of type Object is not a valid path parameter\n' + + '/a/[object Object]/b\n' + + ' ^^^^^^^^^^^^^^^', + ); + expect(() => rawPath`?${mathObject}`).toThrow( + 'Path parameters result in path with invalid segments:\n' + + 'Value of type Math is not a valid path parameter\n' + + '?[object Math]\n' + + ' ^^^^^^^^^^^^^', + ); + expect(() => rawPath`/${basicClass}`).toThrow( + 'Path parameters result in path with invalid segments:\n' + + 'Value of type Object is not a valid path parameter\n' + + '/[object Object]\n' + + ' ^^^^^^^^^^^^^^', + ); + expect(() => rawPath`/../${''}`).toThrow( + 'Path parameters result in path with invalid segments:\n' + + 'Value ".." can\'t be safely passed as a path parameter\n' + + '/../\n' + + ' ^^', + ); + expect(() => rawPath`/../${{}}`).toThrow( + 'Path parameters result in path with invalid segments:\n' + + 'Value ".." can\'t be safely passed as a path parameter\n' + + 'Value of type Object is not a valid path parameter\n' + + '/../[object Object]\n' + + ' ^^ ^^^^^^^^^^^^^^', + ); + + // Valid values + expect(rawPath`/${0}`).toBe('/0'); + expect(rawPath`/${''}`).toBe('/'); + expect(rawPath`/${numberObject}`).toBe('/0'); + expect(rawPath`${stringObject}/`).toBe('/'); + expect(rawPath`/${classWithToString}`).toBe('/ok'); + + // We need to check what happens with cross-realm values, which we might get from + // Jest or other frames in a browser. + + const newRealm = runInNewContext('globalThis'); + expect(newRealm.Object).not.toBe(Object); + + const crossRealmObject = newRealm.Object(); + const crossRealmMathObject = newRealm.Math; + const crossRealmNumber = new newRealm.Number(); + const crossRealmString = new newRealm.String(); + const crossRealmClass = new (class extends newRealm.Object {})(); + const crossRealmClassWithToString = new (class extends newRealm.Object { + toString() { + return 'ok'; + } + })(); + + // Invalid cross-realm values + expect(() => rawPath`/a/${crossRealmObject}/b`).toThrow( + 'Path parameters result in path with invalid segments:\n' + + 'Value of type Object is not a valid path parameter\n' + + '/a/[object Object]/b\n' + + ' ^^^^^^^^^^^^^^^', + ); + expect(() => rawPath`?${crossRealmMathObject}`).toThrow( + 'Path parameters result in path with invalid segments:\n' + + 'Value of type Math is not a valid path parameter\n' + + '?[object Math]\n' + + ' ^^^^^^^^^^^^^', + ); + expect(() => rawPath`/${crossRealmClass}`).toThrow( + 'Path parameters result in path with invalid segments:\n' + + 'Value of type Object is not a valid path parameter\n' + + '/[object Object]\n' + + ' ^^^^^^^^^^^^^^^', + ); + + // Valid cross-realm values + expect(rawPath`/${crossRealmNumber}`).toBe('/0'); + expect(rawPath`${crossRealmString}/`).toBe('/'); + expect(rawPath`/${crossRealmClassWithToString}`).toBe('/ok'); + const results: { [pathParts: string]: { [params: string]: { valid: boolean; result?: string; error?: string }; @@ -85,6 +191,7 @@ describe('path template tag function', () => { valid: false, error: 'Error: Path parameters result in path with invalid segments:\n' + + 'Value "%2E%2e" can\'t be safely passed as a path parameter\n' + '/path_params/%2E%2e/a\n' + ' ^^^^^^', }, @@ -92,6 +199,7 @@ describe('path template tag function', () => { valid: false, error: 'Error: Path parameters result in path with invalid segments:\n' + + 'Value "%2E" can\'t be safely passed as a path parameter\n' + '/path_params/%2E/a\n' + ' ^^^', }, @@ -103,6 +211,7 @@ describe('path template tag function', () => { valid: false, error: 'Error: Path parameters result in path with invalid segments:\n' + + 'Value "%2e%2E" can\'t be safely passed as a path parameter\n' + '/path_params/%2e%2E/\n' + ' ^^^^^^', }, @@ -110,6 +219,7 @@ describe('path template tag function', () => { valid: false, error: 'Error: Path parameters result in path with invalid segments:\n' + + 'Value "%2e" can\'t be safely passed as a path parameter\n' + '/path_params/%2e/\n' + ' ^^^', }, @@ -121,6 +231,7 @@ describe('path template tag function', () => { valid: false, error: 'Error: Path parameters result in path with invalid segments:\n' + + 'Value "%2E" can\'t be safely passed as a path parameter\n' + '/path_params/%2E\n' + ' ^^^', }, @@ -128,6 +239,7 @@ describe('path template tag function', () => { valid: false, error: 'Error: Path parameters result in path with invalid segments:\n' + + 'Value "%2E%2e" can\'t be safely passed as a path parameter\n' + '/path_params/%2E%2e\n' + ' ^^^^^^', }, @@ -137,11 +249,17 @@ describe('path template tag function', () => { '["x"]': { valid: true, result: 'x/a' }, '["%2E"]': { valid: false, - error: 'Error: Path parameters result in path with invalid segments:\n%2E/a\n^^^', + error: + 'Error: Path parameters result in path with invalid segments:\n' + + 'Value "%2E" can\'t be safely passed as a path parameter\n%2E/a\n^^^', }, '["%2e%2E"]': { valid: false, - error: 'Error: Path parameters result in path with invalid segments:\n' + '%2e%2E/a\n' + '^^^^^^', + error: + 'Error: Path parameters result in path with invalid segments:\n' + + 'Value "%2e%2E" can\'t be safely passed as a path parameter\n' + + '%2e%2E/a\n' + + '^^^^^^', }, }, '["","/"]': { @@ -149,11 +267,18 @@ describe('path template tag function', () => { '[""]': { valid: true, result: '/' }, '["%2E%2e"]': { valid: false, - error: 'Error: Path parameters result in path with invalid segments:\n' + '%2E%2e/\n' + '^^^^^^', + error: + 'Error: Path parameters result in path with invalid segments:\n' + + 'Value "%2E%2e" can\'t be safely passed as a path parameter\n' + + '%2E%2e/\n' + + '^^^^^^', }, '["."]': { valid: false, - error: 'Error: Path parameters result in path with invalid segments:\n./\n^', + error: + 'Error: Path parameters result in path with invalid segments:\n' + + 'Value "." can\'t be safely passed as a path parameter\n' + + './\n^', }, }, '["",""]': { @@ -161,11 +286,17 @@ describe('path template tag function', () => { '["x"]': { valid: true, result: 'x' }, '[".."]': { valid: false, - error: 'Error: Path parameters result in path with invalid segments:\n..\n^^', + error: + 'Error: Path parameters result in path with invalid segments:\n' + + 'Value ".." can\'t be safely passed as a path parameter\n' + + '..\n^^', }, '["."]': { valid: false, - error: 'Error: Path parameters result in path with invalid segments:\n.\n^', + error: + 'Error: Path parameters result in path with invalid segments:\n' + + 'Value "." can\'t be safely passed as a path parameter\n' + + '.\n^', }, }, '["a"]': {}, @@ -185,6 +316,7 @@ describe('path template tag function', () => { valid: false, error: 'Error: Path parameters result in path with invalid segments:\n' + + 'Value "%2E%2E" can\'t be safely passed as a path parameter\n' + '/path_params/%2E%2E?beta=true\n' + ' ^^^^^^', }, @@ -192,6 +324,7 @@ describe('path template tag function', () => { valid: false, error: 'Error: Path parameters result in path with invalid segments:\n' + + 'Value "%2e%2E" can\'t be safely passed as a path parameter\n' + '/path_params/%2e%2E?beta=true\n' + ' ^^^^^^', }, @@ -203,6 +336,7 @@ describe('path template tag function', () => { valid: false, error: 'Error: Path parameters result in path with invalid segments:\n' + + 'Value "." can\'t be safely passed as a path parameter\n' + '/path_params/.?beta=true\n' + ' ^', }, @@ -210,6 +344,7 @@ describe('path template tag function', () => { valid: false, error: 'Error: Path parameters result in path with invalid segments:\n' + + 'Value "%2e." can\'t be safely passed as a path parameter\n' + '/path_params/%2e.?beta=true\n' + ' ^^^^', }, @@ -221,6 +356,8 @@ describe('path template tag function', () => { valid: false, error: 'Error: Path parameters result in path with invalid segments:\n' + + 'Value "." can\'t be safely passed as a path parameter\n' + + 'Value "%2e" can\'t be safely passed as a path parameter\n' + '/path_params/./%2e/download\n' + ' ^ ^^^', }, @@ -228,6 +365,8 @@ describe('path template tag function', () => { valid: false, error: 'Error: Path parameters result in path with invalid segments:\n' + + 'Value "%2E%2e" can\'t be safely passed as a path parameter\n' + + 'Value "%2e" can\'t be safely passed as a path parameter\n' + '/path_params/%2E%2e/%2e/download\n' + ' ^^^^^^ ^^^', }, @@ -243,6 +382,7 @@ describe('path template tag function', () => { valid: false, error: 'Error: Path parameters result in path with invalid segments:\n' + + 'Value "%2E" can\'t be safely passed as a path parameter\n' + '/path_params/%2E/download\n' + ' ^^^', }, @@ -250,6 +390,7 @@ describe('path template tag function', () => { valid: false, error: 'Error: Path parameters result in path with invalid segments:\n' + + 'Value "%2E." can\'t be safely passed as a path parameter\n' + '/path_params/%2E./download\n' + ' ^^^^', }, @@ -261,6 +402,7 @@ describe('path template tag function', () => { valid: false, error: 'Error: Path parameters result in path with invalid segments:\n' + + 'Value "." can\'t be safely passed as a path parameter\n' + '/path_params/./download\n' + ' ^', }, @@ -268,6 +410,7 @@ describe('path template tag function', () => { valid: false, error: 'Error: Path parameters result in path with invalid segments:\n' + + 'Value ".." can\'t be safely passed as a path parameter\n' + '/path_params/../download\n' + ' ^^', }, @@ -279,6 +422,7 @@ describe('path template tag function', () => { valid: false, error: 'Error: Path parameters result in path with invalid segments:\n' + + 'Value ".." can\'t be safely passed as a path parameter\n' + '/path_params/../download\n' + ' ^^', }, From d1525d2afa6ad39d1292d37003aaae453e04f301 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 2 Jul 2025 19:04:19 +0000 Subject: [PATCH 112/551] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 9625f4ef..d45a618a 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-2eeb61205775c5997abf8154cd6f6fe81a1e83870eff10050b17ed415aa7860b.yml -openapi_spec_hash: 63405add4a3f53718f8183cbb8c1a22f +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-0ac9428eb663361184124cdd6a6e80ae8dc72c927626c949f22aacc4f40095de.yml +openapi_spec_hash: 27707667d706ac33f2d9ccb23c0f15c3 config_hash: 00ec9df250b9dc077f8d3b93a442d252 From fd19dd4b929e776b6f59a1389b5238813f25f90a Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 2 Jul 2025 19:08:45 +0000 Subject: [PATCH 113/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index eb5abf78..5b530ee1 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.6.4" + ".": "0.6.5" } diff --git a/package.json b/package.json index da5efcd0..3dfa61d4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.6.4", + "version": "0.6.5", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 67bde7c2..d9810da8 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.6.4'; // x-release-please-version +export const VERSION = '0.6.5'; // x-release-please-version From 85bb40defb6bed12e7fd729128f45c48a6bf30ba Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 2 Jul 2025 21:49:34 +0000 Subject: [PATCH 114/551] feat(api): headless browsers --- .stats.yml | 4 +-- src/resources/browsers.ts | 39 +++++++++++++++++----------- tests/api-resources/browsers.test.ts | 1 + 3 files changed, 27 insertions(+), 17 deletions(-) diff --git a/.stats.yml b/.stats.yml index d45a618a..401ed656 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-0ac9428eb663361184124cdd6a6e80ae8dc72c927626c949f22aacc4f40095de.yml -openapi_spec_hash: 27707667d706ac33f2d9ccb23c0f15c3 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-3ec96d0022acb32aa2676c2e7ae20152b899a776ccd499380c334c955b9ba071.yml +openapi_spec_hash: b64c095d82185c1cd0355abea88b606f config_hash: 00ec9df250b9dc077f8d3b93a442d252 diff --git a/src/resources/browsers.ts b/src/resources/browsers.ts index ac3ffac2..8afcb8c2 100644 --- a/src/resources/browsers.ts +++ b/src/resources/browsers.ts @@ -97,11 +97,6 @@ export interface BrowserPersistence { } export interface BrowserCreateResponse { - /** - * Remote URL for live viewing the browser session - */ - browser_live_view_url: string; - /** * Websocket URL for Chrome DevTools Protocol connections to the browser session */ @@ -112,6 +107,12 @@ export interface BrowserCreateResponse { */ 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. */ @@ -119,11 +120,6 @@ export interface BrowserCreateResponse { } export interface BrowserRetrieveResponse { - /** - * Remote URL for live viewing the browser session - */ - browser_live_view_url: string; - /** * Websocket URL for Chrome DevTools Protocol connections to the browser session */ @@ -134,6 +130,12 @@ export interface BrowserRetrieveResponse { */ 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. */ @@ -144,11 +146,6 @@ export type BrowserListResponse = Array { await expect( client.browsers.create( { + headless: false, invocation_id: 'rr33xuugxj9h0bkf1rdt2bet', persistence: { id: 'my-awesome-browser-for-user-1234' }, stealth: true, From 9f91d47de8c59d8aa9fc5d71b2e4015bf4967902 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 2 Jul 2025 21:51:35 +0000 Subject: [PATCH 115/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 5b530ee1..e7ca6139 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.6.5" + ".": "0.7.0" } diff --git a/package.json b/package.json index 3dfa61d4..dce29ff4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.6.5", + "version": "0.7.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index d9810da8..d9da9f72 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.6.5'; // x-release-please-version +export const VERSION = '0.7.0'; // x-release-please-version From d7d53f10c73325cdc649c25df880151e22fc398e Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 3 Jul 2025 04:06:40 +0000 Subject: [PATCH 116/551] chore: add docs to RequestOptions type --- src/client.ts | 2 ++ src/internal/request-options.ts | 53 +++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/src/client.ts b/src/client.ts index 271e14fc..79b91670 100644 --- a/src/client.ts +++ b/src/client.ts @@ -94,6 +94,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/internal/request-options.ts b/src/internal/request-options.ts index ffe01ae0..56765e5a 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; From 2727db67c23688d2263cf5844ac854c724fcb385 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 3 Jul 2025 04:43:32 +0000 Subject: [PATCH 117/551] fix: avoid console usage --- src/core/streaming.ts | 30 ++++++++++++++++++++++-------- src/internal/parse.ts | 4 ++-- 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/src/core/streaming.ts b/src/core/streaming.ts index 7191ee4c..a24bcfec 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 18d0b41f..7fe9be43 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. From 779bd307f48b4d944e468bbc34e29b6a42d7fe88 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 8 Jul 2025 18:15:26 +0000 Subject: [PATCH 118/551] feat(api): manual updates --- .stats.yml | 8 +++--- api.md | 1 + src/resources/browsers.ts | 41 ++++++++++++++++++++++++++++ tests/api-resources/browsers.test.ts | 1 + 4 files changed, 47 insertions(+), 4 deletions(-) diff --git a/.stats.yml b/.stats.yml index 401ed656..aa1aff73 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/api.md b/api.md index 736d6e74..eeda41d2 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/src/resources/browsers.ts b/src/resources/browsers.ts index 8afcb8c2..14398d43 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/tests/api-resources/browsers.test.ts b/tests/api-resources/browsers.test.ts index d28bd024..b066fa2e 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' }, From b8f9f276cf9a678b9e1fbcb3d94aebe925b5cd85 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 8 Jul 2025 18:20:23 +0000 Subject: [PATCH 119/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index e7ca6139..13708fa5 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.7.0" + ".": "0.7.1" } diff --git a/package.json b/package.json index dce29ff4..9abb8482 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/version.ts b/src/version.ts index d9da9f72..5e85c4bc 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 From f2f5fd387412738a2cc677bf656d39cc5ffbb275 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 10 Jul 2025 04:38:35 +0000 Subject: [PATCH 120/551] chore: make some internal functions async --- src/client.ts | 25 ++++++++++++++----------- tests/index.test.ts | 30 +++++++++++++++--------------- 2 files changed, 29 insertions(+), 26 deletions(-) diff --git a/src/client.ts b/src/client.ts index 79b91670..45a16f11 100644 --- a/src/client.ts +++ b/src/client.ts @@ -229,7 +229,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, @@ -242,6 +242,7 @@ export class Kernel { apiKey: this.apiKey, ...options, }); + return client; } /** @@ -259,7 +260,7 @@ export class Kernel { return; } - protected authHeaders(opts: FinalRequestOptions): NullableHeaders | undefined { + protected async authHeaders(opts: FinalRequestOptions): Promise { return buildHeaders([{ Authorization: `Bearer ${this.apiKey}` }]); } @@ -391,7 +392,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 }); @@ -469,7 +472,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`; @@ -568,7 +571,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'); @@ -645,10 +648,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; @@ -656,7 +659,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, @@ -672,7 +675,7 @@ export class Kernel { return { req, url, timeout: options.timeout }; } - private buildHeaders({ + private async buildHeaders({ options, method, bodyHeaders, @@ -682,7 +685,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(); @@ -698,7 +701,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/tests/index.test.ts b/tests/index.test.ts index 5c12c9a5..68b144c9 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, From 179fb4c2239c12616aa811fca7b994225aa22b82 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 16 Jul 2025 16:24:43 +0000 Subject: [PATCH 121/551] feat(api): manual updates replays! --- .stats.yml | 8 +- api.md | 33 ++- src/client.ts | 18 +- src/resources/browsers.ts | 252 +----------------- src/resources/browsers/browsers.ts | 234 ++++++++++++++++ src/resources/browsers/index.ts | 19 ++ src/resources/browsers/replays.ts | 168 ++++++++++++ src/resources/index.ts | 2 +- .../{ => browsers}/browsers.test.ts | 1 - tests/api-resources/browsers/replays.test.ts | 68 +++++ 10 files changed, 527 insertions(+), 276 deletions(-) create mode 100644 src/resources/browsers/browsers.ts create mode 100644 src/resources/browsers/index.ts create mode 100644 src/resources/browsers/replays.ts rename tests/api-resources/{ => browsers}/browsers.test.ts (99%) create mode 100644 tests/api-resources/browsers/replays.test.ts diff --git a/.stats.yml b/.stats.yml index aa1aff73..a0553b1e 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/api.md b/api.md index eeda41d2..6d4c5ed4 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/src/client.ts b/src/client.ts index 45a16f11..bf57ef0d 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, @@ -47,6 +38,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'; diff --git a/src/resources/browsers.ts b/src/resources/browsers.ts index 14398d43..7d73ffd7 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 00000000..1f8f2046 --- /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 00000000..deb5900e --- /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 00000000..208d8c37 --- /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 b48f0f01..f51eb778 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/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 b066fa2e..d28bd024 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 00000000..23a4cd9d --- /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' }); + }); +}); From 4e3088a121367c67620eceb6923dbd499600d310 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 16 Jul 2025 16:33:19 +0000 Subject: [PATCH 122/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 13708fa5..64f3cdd6 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.7.1" + ".": "0.8.0" } diff --git a/package.json b/package.json index 9abb8482..c82d243c 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/version.ts b/src/version.ts index 5e85c4bc..23f967c3 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 From 4e16cc616533165628bac42aff4515f2b8b4c49b Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 17 Jul 2025 03:01:35 +0000 Subject: [PATCH 123/551] chore(ts): reorder package.json imports --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index c82d243c..387ddd00 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,6 @@ "@swc/jest": "^0.2.29", "@types/jest": "^29.4.0", "@types/node": "^20.17.6", - "typescript-eslint": "8.31.1", "@typescript-eslint/eslint-plugin": "8.31.1", "@typescript-eslint/parser": "8.31.1", "eslint": "^9.20.1", @@ -44,7 +43,8 @@ "ts-node": "^10.5.0", "tsc-multi": "https://github.com/stainless-api/tsc-multi/releases/download/v1.1.8/tsc-multi.tgz", "tsconfig-paths": "^4.0.0", - "typescript": "5.8.3" + "typescript": "5.8.3", + "typescript-eslint": "8.31.1" }, "imports": { "@onkernel/sdk": ".", From ae8ebfab57ed251a1011b95a0ffdfdfaf94ac35a Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 21 Jul 2025 15:51:43 +0000 Subject: [PATCH 124/551] chore(api): remove deprecated endpoints --- .stats.yml | 8 +- README.md | 41 ++--- api.md | 16 +- src/client.ts | 2 +- src/resources/apps.ts | 74 +++++++- src/resources/apps/apps.ts | 98 ----------- src/resources/apps/deployments.ts | 175 ------------------- src/resources/apps/index.ts | 9 - src/resources/index.ts | 2 +- tests/api-resources/{apps => }/apps.test.ts | 0 tests/api-resources/apps/deployments.test.ts | 49 ------ 11 files changed, 95 insertions(+), 379 deletions(-) delete mode 100644 src/resources/apps/apps.ts delete mode 100644 src/resources/apps/deployments.ts delete mode 100644 src/resources/apps/index.ts rename tests/api-resources/{apps => }/apps.test.ts (100%) delete mode 100644 tests/api-resources/apps/deployments.test.ts diff --git a/.stats.yml b/.stats.yml index a0553b1e..38d124b5 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -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 +configured_endpoints: 19 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-84945582139b11633f792c1052a33e6af9cafc96bbafc2902a905312d14c4cc1.yml +openapi_spec_hash: c77be216626b789a543529a6de56faed +config_hash: 65328ff206b8c0168c915914506d9dba diff --git a/README.md b/README.md index 77ae2733..98f3d75b 100644 --- a/README.md +++ b/README.md @@ -27,14 +27,9 @@ const client = new Kernel({ environment: 'development', // defaults to 'production' }); -const deployment = await client.apps.deployments.create({ - entrypoint_rel_path: 'main.ts', - file: fs.createReadStream('path/to/file'), - env_vars: { OPENAI_API_KEY: 'x' }, - version: '1.0.0', -}); +const browser = await client.browsers.create({ persistence: { id: 'browser-for-user-1234' } }); -console.log(deployment.apps); +console.log(browser.session_id); ``` ### Request & Response types @@ -50,10 +45,7 @@ const client = new Kernel({ environment: 'development', // defaults to 'production' }); -const params: Kernel.BrowserCreateParams = { - invocation_id: 'REPLACE_ME', - persistence: { id: 'browser-for-user-1234' }, -}; +const params: Kernel.BrowserCreateParams = { persistence: { id: 'browser-for-user-1234' } }; const browser: Kernel.BrowserCreateResponse = await client.browsers.create(params); ``` @@ -75,29 +67,26 @@ import Kernel, { toFile } from '@onkernel/sdk'; const client = new Kernel(); // If you have access to Node `fs` we recommend using `fs.createReadStream()`: -await client.apps.deployments.create({ +await client.deployments.create({ entrypoint_rel_path: 'src/app.py', file: fs.createReadStream('/path/to/file'), }); // Or if you have the web `File` API you can pass a `File` instance: -await client.apps.deployments.create({ - entrypoint_rel_path: 'src/app.py', - file: new File(['my bytes'], 'file'), -}); +await client.deployments.create({ entrypoint_rel_path: 'src/app.py', file: new File(['my bytes'], 'file') }); // You can also pass a `fetch` `Response`: -await client.apps.deployments.create({ +await client.deployments.create({ entrypoint_rel_path: 'src/app.py', file: await fetch('https://somesite/file'), }); // Finally, if none of the above are convenient, you can use our `toFile` helper: -await client.apps.deployments.create({ +await client.deployments.create({ entrypoint_rel_path: 'src/app.py', file: await toFile(Buffer.from('my bytes'), 'file'), }); -await client.apps.deployments.create({ +await client.deployments.create({ entrypoint_rel_path: 'src/app.py', file: await toFile(new Uint8Array([0, 1, 2]), 'file'), }); @@ -112,7 +101,7 @@ a subclass of `APIError` will be thrown: ```ts const browser = await client.browsers - .create({ invocation_id: 'REPLACE_ME', persistence: { id: 'browser-for-user-1234' } }) + .create({ persistence: { id: 'browser-for-user-1234' } }) .catch(async (err) => { if (err instanceof Kernel.APIError) { console.log(err.status); // 400 @@ -153,7 +142,7 @@ const client = new Kernel({ }); // Or, configure per-request: -await client.browsers.create({ invocation_id: 'REPLACE_ME', persistence: { id: 'browser-for-user-1234' } }, { +await client.browsers.create({ persistence: { id: 'browser-for-user-1234' } }, { maxRetries: 5, }); ``` @@ -170,7 +159,7 @@ const client = new Kernel({ }); // Override per-request: -await client.browsers.create({ invocation_id: 'REPLACE_ME', persistence: { id: 'browser-for-user-1234' } }, { +await client.browsers.create({ persistence: { id: 'browser-for-user-1234' } }, { timeout: 5 * 1000, }); ``` @@ -193,14 +182,12 @@ Unlike `.asResponse()` this method consumes the body, returning once it is parse ```ts const client = new Kernel(); -const response = await client.browsers - .create({ invocation_id: 'REPLACE_ME', persistence: { id: 'browser-for-user-1234' } }) - .asResponse(); +const response = await client.browsers.create({ persistence: { id: 'browser-for-user-1234' } }).asResponse(); console.log(response.headers.get('X-My-Header')); console.log(response.statusText); // access the underlying Response object const { data: browser, response: raw } = await client.browsers - .create({ invocation_id: 'REPLACE_ME', persistence: { id: 'browser-for-user-1234' } }) + .create({ persistence: { id: 'browser-for-user-1234' } }) .withResponse(); console.log(raw.headers.get('X-My-Header')); console.log(browser.session_id); @@ -283,7 +270,7 @@ parameter. This library doesn't validate at runtime that the request matches the send will be sent as-is. ```ts -client.apps.deployments.create({ +client.browsers.create({ // ... // @ts-expect-error baz is not yet public baz: 'undocumented option', diff --git a/api.md b/api.md index 6d4c5ed4..5f2b98c1 100644 --- a/api.md +++ b/api.md @@ -30,23 +30,11 @@ Methods: Types: -- AppListResponse +- AppListResponse Methods: -- client.apps.list({ ...params }) -> AppListResponse - -## Deployments - -Types: - -- DeploymentCreateResponse -- DeploymentFollowResponse - -Methods: - -- client.apps.deployments.create({ ...params }) -> DeploymentCreateResponse -- client.apps.deployments.follow(id) -> DeploymentFollowResponse +- client.apps.list({ ...params }) -> AppListResponse # Invocations diff --git a/src/client.ts b/src/client.ts index bf57ef0d..789a1a35 100644 --- a/src/client.ts +++ b/src/client.ts @@ -16,6 +16,7 @@ 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 { AppListParams, AppListResponse, Apps } from './resources/apps'; import { DeploymentCreateParams, DeploymentCreateResponse, @@ -37,7 +38,6 @@ import { InvocationUpdateResponse, Invocations, } from './resources/invocations'; -import { AppListParams, AppListResponse, Apps } from './resources/apps/apps'; import { BrowserCreateParams, BrowserCreateResponse, diff --git a/src/resources/apps.ts b/src/resources/apps.ts index c368b826..b1b71452 100644 --- a/src/resources/apps.ts +++ b/src/resources/apps.ts @@ -1,3 +1,75 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -export * from './apps/index'; +import { APIResource } from '../core/resource'; +import * as Shared from './shared'; +import { APIPromise } from '../core/api-promise'; +import { RequestOptions } from '../internal/request-options'; + +export class Apps extends APIResource { + /** + * List applications. Optionally filter by app name and/or version label. + */ + list(query: AppListParams | null | undefined = {}, options?: RequestOptions): APIPromise { + return this._client.get('/apps', { query, ...options }); + } +} + +export type AppListResponse = Array; + +export namespace AppListResponse { + /** + * Summary of an application version. + */ + export interface AppListResponseItem { + /** + * Unique identifier for the app version + */ + id: string; + + /** + * List of actions available on the app + */ + actions: Array; + + /** + * Name of the application + */ + app_name: string; + + /** + * Deployment ID + */ + deployment: string; + + /** + * Environment variables configured for this app version + */ + env_vars: { [key: string]: string }; + + /** + * Deployment region code + */ + region: 'aws.us-east-1a'; + + /** + * Version label for the application + */ + version: string; + } +} + +export interface AppListParams { + /** + * Filter results by application name. + */ + app_name?: string; + + /** + * Filter results by version label. + */ + version?: string; +} + +export declare namespace Apps { + export { type AppListResponse as AppListResponse, type AppListParams as AppListParams }; +} diff --git a/src/resources/apps/apps.ts b/src/resources/apps/apps.ts deleted file mode 100644 index 895af238..00000000 --- a/src/resources/apps/apps.ts +++ /dev/null @@ -1,98 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { APIResource } from '../../core/resource'; -import * as Shared from '../shared'; -import * as DeploymentsAPI from './deployments'; -import { - DeploymentCreateParams, - DeploymentCreateResponse, - DeploymentFollowResponse, - Deployments, -} from './deployments'; -import { APIPromise } from '../../core/api-promise'; -import { RequestOptions } from '../../internal/request-options'; - -export class Apps extends APIResource { - deployments: DeploymentsAPI.Deployments = new DeploymentsAPI.Deployments(this._client); - - /** - * List applications. Optionally filter by app name and/or version label. - * - * @example - * ```ts - * const apps = await client.apps.list(); - * ``` - */ - list(query: AppListParams | null | undefined = {}, options?: RequestOptions): APIPromise { - return this._client.get('/apps', { query, ...options }); - } -} - -export type AppListResponse = Array; - -export namespace AppListResponse { - /** - * Summary of an application version. - */ - export interface AppListResponseItem { - /** - * Unique identifier for the app version - */ - id: string; - - /** - * List of actions available on the app - */ - actions: Array; - - /** - * Name of the application - */ - app_name: string; - - /** - * Deployment ID - */ - deployment: string; - - /** - * Environment variables configured for this app version - */ - env_vars: { [key: string]: string }; - - /** - * Deployment region code - */ - region: 'aws.us-east-1a'; - - /** - * Version label for the application - */ - version: string; - } -} - -export interface AppListParams { - /** - * Filter results by application name. - */ - app_name?: string; - - /** - * Filter results by version label. - */ - version?: string; -} - -Apps.Deployments = Deployments; - -export declare namespace Apps { - export { type AppListResponse as AppListResponse, type AppListParams as AppListParams }; - - export { - Deployments as Deployments, - type DeploymentCreateResponse as DeploymentCreateResponse, - type DeploymentFollowResponse as DeploymentFollowResponse, - type DeploymentCreateParams as DeploymentCreateParams, - }; -} diff --git a/src/resources/apps/deployments.ts b/src/resources/apps/deployments.ts deleted file mode 100644 index 109fa692..00000000 --- a/src/resources/apps/deployments.ts +++ /dev/null @@ -1,175 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { APIResource } from '../../core/resource'; -import * as Shared from '../shared'; -import { APIPromise } from '../../core/api-promise'; -import { Stream } from '../../core/streaming'; -import { type Uploadable } from '../../core/uploads'; -import { buildHeaders } from '../../internal/headers'; -import { RequestOptions } from '../../internal/request-options'; -import { multipartFormRequestOptions } from '../../internal/uploads'; -import { path } from '../../internal/utils/path'; - -export class Deployments extends APIResource { - /** - * Deploy a new application and associated actions to Kernel. - * - * @example - * ```ts - * const deployment = await client.apps.deployments.create({ - * entrypoint_rel_path: 'src/app.py', - * file: fs.createReadStream('path/to/file'), - * }); - * ``` - */ - create(body: DeploymentCreateParams, options?: RequestOptions): APIPromise { - return this._client.post('/deploy', multipartFormRequestOptions({ body, ...options }, this._client)); - } - - /** - * Establishes a Server-Sent Events (SSE) stream that delivers real-time logs and - * status updates for a deployed application. The stream terminates automatically - * once the application reaches a terminal state. - * - * @example - * ```ts - * const response = await client.apps.deployments.follow('id'); - * ``` - */ - follow(id: string, options?: RequestOptions): APIPromise> { - return this._client.get(path`/apps/${id}/events`, { - ...options, - headers: buildHeaders([{ Accept: 'text/event-stream' }, options?.headers]), - stream: true, - }) as APIPromise>; - } -} - -export interface DeploymentCreateResponse { - /** - * List of apps deployed - */ - apps: Array; - - /** - * Current status of the deployment - */ - status: 'queued' | 'deploying' | 'succeeded' | 'failed'; - - /** - * Status reason - */ - status_reason?: string; -} - -export namespace DeploymentCreateResponse { - export interface App { - /** - * ID for the app version deployed - */ - id: string; - - /** - * List of actions available on the app - */ - actions: Array; - - /** - * Name of the app - */ - name: string; - } -} - -/** - * Union type representing any application event. Actual schema is determined by - * the 'event' field. - */ -export type DeploymentFollowResponse = - | DeploymentFollowResponse.StateEvent - | DeploymentFollowResponse.StateUpdateEvent - | Shared.LogEvent - | Shared.HeartbeatEvent; - -export namespace DeploymentFollowResponse { - /** - * Initial state of the application, emitted once when subscribing. - */ - export interface StateEvent { - /** - * Event type identifier (always "state"). - */ - event: 'state'; - - /** - * Current application state (e.g., "deploying", "running", "succeeded", "failed"). - */ - state: string; - - /** - * Time the state was reported. - */ - timestamp?: string; - } - - /** - * An update emitted when the application's state changes. - */ - export interface StateUpdateEvent { - /** - * Event type identifier (always "state_update"). - */ - event: 'state_update'; - - /** - * New application state (e.g., "running", "succeeded", "failed"). - */ - state: string; - - /** - * Time the state change occurred. - */ - timestamp?: string; - } -} - -export interface DeploymentCreateParams { - /** - * Relative path to the entrypoint of the application - */ - entrypoint_rel_path: string; - - /** - * ZIP file containing the application source directory - */ - file: Uploadable; - - /** - * Map of environment variables to set for the deployed application. Each key-value - * pair represents an environment variable. - */ - env_vars?: { [key: string]: string }; - - /** - * Allow overwriting an existing app version - */ - force?: boolean; - - /** - * Region for deployment. Currently we only support "aws.us-east-1a" - */ - region?: 'aws.us-east-1a'; - - /** - * Version of the application. Can be any string. - */ - version?: string; -} - -export declare namespace Deployments { - export { - type DeploymentCreateResponse as DeploymentCreateResponse, - type DeploymentFollowResponse as DeploymentFollowResponse, - type DeploymentCreateParams as DeploymentCreateParams, - }; -} diff --git a/src/resources/apps/index.ts b/src/resources/apps/index.ts deleted file mode 100644 index a32f41e6..00000000 --- a/src/resources/apps/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -export { Apps, type AppListResponse, type AppListParams } from './apps'; -export { - Deployments, - type DeploymentCreateResponse, - type DeploymentFollowResponse, - type DeploymentCreateParams, -} from './deployments'; diff --git a/src/resources/index.ts b/src/resources/index.ts index f51eb778..a368fedb 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -1,7 +1,7 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. export * from './shared'; -export { Apps, type AppListResponse, type AppListParams } from './apps/apps'; +export { Apps, type AppListResponse, type AppListParams } from './apps'; export { Browsers, type BrowserPersistence, diff --git a/tests/api-resources/apps/apps.test.ts b/tests/api-resources/apps.test.ts similarity index 100% rename from tests/api-resources/apps/apps.test.ts rename to tests/api-resources/apps.test.ts diff --git a/tests/api-resources/apps/deployments.test.ts b/tests/api-resources/apps/deployments.test.ts deleted file mode 100644 index 79781984..00000000 --- a/tests/api-resources/apps/deployments.test.ts +++ /dev/null @@ -1,49 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import Kernel, { toFile } 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 deployments', () => { - // skipped: tests are disabled for the time being - test.skip('create: only required params', async () => { - const responsePromise = client.apps.deployments.create({ - entrypoint_rel_path: 'src/app.py', - file: await toFile(Buffer.from('# my file contents'), 'README.md'), - }); - 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('create: required and optional params', async () => { - const response = await client.apps.deployments.create({ - entrypoint_rel_path: 'src/app.py', - file: await toFile(Buffer.from('# my file contents'), 'README.md'), - env_vars: { foo: 'string' }, - force: false, - region: 'aws.us-east-1a', - version: '1.0.0', - }); - }); - - // skipped: currently no good way to test endpoints with content type text/event-stream, Prism mock server will fail - test.skip('follow', async () => { - const responsePromise = client.apps.deployments.follow('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); - }); -}); From ba5290606465da21056f8140fdd693ff0d036137 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 23 Jul 2025 22:49:43 +0000 Subject: [PATCH 125/551] feat(api): add action name to the response to invoke --- .stats.yml | 4 ++-- src/resources/invocations.ts | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 38d124b5..5c1470b3 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 19 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-84945582139b11633f792c1052a33e6af9cafc96bbafc2902a905312d14c4cc1.yml -openapi_spec_hash: c77be216626b789a543529a6de56faed +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-5e4716f7fce42bbcecc7ecb699c1c467ae778d74d558f7a260d531e2af1a7f30.yml +openapi_spec_hash: f545dcef9001b00c2604e3dcc6a12f7a config_hash: 65328ff206b8c0168c915914506d9dba diff --git a/src/resources/invocations.ts b/src/resources/invocations.ts index 24afed15..89bc359c 100644 --- a/src/resources/invocations.ts +++ b/src/resources/invocations.ts @@ -165,6 +165,11 @@ export interface InvocationCreateResponse { */ id: string; + /** + * Name of the action invoked + */ + action_name: string; + /** * Status of the invocation */ From 2dbf2a0e0bc81472c16feb95bf65469ea6e21c98 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 23 Jul 2025 22:54:07 +0000 Subject: [PATCH 126/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 64f3cdd6..2e1c40ed 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.8.0" + ".": "0.8.2" } diff --git a/package.json b/package.json index 387ddd00..0c720ea2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.8.0", + "version": "0.8.2", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 23f967c3..72b24dd1 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.8.0'; // x-release-please-version +export const VERSION = '0.8.2'; // x-release-please-version From 7b7e5c82662dacf58cde833ee9057d4353481da5 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 30 Jul 2025 00:52:52 +0000 Subject: [PATCH 127/551] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 5c1470b3..fbe1e82b 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 19 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-5e4716f7fce42bbcecc7ecb699c1c467ae778d74d558f7a260d531e2af1a7f30.yml -openapi_spec_hash: f545dcef9001b00c2604e3dcc6a12f7a +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-9f2d347a4bcb03aed092ba4495aac090c3d988e9a99af091ee35c09994adad8b.yml +openapi_spec_hash: 73b92bd5503ab6c64dc26da31cca36e2 config_hash: 65328ff206b8c0168c915914506d9dba From c7e01195b3e859ec3c86347f4d5f4f63770d3fab Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 30 Jul 2025 04:24:15 +0000 Subject: [PATCH 128/551] chore(internal): remove redundant imports config --- package.json | 4 ---- 1 file changed, 4 deletions(-) diff --git a/package.json b/package.json index 0c720ea2..1c279fd6 100644 --- a/package.json +++ b/package.json @@ -46,10 +46,6 @@ "typescript": "5.8.3", "typescript-eslint": "8.31.1" }, - "imports": { - "@onkernel/sdk": ".", - "@onkernel/sdk/*": "./src/*" - }, "exports": { ".": { "import": "./dist/index.mjs", From 0d79c87dadefc0743be67acc9815108c676763e7 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 1 Aug 2025 19:16:03 +0000 Subject: [PATCH 129/551] feat(api): lower default timeout to 5s --- .stats.yml | 2 +- README.md | 4 ++-- src/client.ts | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.stats.yml b/.stats.yml index fbe1e82b..c8304edf 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 19 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-9f2d347a4bcb03aed092ba4495aac090c3d988e9a99af091ee35c09994adad8b.yml openapi_spec_hash: 73b92bd5503ab6c64dc26da31cca36e2 -config_hash: 65328ff206b8c0168c915914506d9dba +config_hash: aafe2b8c43d82d9838c8b77cdd59189f diff --git a/README.md b/README.md index 98f3d75b..77aef20b 100644 --- a/README.md +++ b/README.md @@ -149,13 +149,13 @@ await client.browsers.create({ persistence: { id: 'browser-for-user-1234' } }, { ### Timeouts -Requests time out after 1 minute by default. You can configure this with a `timeout` option: +Requests time out after 5 seconds by default. You can configure this with a `timeout` option: ```ts // Configure the default for all requests: const client = new Kernel({ - timeout: 20 * 1000, // 20 seconds (default is 1 minute) + timeout: 20 * 1000, // 20 seconds (default is 5 seconds) }); // Override per-request: diff --git a/src/client.ts b/src/client.ts index 789a1a35..56934bf8 100644 --- a/src/client.ts +++ b/src/client.ts @@ -174,7 +174,7 @@ export class Kernel { * @param {string | undefined} [opts.apiKey=process.env['KERNEL_API_KEY'] ?? undefined] * @param {Environment} [opts.environment=production] - Specifies the environment URL to use for the API. * @param {string} [opts.baseURL=process.env['KERNEL_BASE_URL'] ?? https://api.onkernel.com/] - Override the default base URL for the API. - * @param {number} [opts.timeout=1 minute] - The maximum amount of time (in milliseconds) the client will wait for a response before timing out. + * @param {number} [opts.timeout=5 seconds] - The maximum amount of time (in milliseconds) the client will wait for a response before timing out. * @param {MergedRequestInit} [opts.fetchOptions] - Additional `RequestInit` options to be passed to `fetch` calls. * @param {Fetch} [opts.fetch] - Specify a custom `fetch` function implementation. * @param {number} [opts.maxRetries=2] - The maximum number of times the client will retry a request. @@ -206,7 +206,7 @@ export class Kernel { } this.baseURL = options.baseURL || environments[options.environment || 'production']; - this.timeout = options.timeout ?? Kernel.DEFAULT_TIMEOUT /* 1 minute */; + this.timeout = options.timeout ?? Kernel.DEFAULT_TIMEOUT /* 5 seconds */; this.logger = options.logger ?? console; const defaultLogLevel = 'warn'; // Set default logLevel early so that we can log a warning in parseLogLevel. @@ -750,7 +750,7 @@ export class Kernel { } static Kernel = this; - static DEFAULT_TIMEOUT = 60000; // 1 minute + static DEFAULT_TIMEOUT = 5000; // 5 seconds static KernelError = Errors.KernelError; static APIError = Errors.APIError; From ae721200340746b8288c5e8937a36331c2c6bd57 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 1 Aug 2025 19:25:58 +0000 Subject: [PATCH 130/551] feat(api): manual updates --- .stats.yml | 2 +- README.md | 4 ++-- src/client.ts | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.stats.yml b/.stats.yml index c8304edf..fbe1e82b 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 19 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-9f2d347a4bcb03aed092ba4495aac090c3d988e9a99af091ee35c09994adad8b.yml openapi_spec_hash: 73b92bd5503ab6c64dc26da31cca36e2 -config_hash: aafe2b8c43d82d9838c8b77cdd59189f +config_hash: 65328ff206b8c0168c915914506d9dba diff --git a/README.md b/README.md index 77aef20b..98f3d75b 100644 --- a/README.md +++ b/README.md @@ -149,13 +149,13 @@ await client.browsers.create({ persistence: { id: 'browser-for-user-1234' } }, { ### Timeouts -Requests time out after 5 seconds by default. You can configure this with a `timeout` option: +Requests time out after 1 minute by default. You can configure this with a `timeout` option: ```ts // Configure the default for all requests: const client = new Kernel({ - timeout: 20 * 1000, // 20 seconds (default is 5 seconds) + timeout: 20 * 1000, // 20 seconds (default is 1 minute) }); // Override per-request: diff --git a/src/client.ts b/src/client.ts index 56934bf8..789a1a35 100644 --- a/src/client.ts +++ b/src/client.ts @@ -174,7 +174,7 @@ export class Kernel { * @param {string | undefined} [opts.apiKey=process.env['KERNEL_API_KEY'] ?? undefined] * @param {Environment} [opts.environment=production] - Specifies the environment URL to use for the API. * @param {string} [opts.baseURL=process.env['KERNEL_BASE_URL'] ?? https://api.onkernel.com/] - Override the default base URL for the API. - * @param {number} [opts.timeout=5 seconds] - The maximum amount of time (in milliseconds) the client will wait for a response before timing out. + * @param {number} [opts.timeout=1 minute] - The maximum amount of time (in milliseconds) the client will wait for a response before timing out. * @param {MergedRequestInit} [opts.fetchOptions] - Additional `RequestInit` options to be passed to `fetch` calls. * @param {Fetch} [opts.fetch] - Specify a custom `fetch` function implementation. * @param {number} [opts.maxRetries=2] - The maximum number of times the client will retry a request. @@ -206,7 +206,7 @@ export class Kernel { } this.baseURL = options.baseURL || environments[options.environment || 'production']; - this.timeout = options.timeout ?? Kernel.DEFAULT_TIMEOUT /* 5 seconds */; + this.timeout = options.timeout ?? Kernel.DEFAULT_TIMEOUT /* 1 minute */; this.logger = options.logger ?? console; const defaultLogLevel = 'warn'; // Set default logLevel early so that we can log a warning in parseLogLevel. @@ -750,7 +750,7 @@ export class Kernel { } static Kernel = this; - static DEFAULT_TIMEOUT = 5000; // 5 seconds + static DEFAULT_TIMEOUT = 60000; // 1 minute static KernelError = Errors.KernelError; static APIError = Errors.APIError; From 578ab5eba39fd4b05abd64d133f19d265c4227e2 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 1 Aug 2025 19:34:23 +0000 Subject: [PATCH 131/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 2e1c40ed..2a248c79 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.8.2" + ".": "0.8.3" } diff --git a/package.json b/package.json index 1c279fd6..9c6fda54 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.8.2", + "version": "0.8.3", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 72b24dd1..c8e73209 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.8.2'; // x-release-please-version +export const VERSION = '0.8.3'; // x-release-please-version From eeb3bbb22112473c891946564eef4d0107a50b32 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 7 Aug 2025 03:21:42 +0000 Subject: [PATCH 132/551] chore(internal): move publish config --- bin/publish-npm | 2 +- package.json | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/bin/publish-npm b/bin/publish-npm index fa2243d2..45e8aa80 100644 --- a/bin/publish-npm +++ b/bin/publish-npm @@ -58,4 +58,4 @@ else fi # Publish with the appropriate tag -yarn publish --access public --tag "$TAG" +yarn publish --tag "$TAG" diff --git a/package.json b/package.json index 9c6fda54..f55ef9e4 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,9 @@ "**/*" ], "private": false, + "publishConfig": { + "access": "public" + }, "scripts": { "test": "./scripts/test", "build": "./scripts/build", From 86ccb7b38c72e7988a6449c5c383b5b7a84e7dad Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 7 Aug 2025 21:28:00 +0000 Subject: [PATCH 133/551] feat(api): browser instance file i/o --- .stats.yml | 8 +- api.md | 32 ++ src/resources/browsers/browsers.ts | 30 ++ src/resources/browsers/fs.ts | 3 + src/resources/browsers/fs/fs.ts | 370 ++++++++++++++++++ src/resources/browsers/fs/index.ts | 23 ++ src/resources/browsers/fs/watch.ts | 135 +++++++ src/resources/browsers/index.ts | 13 + tests/api-resources/browsers/fs/fs.test.ts | 163 ++++++++ tests/api-resources/browsers/fs/watch.test.ts | 61 +++ 10 files changed, 834 insertions(+), 4 deletions(-) create mode 100644 src/resources/browsers/fs.ts create mode 100644 src/resources/browsers/fs/fs.ts create mode 100644 src/resources/browsers/fs/index.ts create mode 100644 src/resources/browsers/fs/watch.ts create mode 100644 tests/api-resources/browsers/fs/fs.test.ts create mode 100644 tests/api-resources/browsers/fs/watch.test.ts diff --git a/.stats.yml b/.stats.yml index fbe1e82b..062204b4 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 19 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-9f2d347a4bcb03aed092ba4495aac090c3d988e9a99af091ee35c09994adad8b.yml -openapi_spec_hash: 73b92bd5503ab6c64dc26da31cca36e2 -config_hash: 65328ff206b8c0168c915914506d9dba +configured_endpoints: 31 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-e907afeabfeea49dedd783112ac3fd29267bc86f3d594f89ba9a2abf2bcbc9d8.yml +openapi_spec_hash: 060ca6288c1a09b6d1bdf207a0011165 +config_hash: f67e4b33b2fb30c1405ee2fff8096320 diff --git a/api.md b/api.md index 5f2b98c1..19d1eca5 100644 --- a/api.md +++ b/api.md @@ -84,3 +84,35 @@ Methods: - client.browsers.replays.download(replayID, { ...params }) -> Response - client.browsers.replays.start(id, { ...params }) -> ReplayStartResponse - client.browsers.replays.stop(replayID, { ...params }) -> void + +## Fs + +Types: + +- FFileInfoResponse +- FListFilesResponse + +Methods: + +- client.browsers.fs.createDirectory(id, { ...params }) -> void +- client.browsers.fs.deleteDirectory(id, { ...params }) -> void +- client.browsers.fs.deleteFile(id, { ...params }) -> void +- client.browsers.fs.fileInfo(id, { ...params }) -> FFileInfoResponse +- client.browsers.fs.listFiles(id, { ...params }) -> FListFilesResponse +- client.browsers.fs.move(id, { ...params }) -> void +- client.browsers.fs.readFile(id, { ...params }) -> Response +- client.browsers.fs.setFilePermissions(id, { ...params }) -> void +- client.browsers.fs.writeFile(id, contents, { ...params }) -> void + +### Watch + +Types: + +- WatchEventsResponse +- WatchStartResponse + +Methods: + +- client.browsers.fs.watch.events(watchID, { ...params }) -> WatchEventsResponse +- client.browsers.fs.watch.start(id, { ...params }) -> WatchStartResponse +- client.browsers.fs.watch.stop(watchID, { ...params }) -> void diff --git a/src/resources/browsers/browsers.ts b/src/resources/browsers/browsers.ts index 1f8f2046..be958310 100644 --- a/src/resources/browsers/browsers.ts +++ b/src/resources/browsers/browsers.ts @@ -11,6 +11,20 @@ import { ReplayStopParams, Replays, } from './replays'; +import * as FsAPI from './fs/fs'; +import { + FCreateDirectoryParams, + FDeleteDirectoryParams, + FDeleteFileParams, + FFileInfoParams, + FFileInfoResponse, + FListFilesParams, + FListFilesResponse, + FMoveParams, + FReadFileParams, + FSetFilePermissionsParams, + Fs, +} from './fs/fs'; import { APIPromise } from '../../core/api-promise'; import { buildHeaders } from '../../internal/headers'; import { RequestOptions } from '../../internal/request-options'; @@ -18,6 +32,7 @@ import { path } from '../../internal/utils/path'; export class Browsers extends APIResource { replays: ReplaysAPI.Replays = new ReplaysAPI.Replays(this._client); + fs: FsAPI.Fs = new FsAPI.Fs(this._client); /** * Create a new browser session from within an action. @@ -212,6 +227,7 @@ export interface BrowserDeleteParams { } Browsers.Replays = Replays; +Browsers.Fs = Fs; export declare namespace Browsers { export { @@ -231,4 +247,18 @@ export declare namespace Browsers { type ReplayStartParams as ReplayStartParams, type ReplayStopParams as ReplayStopParams, }; + + export { + Fs as Fs, + type FFileInfoResponse as FFileInfoResponse, + type FListFilesResponse as FListFilesResponse, + type FCreateDirectoryParams as FCreateDirectoryParams, + type FDeleteDirectoryParams as FDeleteDirectoryParams, + type FDeleteFileParams as FDeleteFileParams, + type FFileInfoParams as FFileInfoParams, + type FListFilesParams as FListFilesParams, + type FMoveParams as FMoveParams, + type FReadFileParams as FReadFileParams, + type FSetFilePermissionsParams as FSetFilePermissionsParams, + }; } diff --git a/src/resources/browsers/fs.ts b/src/resources/browsers/fs.ts new file mode 100644 index 00000000..d210ff1f --- /dev/null +++ b/src/resources/browsers/fs.ts @@ -0,0 +1,3 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export * from './fs/index'; diff --git a/src/resources/browsers/fs/fs.ts b/src/resources/browsers/fs/fs.ts new file mode 100644 index 00000000..2a61cf5b --- /dev/null +++ b/src/resources/browsers/fs/fs.ts @@ -0,0 +1,370 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../../core/resource'; +import * as WatchAPI from './watch'; +import { + Watch, + WatchEventsParams, + WatchEventsResponse, + WatchStartParams, + WatchStartResponse, + WatchStopParams, +} from './watch'; +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 Fs extends APIResource { + watch: WatchAPI.Watch = new WatchAPI.Watch(this._client); + + /** + * Create a new directory + * + * @example + * ```ts + * await client.browsers.fs.createDirectory('id', { + * path: '/J!', + * }); + * ``` + */ + createDirectory(id: string, body: FCreateDirectoryParams, options?: RequestOptions): APIPromise { + return this._client.put(path`/browsers/${id}/fs/create_directory`, { + body, + ...options, + headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), + }); + } + + /** + * Delete a directory + * + * @example + * ```ts + * await client.browsers.fs.deleteDirectory('id', { + * path: '/J!', + * }); + * ``` + */ + deleteDirectory(id: string, body: FDeleteDirectoryParams, options?: RequestOptions): APIPromise { + return this._client.put(path`/browsers/${id}/fs/delete_directory`, { + body, + ...options, + headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), + }); + } + + /** + * Delete a file + * + * @example + * ```ts + * await client.browsers.fs.deleteFile('id', { path: '/J!' }); + * ``` + */ + deleteFile(id: string, body: FDeleteFileParams, options?: RequestOptions): APIPromise { + return this._client.put(path`/browsers/${id}/fs/delete_file`, { + body, + ...options, + headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), + }); + } + + /** + * Get information about a file or directory + * + * @example + * ```ts + * const response = await client.browsers.fs.fileInfo('id', { + * path: '/J!', + * }); + * ``` + */ + fileInfo(id: string, query: FFileInfoParams, options?: RequestOptions): APIPromise { + return this._client.get(path`/browsers/${id}/fs/file_info`, { query, ...options }); + } + + /** + * List files in a directory + * + * @example + * ```ts + * const response = await client.browsers.fs.listFiles('id', { + * path: '/J!', + * }); + * ``` + */ + listFiles(id: string, query: FListFilesParams, options?: RequestOptions): APIPromise { + return this._client.get(path`/browsers/${id}/fs/list_files`, { query, ...options }); + } + + /** + * Move or rename a file or directory + * + * @example + * ```ts + * await client.browsers.fs.move('id', { + * dest_path: '/J!', + * src_path: '/J!', + * }); + * ``` + */ + move(id: string, body: FMoveParams, options?: RequestOptions): APIPromise { + return this._client.put(path`/browsers/${id}/fs/move`, { + body, + ...options, + headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), + }); + } + + /** + * Read file contents + * + * @example + * ```ts + * const response = await client.browsers.fs.readFile('id', { + * path: '/J!', + * }); + * + * const content = await response.blob(); + * console.log(content); + * ``` + */ + readFile(id: string, query: FReadFileParams, options?: RequestOptions): APIPromise { + return this._client.get(path`/browsers/${id}/fs/read_file`, { + query, + ...options, + headers: buildHeaders([{ Accept: 'application/octet-stream' }, options?.headers]), + __binaryResponse: true, + }); + } + + /** + * Set file or directory permissions/ownership + * + * @example + * ```ts + * await client.browsers.fs.setFilePermissions('id', { + * mode: '0611', + * path: '/J!', + * }); + * ``` + */ + setFilePermissions( + id: string, + body: FSetFilePermissionsParams, + options?: RequestOptions, + ): APIPromise { + return this._client.put(path`/browsers/${id}/fs/set_file_permissions`, { + body, + ...options, + headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), + }); + } + + /** + * Write or create a file + * + * @example + * ```ts + * await client.browsers.fs.writeFile( + * 'id', + * fs.createReadStream('path/to/file'), + * { path: '/J!' }, + * ); + * ``` + */ + writeFile( + id: string, + contents: string | ArrayBuffer | ArrayBufferView | Blob | DataView, + options?: RequestOptions, + ): APIPromise { + const { path, mode } = params; + return this._client.put(path`/browsers/${id}/fs/write_file`, { + body: contents, + ...options, + headers: buildHeaders([ + { 'Content-Type': 'application/octet-stream', Accept: '*/*' }, + options?.headers, + ]), + }); + } +} + +export interface FFileInfoResponse { + /** + * Whether the path is a directory. + */ + is_dir: boolean; + + /** + * Last modification time. + */ + mod_time: string; + + /** + * File mode bits (e.g., "drwxr-xr-x" or "-rw-r--r--"). + */ + mode: string; + + /** + * Base name of the file or directory. + */ + name: string; + + /** + * Absolute path. + */ + path: string; + + /** + * Size in bytes. 0 for directories. + */ + size_bytes: number; +} + +/** + * Array of file or directory information entries. + */ +export type FListFilesResponse = Array; + +export namespace FListFilesResponse { + export interface FListFilesResponseItem { + /** + * Whether the path is a directory. + */ + is_dir: boolean; + + /** + * Last modification time. + */ + mod_time: string; + + /** + * File mode bits (e.g., "drwxr-xr-x" or "-rw-r--r--"). + */ + mode: string; + + /** + * Base name of the file or directory. + */ + name: string; + + /** + * Absolute path. + */ + path: string; + + /** + * Size in bytes. 0 for directories. + */ + size_bytes: number; + } +} + +export interface FCreateDirectoryParams { + /** + * Absolute directory path to create. + */ + path: string; + + /** + * Optional directory mode (octal string, e.g. 755). Defaults to 755. + */ + mode?: string; +} + +export interface FDeleteDirectoryParams { + /** + * Absolute path to delete. + */ + path: string; +} + +export interface FDeleteFileParams { + /** + * Absolute path to delete. + */ + path: string; +} + +export interface FFileInfoParams { + /** + * Absolute path of the file or directory. + */ + path: string; +} + +export interface FListFilesParams { + /** + * Absolute directory path. + */ + path: string; +} + +export interface FMoveParams { + /** + * Absolute destination path. + */ + dest_path: string; + + /** + * Absolute source path. + */ + src_path: string; +} + +export interface FReadFileParams { + /** + * Absolute file path to read. + */ + path: string; +} + +export interface FSetFilePermissionsParams { + /** + * File mode bits (octal string, e.g. 644). + */ + mode: string; + + /** + * Absolute path whose permissions are to be changed. + */ + path: string; + + /** + * New group name or GID. + */ + group?: string; + + /** + * New owner username or UID. + */ + owner?: string; +} + +Fs.Watch = Watch; + +export declare namespace Fs { + export { + type FFileInfoResponse as FFileInfoResponse, + type FListFilesResponse as FListFilesResponse, + type FCreateDirectoryParams as FCreateDirectoryParams, + type FDeleteDirectoryParams as FDeleteDirectoryParams, + type FDeleteFileParams as FDeleteFileParams, + type FFileInfoParams as FFileInfoParams, + type FListFilesParams as FListFilesParams, + type FMoveParams as FMoveParams, + type FReadFileParams as FReadFileParams, + type FSetFilePermissionsParams as FSetFilePermissionsParams, + }; + + export { + Watch as Watch, + type WatchEventsResponse as WatchEventsResponse, + type WatchStartResponse as WatchStartResponse, + type WatchEventsParams as WatchEventsParams, + type WatchStartParams as WatchStartParams, + type WatchStopParams as WatchStopParams, + }; +} diff --git a/src/resources/browsers/fs/index.ts b/src/resources/browsers/fs/index.ts new file mode 100644 index 00000000..bc145c27 --- /dev/null +++ b/src/resources/browsers/fs/index.ts @@ -0,0 +1,23 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export { + Fs, + type FFileInfoResponse, + type FListFilesResponse, + type FCreateDirectoryParams, + type FDeleteDirectoryParams, + type FDeleteFileParams, + type FFileInfoParams, + type FListFilesParams, + type FMoveParams, + type FReadFileParams, + type FSetFilePermissionsParams, +} from './fs'; +export { + Watch, + type WatchEventsResponse, + type WatchStartResponse, + type WatchEventsParams, + type WatchStartParams, + type WatchStopParams, +} from './watch'; diff --git a/src/resources/browsers/fs/watch.ts b/src/resources/browsers/fs/watch.ts new file mode 100644 index 00000000..b0cc18c6 --- /dev/null +++ b/src/resources/browsers/fs/watch.ts @@ -0,0 +1,135 @@ +// 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 { Stream } from '../../../core/streaming'; +import { buildHeaders } from '../../../internal/headers'; +import { RequestOptions } from '../../../internal/request-options'; +import { path } from '../../../internal/utils/path'; + +export class Watch extends APIResource { + /** + * Stream filesystem events for a watch + * + * @example + * ```ts + * const response = await client.browsers.fs.watch.events( + * 'watch_id', + * { id: 'id' }, + * ); + * ``` + */ + events( + watchID: string, + params: WatchEventsParams, + options?: RequestOptions, + ): APIPromise> { + const { id } = params; + return this._client.get(path`/browsers/${id}/fs/watch/${watchID}/events`, { + ...options, + headers: buildHeaders([{ Accept: 'text/event-stream' }, options?.headers]), + stream: true, + }) as APIPromise>; + } + + /** + * Watch a directory for changes + * + * @example + * ```ts + * const response = await client.browsers.fs.watch.start( + * 'id', + * { path: 'path' }, + * ); + * ``` + */ + start(id: string, body: WatchStartParams, options?: RequestOptions): APIPromise { + return this._client.post(path`/browsers/${id}/fs/watch`, { body, ...options }); + } + + /** + * Stop watching a directory + * + * @example + * ```ts + * await client.browsers.fs.watch.stop('watch_id', { + * id: 'id', + * }); + * ``` + */ + stop(watchID: string, params: WatchStopParams, options?: RequestOptions): APIPromise { + const { id } = params; + return this._client.delete(path`/browsers/${id}/fs/watch/${watchID}`, { + ...options, + headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), + }); + } +} + +/** + * Filesystem change event. + */ +export interface WatchEventsResponse { + /** + * Absolute path of the file or directory. + */ + path: string; + + /** + * Event type. + */ + type: 'CREATE' | 'WRITE' | 'DELETE' | 'RENAME'; + + /** + * Whether the affected path is a directory. + */ + is_dir?: boolean; + + /** + * Base name of the file or directory affected. + */ + name?: string; +} + +export interface WatchStartResponse { + /** + * Unique identifier for the directory watch + */ + watch_id?: string; +} + +export interface WatchEventsParams { + /** + * Browser session ID + */ + id: string; +} + +export interface WatchStartParams { + /** + * Directory to watch. + */ + path: string; + + /** + * Whether to watch recursively. + */ + recursive?: boolean; +} + +export interface WatchStopParams { + /** + * Browser session ID + */ + id: string; +} + +export declare namespace Watch { + export { + type WatchEventsResponse as WatchEventsResponse, + type WatchStartResponse as WatchStartResponse, + type WatchEventsParams as WatchEventsParams, + type WatchStartParams as WatchStartParams, + type WatchStopParams as WatchStopParams, + }; +} diff --git a/src/resources/browsers/index.ts b/src/resources/browsers/index.ts index deb5900e..4c5fe2c3 100644 --- a/src/resources/browsers/index.ts +++ b/src/resources/browsers/index.ts @@ -9,6 +9,19 @@ export { type BrowserCreateParams, type BrowserDeleteParams, } from './browsers'; +export { + Fs, + type FFileInfoResponse, + type FListFilesResponse, + type FCreateDirectoryParams, + type FDeleteDirectoryParams, + type FDeleteFileParams, + type FFileInfoParams, + type FListFilesParams, + type FMoveParams, + type FReadFileParams, + type FSetFilePermissionsParams, +} from './fs/index'; export { Replays, type ReplayListResponse, diff --git a/tests/api-resources/browsers/fs/fs.test.ts b/tests/api-resources/browsers/fs/fs.test.ts new file mode 100644 index 00000000..7bc502b9 --- /dev/null +++ b/tests/api-resources/browsers/fs/fs.test.ts @@ -0,0 +1,163 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import Kernel, { toFile } 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 fs', () => { + // skipped: tests are disabled for the time being + test.skip('createDirectory: only required params', async () => { + const responsePromise = client.browsers.fs.createDirectory('id', { path: '/J!' }); + 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('createDirectory: required and optional params', async () => { + const response = await client.browsers.fs.createDirectory('id', { path: '/J!', mode: '0611' }); + }); + + // skipped: tests are disabled for the time being + test.skip('deleteDirectory: only required params', async () => { + const responsePromise = client.browsers.fs.deleteDirectory('id', { path: '/J!' }); + 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('deleteDirectory: required and optional params', async () => { + const response = await client.browsers.fs.deleteDirectory('id', { path: '/J!' }); + }); + + // skipped: tests are disabled for the time being + test.skip('deleteFile: only required params', async () => { + const responsePromise = client.browsers.fs.deleteFile('id', { path: '/J!' }); + 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('deleteFile: required and optional params', async () => { + const response = await client.browsers.fs.deleteFile('id', { path: '/J!' }); + }); + + // skipped: tests are disabled for the time being + test.skip('fileInfo: only required params', async () => { + const responsePromise = client.browsers.fs.fileInfo('id', { path: '/J!' }); + 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('fileInfo: required and optional params', async () => { + const response = await client.browsers.fs.fileInfo('id', { path: '/J!' }); + }); + + // skipped: tests are disabled for the time being + test.skip('listFiles: only required params', async () => { + const responsePromise = client.browsers.fs.listFiles('id', { path: '/J!' }); + 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('listFiles: required and optional params', async () => { + const response = await client.browsers.fs.listFiles('id', { path: '/J!' }); + }); + + // skipped: tests are disabled for the time being + test.skip('move: only required params', async () => { + const responsePromise = client.browsers.fs.move('id', { dest_path: '/J!', src_path: '/J!' }); + 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('move: required and optional params', async () => { + const response = await client.browsers.fs.move('id', { dest_path: '/J!', src_path: '/J!' }); + }); + + // skipped: tests are disabled for the time being + test.skip('readFile: required and optional params', async () => { + const response = await client.browsers.fs.readFile('id', { path: '/J!' }); + }); + + // skipped: tests are disabled for the time being + test.skip('setFilePermissions: only required params', async () => { + const responsePromise = client.browsers.fs.setFilePermissions('id', { mode: '0611', path: '/J!' }); + 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('setFilePermissions: required and optional params', async () => { + const response = await client.browsers.fs.setFilePermissions('id', { + mode: '0611', + path: '/J!', + group: 'group', + owner: 'owner', + }); + }); + + // skipped: tests are disabled for the time being + test.skip('writeFile: only required params', async () => { + const responsePromise = client.browsers.fs.writeFile( + 'id', + await toFile(Buffer.from('# my file contents'), 'README.md'), + ); + 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('writeFile: required and optional params', async () => { + const response = await client.browsers.fs.writeFile( + 'id', + await toFile(Buffer.from('# my file contents'), 'README.md'), + { path: '/J!', mode: '0611' }, + ); + }); +}); diff --git a/tests/api-resources/browsers/fs/watch.test.ts b/tests/api-resources/browsers/fs/watch.test.ts new file mode 100644 index 00000000..c85702d3 --- /dev/null +++ b/tests/api-resources/browsers/fs/watch.test.ts @@ -0,0 +1,61 @@ +// 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 watch', () => { + // skipped: currently no good way to test endpoints with content type text/event-stream, Prism mock server will fail + test.skip('events: only required params', async () => { + const responsePromise = client.browsers.fs.watch.events('watch_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: currently no good way to test endpoints with content type text/event-stream, Prism mock server will fail + test.skip('events: required and optional params', async () => { + const response = await client.browsers.fs.watch.events('watch_id', { id: 'id' }); + }); + + // skipped: tests are disabled for the time being + test.skip('start: only required params', async () => { + const responsePromise = client.browsers.fs.watch.start('id', { path: 'path' }); + 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: required and optional params', async () => { + const response = await client.browsers.fs.watch.start('id', { path: 'path', recursive: true }); + }); + + // skipped: tests are disabled for the time being + test.skip('stop: only required params', async () => { + const responsePromise = client.browsers.fs.watch.stop('watch_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.fs.watch.stop('watch_id', { id: 'id' }); + }); +}); From cdd73c32fa6b4864c17dcc34648e68a160a534f2 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 8 Aug 2025 03:08:16 +0000 Subject: [PATCH 134/551] fix(methods): define methods with parameters and binary body correctly --- src/resources/browsers/browsers.ts | 2 ++ src/resources/browsers/fs/fs.ts | 17 ++++++++++++++++- src/resources/browsers/fs/index.ts | 1 + src/resources/browsers/index.ts | 1 + tests/api-resources/browsers/fs/fs.test.ts | 1 + 5 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/resources/browsers/browsers.ts b/src/resources/browsers/browsers.ts index be958310..438a892f 100644 --- a/src/resources/browsers/browsers.ts +++ b/src/resources/browsers/browsers.ts @@ -23,6 +23,7 @@ import { FMoveParams, FReadFileParams, FSetFilePermissionsParams, + FWriteFileParams, Fs, } from './fs/fs'; import { APIPromise } from '../../core/api-promise'; @@ -260,5 +261,6 @@ export declare namespace Browsers { type FMoveParams as FMoveParams, type FReadFileParams as FReadFileParams, type FSetFilePermissionsParams as FSetFilePermissionsParams, + type FWriteFileParams as FWriteFileParams, }; } diff --git a/src/resources/browsers/fs/fs.ts b/src/resources/browsers/fs/fs.ts index 2a61cf5b..caaa1486 100644 --- a/src/resources/browsers/fs/fs.ts +++ b/src/resources/browsers/fs/fs.ts @@ -177,11 +177,13 @@ export class Fs extends APIResource { writeFile( id: string, contents: string | ArrayBuffer | ArrayBufferView | Blob | DataView, + params: FWriteFileParams, options?: RequestOptions, ): APIPromise { - const { path, mode } = params; + const { path: path_, mode } = params; return this._client.put(path`/browsers/${id}/fs/write_file`, { body: contents, + query: { path: path_, mode }, ...options, headers: buildHeaders([ { 'Content-Type': 'application/octet-stream', Accept: '*/*' }, @@ -343,6 +345,18 @@ export interface FSetFilePermissionsParams { owner?: string; } +export interface FWriteFileParams { + /** + * Query param: Destination absolute file path. + */ + path: string; + + /** + * Query param: Optional file mode (octal string, e.g. 644). Defaults to 644. + */ + mode?: string; +} + Fs.Watch = Watch; export declare namespace Fs { @@ -357,6 +371,7 @@ export declare namespace Fs { type FMoveParams as FMoveParams, type FReadFileParams as FReadFileParams, type FSetFilePermissionsParams as FSetFilePermissionsParams, + type FWriteFileParams as FWriteFileParams, }; export { diff --git a/src/resources/browsers/fs/index.ts b/src/resources/browsers/fs/index.ts index bc145c27..14c3cb81 100644 --- a/src/resources/browsers/fs/index.ts +++ b/src/resources/browsers/fs/index.ts @@ -12,6 +12,7 @@ export { type FMoveParams, type FReadFileParams, type FSetFilePermissionsParams, + type FWriteFileParams, } from './fs'; export { Watch, diff --git a/src/resources/browsers/index.ts b/src/resources/browsers/index.ts index 4c5fe2c3..cc79adb5 100644 --- a/src/resources/browsers/index.ts +++ b/src/resources/browsers/index.ts @@ -21,6 +21,7 @@ export { type FMoveParams, type FReadFileParams, type FSetFilePermissionsParams, + type FWriteFileParams, } from './fs/index'; export { Replays, diff --git a/tests/api-resources/browsers/fs/fs.test.ts b/tests/api-resources/browsers/fs/fs.test.ts index 7bc502b9..44a5ad8f 100644 --- a/tests/api-resources/browsers/fs/fs.test.ts +++ b/tests/api-resources/browsers/fs/fs.test.ts @@ -142,6 +142,7 @@ describe('resource fs', () => { const responsePromise = client.browsers.fs.writeFile( 'id', await toFile(Buffer.from('# my file contents'), 'README.md'), + { path: '/J!' }, ); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); From 1590fa8cc7fbc8fc6ed0dd9a0d7a40ff341bc59d Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 8 Aug 2025 13:41:06 +0000 Subject: [PATCH 135/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 2a248c79..76d5538a 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.8.3" + ".": "0.9.0" } diff --git a/package.json b/package.json index f55ef9e4..e01977ab 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.8.3", + "version": "0.9.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index c8e73209..5c161947 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.8.3'; // x-release-please-version +export const VERSION = '0.9.0'; // x-release-please-version From 5371e6ef96715ec38f873e996d6839d5765216ea Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 9 Aug 2025 03:50:37 +0000 Subject: [PATCH 136/551] chore: update @stainless-api/prism-cli to v5.15.0 --- scripts/mock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/mock b/scripts/mock index d2814ae6..0b28f6ea 100755 --- a/scripts/mock +++ b/scripts/mock @@ -21,7 +21,7 @@ echo "==> Starting mock server with URL ${URL}" # Run prism mock on the given spec if [ "$1" == "--daemon" ]; then - npm exec --package=@stainless-api/prism-cli@5.8.5 -- prism mock "$URL" &> .prism.log & + npm exec --package=@stainless-api/prism-cli@5.15.0 -- prism mock "$URL" &> .prism.log & # Wait for server to come online echo -n "Waiting for server" @@ -37,5 +37,5 @@ if [ "$1" == "--daemon" ]; then echo else - npm exec --package=@stainless-api/prism-cli@5.8.5 -- prism mock "$URL" + npm exec --package=@stainless-api/prism-cli@5.15.0 -- prism mock "$URL" fi From c9596a70382e260b1e59b3148dd010dbf0baf93d Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 9 Aug 2025 03:54:22 +0000 Subject: [PATCH 137/551] chore(internal): update comment in script --- scripts/test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/test b/scripts/test index 2049e31b..7bce0516 100755 --- a/scripts/test +++ b/scripts/test @@ -43,7 +43,7 @@ elif ! prism_is_running ; then echo -e "To run the server, pass in the path or url of your OpenAPI" echo -e "spec to the prism command:" echo - echo -e " \$ ${YELLOW}npm exec --package=@stoplight/prism-cli@~5.3.2 -- prism mock path/to/your.openapi.yml${NC}" + echo -e " \$ ${YELLOW}npm exec --package=@stainless-api/prism-cli@5.15.0 -- prism mock path/to/your.openapi.yml${NC}" echo exit 1 From b7a260034b0c87ac8f54e7856834f0cd99c8fcf7 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 11 Aug 2025 23:58:55 +0000 Subject: [PATCH 138/551] feat(api): add browser ttls --- .stats.yml | 4 +- src/resources/browsers/browsers.ts | 52 +++++++++++++++++++ tests/api-resources/browsers/browsers.test.ts | 1 + 3 files changed, 55 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 062204b4..86b4afde 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 31 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-e907afeabfeea49dedd783112ac3fd29267bc86f3d594f89ba9a2abf2bcbc9d8.yml -openapi_spec_hash: 060ca6288c1a09b6d1bdf207a0011165 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-6f4aab5f0db80d6ce30ef40274eee347cce0a9465e7f1e5077f8f4a085251ddf.yml +openapi_spec_hash: 8e83254243d1620b80a0dc8aa212ee0d config_hash: f67e4b33b2fb30c1405ee2fff8096320 diff --git a/src/resources/browsers/browsers.ts b/src/resources/browsers/browsers.ts index 438a892f..e6343950 100644 --- a/src/resources/browsers/browsers.ts +++ b/src/resources/browsers/browsers.ts @@ -129,11 +129,26 @@ export interface BrowserCreateResponse { */ cdp_ws_url: string; + /** + * Indicates whether the browser session is headless. + */ + headless: boolean; + /** * Unique identifier for the browser session */ session_id: string; + /** + * Indicates whether the browser session is stealth. + */ + stealth: boolean; + + /** + * The number of seconds of inactivity before the browser session is terminated. + */ + timeout_seconds: number; + /** * Remote URL for live viewing the browser session. Only available for non-headless * browsers. @@ -152,11 +167,26 @@ export interface BrowserRetrieveResponse { */ cdp_ws_url: string; + /** + * Indicates whether the browser session is headless. + */ + headless: boolean; + /** * Unique identifier for the browser session */ session_id: string; + /** + * Indicates whether the browser session is stealth. + */ + stealth: boolean; + + /** + * The number of seconds of inactivity before the browser session is terminated. + */ + timeout_seconds: number; + /** * Remote URL for live viewing the browser session. Only available for non-headless * browsers. @@ -178,11 +208,26 @@ export namespace BrowserListResponse { */ cdp_ws_url: string; + /** + * Indicates whether the browser session is headless. + */ + headless: boolean; + /** * Unique identifier for the browser session */ session_id: string; + /** + * Indicates whether the browser session is stealth. + */ + stealth: boolean; + + /** + * The number of seconds of inactivity before the browser session is terminated. + */ + timeout_seconds: number; + /** * Remote URL for live viewing the browser session. Only available for non-headless * browsers. @@ -218,6 +263,13 @@ export interface BrowserCreateParams { * mechanisms. */ stealth?: boolean; + + /** + * The number of seconds of inactivity before the browser session is terminated. + * Only applicable to non-persistent browsers. Activity includes CDP connections + * and live view connections. Defaults to 60 seconds. + */ + timeout_seconds?: number; } export interface BrowserDeleteParams { diff --git a/tests/api-resources/browsers/browsers.test.ts b/tests/api-resources/browsers/browsers.test.ts index d28bd024..f1269105 100644 --- a/tests/api-resources/browsers/browsers.test.ts +++ b/tests/api-resources/browsers/browsers.test.ts @@ -30,6 +30,7 @@ describe('resource browsers', () => { invocation_id: 'rr33xuugxj9h0bkf1rdt2bet', persistence: { id: 'my-awesome-browser-for-user-1234' }, stealth: true, + timeout_seconds: 0, }, { path: '/_stainless_unknown_path' }, ), From a93617d016c4f02c11b5aa68470b80fa5191582e Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 12 Aug 2025 02:13:22 +0000 Subject: [PATCH 139/551] chore(internal): codegen related update --- tests/api-resources/apps.test.ts | 4 +-- tests/api-resources/browsers/browsers.test.ts | 14 ++++---- tests/api-resources/browsers/fs/fs.test.ts | 35 +++++++++---------- tests/api-resources/browsers/fs/watch.test.ts | 12 +++---- tests/api-resources/browsers/replays.test.ts | 13 ++++--- tests/api-resources/deployments.test.ts | 14 ++++---- tests/api-resources/invocations.test.ts | 14 ++++---- 7 files changed, 52 insertions(+), 54 deletions(-) diff --git a/tests/api-resources/apps.test.ts b/tests/api-resources/apps.test.ts index 6bb4e0d8..36a0654b 100644 --- a/tests/api-resources/apps.test.ts +++ b/tests/api-resources/apps.test.ts @@ -8,7 +8,7 @@ const client = new Kernel({ }); describe('resource apps', () => { - // skipped: tests are disabled for the time being + // Prism tests are disabled test.skip('list', async () => { const responsePromise = client.apps.list(); const rawResponse = await responsePromise.asResponse(); @@ -20,7 +20,7 @@ describe('resource apps', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // skipped: tests are disabled for the time being + // Prism tests are disabled test.skip('list: 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( diff --git a/tests/api-resources/browsers/browsers.test.ts b/tests/api-resources/browsers/browsers.test.ts index f1269105..7685e689 100644 --- a/tests/api-resources/browsers/browsers.test.ts +++ b/tests/api-resources/browsers/browsers.test.ts @@ -8,7 +8,7 @@ const client = new Kernel({ }); describe('resource browsers', () => { - // skipped: tests are disabled for the time being + // Prism tests are disabled test.skip('create', async () => { const responsePromise = client.browsers.create(); const rawResponse = await responsePromise.asResponse(); @@ -20,7 +20,7 @@ describe('resource browsers', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // skipped: tests are disabled for the time being + // Prism tests are disabled test.skip('create: 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( @@ -37,7 +37,7 @@ describe('resource browsers', () => { ).rejects.toThrow(Kernel.NotFoundError); }); - // skipped: tests are disabled for the time being + // Prism tests are disabled test.skip('retrieve', async () => { const responsePromise = client.browsers.retrieve('htzv5orfit78e1m2biiifpbv'); const rawResponse = await responsePromise.asResponse(); @@ -49,7 +49,7 @@ describe('resource browsers', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // skipped: tests are disabled for the time being + // Prism tests are disabled test.skip('list', async () => { const responsePromise = client.browsers.list(); const rawResponse = await responsePromise.asResponse(); @@ -61,7 +61,7 @@ describe('resource browsers', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // skipped: tests are disabled for the time being + // Prism tests are disabled test.skip('delete: only required params', async () => { const responsePromise = client.browsers.delete({ persistent_id: 'persistent_id' }); const rawResponse = await responsePromise.asResponse(); @@ -73,12 +73,12 @@ describe('resource browsers', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // skipped: tests are disabled for the time being + // Prism tests are disabled test.skip('delete: required and optional params', async () => { const response = await client.browsers.delete({ persistent_id: 'persistent_id' }); }); - // skipped: tests are disabled for the time being + // Prism tests are disabled test.skip('deleteByID', async () => { const responsePromise = client.browsers.deleteByID('htzv5orfit78e1m2biiifpbv'); const rawResponse = await responsePromise.asResponse(); diff --git a/tests/api-resources/browsers/fs/fs.test.ts b/tests/api-resources/browsers/fs/fs.test.ts index 44a5ad8f..87fbb3d3 100644 --- a/tests/api-resources/browsers/fs/fs.test.ts +++ b/tests/api-resources/browsers/fs/fs.test.ts @@ -8,7 +8,7 @@ const client = new Kernel({ }); describe('resource fs', () => { - // skipped: tests are disabled for the time being + // Prism tests are disabled test.skip('createDirectory: only required params', async () => { const responsePromise = client.browsers.fs.createDirectory('id', { path: '/J!' }); const rawResponse = await responsePromise.asResponse(); @@ -20,12 +20,12 @@ describe('resource fs', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // skipped: tests are disabled for the time being + // Prism tests are disabled test.skip('createDirectory: required and optional params', async () => { const response = await client.browsers.fs.createDirectory('id', { path: '/J!', mode: '0611' }); }); - // skipped: tests are disabled for the time being + // Prism tests are disabled test.skip('deleteDirectory: only required params', async () => { const responsePromise = client.browsers.fs.deleteDirectory('id', { path: '/J!' }); const rawResponse = await responsePromise.asResponse(); @@ -37,12 +37,12 @@ describe('resource fs', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // skipped: tests are disabled for the time being + // Prism tests are disabled test.skip('deleteDirectory: required and optional params', async () => { const response = await client.browsers.fs.deleteDirectory('id', { path: '/J!' }); }); - // skipped: tests are disabled for the time being + // Prism tests are disabled test.skip('deleteFile: only required params', async () => { const responsePromise = client.browsers.fs.deleteFile('id', { path: '/J!' }); const rawResponse = await responsePromise.asResponse(); @@ -54,12 +54,12 @@ describe('resource fs', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // skipped: tests are disabled for the time being + // Prism tests are disabled test.skip('deleteFile: required and optional params', async () => { const response = await client.browsers.fs.deleteFile('id', { path: '/J!' }); }); - // skipped: tests are disabled for the time being + // Prism tests are disabled test.skip('fileInfo: only required params', async () => { const responsePromise = client.browsers.fs.fileInfo('id', { path: '/J!' }); const rawResponse = await responsePromise.asResponse(); @@ -71,12 +71,12 @@ describe('resource fs', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // skipped: tests are disabled for the time being + // Prism tests are disabled test.skip('fileInfo: required and optional params', async () => { const response = await client.browsers.fs.fileInfo('id', { path: '/J!' }); }); - // skipped: tests are disabled for the time being + // Prism tests are disabled test.skip('listFiles: only required params', async () => { const responsePromise = client.browsers.fs.listFiles('id', { path: '/J!' }); const rawResponse = await responsePromise.asResponse(); @@ -88,12 +88,12 @@ describe('resource fs', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // skipped: tests are disabled for the time being + // Prism tests are disabled test.skip('listFiles: required and optional params', async () => { const response = await client.browsers.fs.listFiles('id', { path: '/J!' }); }); - // skipped: tests are disabled for the time being + // Prism tests are disabled test.skip('move: only required params', async () => { const responsePromise = client.browsers.fs.move('id', { dest_path: '/J!', src_path: '/J!' }); const rawResponse = await responsePromise.asResponse(); @@ -105,17 +105,16 @@ describe('resource fs', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // skipped: tests are disabled for the time being + // Prism tests are disabled test.skip('move: required and optional params', async () => { const response = await client.browsers.fs.move('id', { dest_path: '/J!', src_path: '/J!' }); }); - // skipped: tests are disabled for the time being - test.skip('readFile: required and optional params', async () => { + test('readFile: required and optional params', async () => { const response = await client.browsers.fs.readFile('id', { path: '/J!' }); }); - // skipped: tests are disabled for the time being + // Prism tests are disabled test.skip('setFilePermissions: only required params', async () => { const responsePromise = client.browsers.fs.setFilePermissions('id', { mode: '0611', path: '/J!' }); const rawResponse = await responsePromise.asResponse(); @@ -127,7 +126,7 @@ describe('resource fs', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // skipped: tests are disabled for the time being + // Prism tests are disabled test.skip('setFilePermissions: required and optional params', async () => { const response = await client.browsers.fs.setFilePermissions('id', { mode: '0611', @@ -137,7 +136,7 @@ describe('resource fs', () => { }); }); - // skipped: tests are disabled for the time being + // Prism tests are disabled test.skip('writeFile: only required params', async () => { const responsePromise = client.browsers.fs.writeFile( 'id', @@ -153,7 +152,7 @@ describe('resource fs', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // skipped: tests are disabled for the time being + // Prism tests are disabled test.skip('writeFile: required and optional params', async () => { const response = await client.browsers.fs.writeFile( 'id', diff --git a/tests/api-resources/browsers/fs/watch.test.ts b/tests/api-resources/browsers/fs/watch.test.ts index c85702d3..47ddfb80 100644 --- a/tests/api-resources/browsers/fs/watch.test.ts +++ b/tests/api-resources/browsers/fs/watch.test.ts @@ -8,7 +8,7 @@ const client = new Kernel({ }); describe('resource watch', () => { - // skipped: currently no good way to test endpoints with content type text/event-stream, Prism mock server will fail + // Prism doesn't support text/event-stream responses test.skip('events: only required params', async () => { const responsePromise = client.browsers.fs.watch.events('watch_id', { id: 'id' }); const rawResponse = await responsePromise.asResponse(); @@ -20,12 +20,12 @@ describe('resource watch', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // skipped: currently no good way to test endpoints with content type text/event-stream, Prism mock server will fail + // Prism doesn't support text/event-stream responses test.skip('events: required and optional params', async () => { const response = await client.browsers.fs.watch.events('watch_id', { id: 'id' }); }); - // skipped: tests are disabled for the time being + // Prism tests are disabled test.skip('start: only required params', async () => { const responsePromise = client.browsers.fs.watch.start('id', { path: 'path' }); const rawResponse = await responsePromise.asResponse(); @@ -37,12 +37,12 @@ describe('resource watch', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // skipped: tests are disabled for the time being + // Prism tests are disabled test.skip('start: required and optional params', async () => { const response = await client.browsers.fs.watch.start('id', { path: 'path', recursive: true }); }); - // skipped: tests are disabled for the time being + // Prism tests are disabled test.skip('stop: only required params', async () => { const responsePromise = client.browsers.fs.watch.stop('watch_id', { id: 'id' }); const rawResponse = await responsePromise.asResponse(); @@ -54,7 +54,7 @@ describe('resource watch', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // skipped: tests are disabled for the time being + // Prism tests are disabled test.skip('stop: required and optional params', async () => { const response = await client.browsers.fs.watch.stop('watch_id', { id: 'id' }); }); diff --git a/tests/api-resources/browsers/replays.test.ts b/tests/api-resources/browsers/replays.test.ts index 23a4cd9d..d0ee498b 100644 --- a/tests/api-resources/browsers/replays.test.ts +++ b/tests/api-resources/browsers/replays.test.ts @@ -8,7 +8,7 @@ const client = new Kernel({ }); describe('resource replays', () => { - // skipped: tests are disabled for the time being + // Prism tests are disabled test.skip('list', async () => { const responsePromise = client.browsers.replays.list('id'); const rawResponse = await responsePromise.asResponse(); @@ -20,12 +20,11 @@ describe('resource replays', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // skipped: tests are disabled for the time being - test.skip('download: required and optional params', async () => { + test('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 + // Prism tests are disabled test.skip('start', async () => { const responsePromise = client.browsers.replays.start('id'); const rawResponse = await responsePromise.asResponse(); @@ -37,7 +36,7 @@ describe('resource replays', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // skipped: tests are disabled for the time being + // Prism tests are disabled 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( @@ -49,7 +48,7 @@ describe('resource replays', () => { ).rejects.toThrow(Kernel.NotFoundError); }); - // skipped: tests are disabled for the time being + // Prism tests are disabled test.skip('stop: only required params', async () => { const responsePromise = client.browsers.replays.stop('replay_id', { id: 'id' }); const rawResponse = await responsePromise.asResponse(); @@ -61,7 +60,7 @@ describe('resource replays', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // skipped: tests are disabled for the time being + // Prism tests are disabled test.skip('stop: required and optional params', async () => { const response = await client.browsers.replays.stop('replay_id', { id: 'id' }); }); diff --git a/tests/api-resources/deployments.test.ts b/tests/api-resources/deployments.test.ts index 83eb8d76..289fe0c6 100644 --- a/tests/api-resources/deployments.test.ts +++ b/tests/api-resources/deployments.test.ts @@ -8,7 +8,7 @@ const client = new Kernel({ }); describe('resource deployments', () => { - // skipped: tests are disabled for the time being + // Prism tests are disabled test.skip('create: only required params', async () => { const responsePromise = client.deployments.create({ entrypoint_rel_path: 'src/app.py', @@ -23,7 +23,7 @@ describe('resource deployments', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // skipped: tests are disabled for the time being + // Prism tests are disabled test.skip('create: required and optional params', async () => { const response = await client.deployments.create({ entrypoint_rel_path: 'src/app.py', @@ -35,7 +35,7 @@ describe('resource deployments', () => { }); }); - // skipped: tests are disabled for the time being + // Prism tests are disabled test.skip('retrieve', async () => { const responsePromise = client.deployments.retrieve('id'); const rawResponse = await responsePromise.asResponse(); @@ -47,7 +47,7 @@ describe('resource deployments', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // skipped: tests are disabled for the time being + // Prism tests are disabled test.skip('list', async () => { const responsePromise = client.deployments.list(); const rawResponse = await responsePromise.asResponse(); @@ -59,7 +59,7 @@ describe('resource deployments', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // skipped: tests are disabled for the time being + // Prism tests are disabled test.skip('list: 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( @@ -67,7 +67,7 @@ describe('resource deployments', () => { ).rejects.toThrow(Kernel.NotFoundError); }); - // skipped: currently no good way to test endpoints with content type text/event-stream, Prism mock server will fail + // Prism doesn't support text/event-stream responses test.skip('follow', async () => { const responsePromise = client.deployments.follow('id'); const rawResponse = await responsePromise.asResponse(); @@ -79,7 +79,7 @@ describe('resource deployments', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // skipped: currently no good way to test endpoints with content type text/event-stream, Prism mock server will fail + // Prism doesn't support text/event-stream responses test.skip('follow: 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( diff --git a/tests/api-resources/invocations.test.ts b/tests/api-resources/invocations.test.ts index e481c152..baa3790e 100644 --- a/tests/api-resources/invocations.test.ts +++ b/tests/api-resources/invocations.test.ts @@ -8,7 +8,7 @@ const client = new Kernel({ }); describe('resource invocations', () => { - // skipped: tests are disabled for the time being + // Prism tests are disabled test.skip('create: only required params', async () => { const responsePromise = client.invocations.create({ action_name: 'analyze', @@ -24,7 +24,7 @@ describe('resource invocations', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // skipped: tests are disabled for the time being + // Prism tests are disabled test.skip('create: required and optional params', async () => { const response = await client.invocations.create({ action_name: 'analyze', @@ -35,7 +35,7 @@ describe('resource invocations', () => { }); }); - // skipped: tests are disabled for the time being + // Prism tests are disabled test.skip('retrieve', async () => { const responsePromise = client.invocations.retrieve('rr33xuugxj9h0bkf1rdt2bet'); const rawResponse = await responsePromise.asResponse(); @@ -47,7 +47,7 @@ describe('resource invocations', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // skipped: tests are disabled for the time being + // Prism tests are disabled test.skip('update: only required params', async () => { const responsePromise = client.invocations.update('id', { status: 'succeeded' }); const rawResponse = await responsePromise.asResponse(); @@ -59,12 +59,12 @@ describe('resource invocations', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // skipped: tests are disabled for the time being + // Prism tests are disabled test.skip('update: required and optional params', async () => { const response = await client.invocations.update('id', { status: 'succeeded', output: 'output' }); }); - // skipped: tests are disabled for the time being + // Prism tests are disabled test.skip('deleteBrowsers', async () => { const responsePromise = client.invocations.deleteBrowsers('id'); const rawResponse = await responsePromise.asResponse(); @@ -76,7 +76,7 @@ describe('resource invocations', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // skipped: currently no good way to test endpoints with content type text/event-stream, Prism mock server will fail + // Prism doesn't support text/event-stream responses test.skip('follow', async () => { const responsePromise = client.invocations.follow('id'); const rawResponse = await responsePromise.asResponse(); From f49b9d12381236314879d374e27cf9b9684c07cb Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 15 Aug 2025 17:18:57 +0000 Subject: [PATCH 140/551] feat(api): add browser timeouts --- .stats.yml | 4 ++-- src/resources/browsers/browsers.ts | 27 +++++++++++++++++++++------ 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/.stats.yml b/.stats.yml index 86b4afde..f6de080e 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 31 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-6f4aab5f0db80d6ce30ef40274eee347cce0a9465e7f1e5077f8f4a085251ddf.yml -openapi_spec_hash: 8e83254243d1620b80a0dc8aa212ee0d +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-b55c3e0424fa7733487139488b9fff00ad8949ff02ee3160ee36b9334e84b134.yml +openapi_spec_hash: 17f36677e3dc0a3aeb419654c8d5cae3 config_hash: f67e4b33b2fb30c1405ee2fff8096320 diff --git a/src/resources/browsers/browsers.ts b/src/resources/browsers/browsers.ts index e6343950..3e37d792 100644 --- a/src/resources/browsers/browsers.ts +++ b/src/resources/browsers/browsers.ts @@ -130,7 +130,12 @@ export interface BrowserCreateResponse { cdp_ws_url: string; /** - * Indicates whether the browser session is headless. + * When the browser session was created. + */ + created_at: string; + + /** + * Whether the browser session is running in headless mode. */ headless: boolean; @@ -140,7 +145,7 @@ export interface BrowserCreateResponse { session_id: string; /** - * Indicates whether the browser session is stealth. + * Whether the browser session is running in stealth mode. */ stealth: boolean; @@ -168,7 +173,12 @@ export interface BrowserRetrieveResponse { cdp_ws_url: string; /** - * Indicates whether the browser session is headless. + * When the browser session was created. + */ + created_at: string; + + /** + * Whether the browser session is running in headless mode. */ headless: boolean; @@ -178,7 +188,7 @@ export interface BrowserRetrieveResponse { session_id: string; /** - * Indicates whether the browser session is stealth. + * Whether the browser session is running in stealth mode. */ stealth: boolean; @@ -209,7 +219,12 @@ export namespace BrowserListResponse { cdp_ws_url: string; /** - * Indicates whether the browser session is headless. + * When the browser session was created. + */ + created_at: string; + + /** + * Whether the browser session is running in headless mode. */ headless: boolean; @@ -219,7 +234,7 @@ export namespace BrowserListResponse { session_id: string; /** - * Indicates whether the browser session is stealth. + * Whether the browser session is running in stealth mode. */ stealth: boolean; From a183f84be20d7812e366df8b78125278434a9204 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 15 Aug 2025 17:22:07 +0000 Subject: [PATCH 141/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 76d5538a..b28fea99 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.9.0" + ".": "0.9.1" } diff --git a/package.json b/package.json index e01977ab..e3715cb0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.9.0", + "version": "0.9.1", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 5c161947..72f481f5 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.9.0'; // x-release-please-version +export const VERSION = '0.9.1'; // x-release-please-version From 017ab80641edabb1a7e158f3927d166a8e7d0eaf Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 16 Aug 2025 03:21:48 +0000 Subject: [PATCH 142/551] chore(deps): update dependency @types/node to v20.17.58 --- yarn.lock | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/yarn.lock b/yarn.lock index 58c08d5f..fd164dcf 100644 --- a/yarn.lock +++ b/yarn.lock @@ -938,11 +938,11 @@ undici-types "~5.26.4" "@types/node@^20.17.6": - version "20.17.6" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.17.6.tgz#6e4073230c180d3579e8c60141f99efdf5df0081" - integrity sha512-VEI7OdvK2wP7XHnsuXbAJnEpEkF6NjSN45QJlL4VGqZSXsnicpesdTWsg9RISeSdYd3yeRj/y3k5KGjUXYnFwQ== + version "20.19.11" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.19.11.tgz#728cab53092bd5f143beed7fbba7ba99de3c16c4" + integrity sha512-uug3FEEGv0r+jrecvUUpbY8lLisvIjg6AAic6a2bSP5OEOLeJsDSnvhCDov7ipFFMXS3orMpzlmi0ZcuGkBbow== dependencies: - undici-types "~6.19.2" + undici-types "~6.21.0" "@types/stack-utils@^2.0.0": version "2.0.3" @@ -3285,6 +3285,7 @@ ts-node@^10.5.0: "tsc-multi@https://github.com/stainless-api/tsc-multi/releases/download/v1.1.8/tsc-multi.tgz": version "1.1.8" + uid f544b359b8f05e607771ffacc280e58201476b04 resolved "https://github.com/stainless-api/tsc-multi/releases/download/v1.1.8/tsc-multi.tgz#f544b359b8f05e607771ffacc280e58201476b04" dependencies: debug "^4.3.7" @@ -3353,10 +3354,10 @@ undici-types@~5.26.4: resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== -undici-types@~6.19.2: - version "6.19.8" - resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.19.8.tgz#35111c9d1437ab83a7cdc0abae2f26d88eda0a02" - integrity sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw== +undici-types@~6.21.0: + version "6.21.0" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.21.0.tgz#691d00af3909be93a7faa13be61b3a5b50ef12cb" + integrity sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ== unicode-emoji-modifier-base@^1.0.0: version "1.0.0" From 8e20b9426363ad7dbd061f7778d67e8aeccc15a6 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 16 Aug 2025 03:24:42 +0000 Subject: [PATCH 143/551] chore(internal): formatting change --- src/client.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/client.ts b/src/client.ts index 789a1a35..4aa69648 100644 --- a/src/client.ts +++ b/src/client.ts @@ -773,10 +773,12 @@ export class Kernel { invocations: API.Invocations = new API.Invocations(this); browsers: API.Browsers = new API.Browsers(this); } + Kernel.Deployments = Deployments; Kernel.Apps = Apps; Kernel.Invocations = Invocations; Kernel.Browsers = Browsers; + export declare namespace Kernel { export type RequestOptions = Opts.RequestOptions; From f9020ec8d39be1cdcb217febfaaeba2e3f996a72 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 20 Aug 2025 05:12:18 +0000 Subject: [PATCH 144/551] feat(mcp): add code execution tool --- package.json | 2 +- yarn.lock | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index e3715cb0..43e0e2fe 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,7 @@ "publint": "^0.2.12", "ts-jest": "^29.1.0", "ts-node": "^10.5.0", - "tsc-multi": "https://github.com/stainless-api/tsc-multi/releases/download/v1.1.8/tsc-multi.tgz", + "tsc-multi": "https://github.com/stainless-api/tsc-multi/releases/download/v1.1.9/tsc-multi.tgz", "tsconfig-paths": "^4.0.0", "typescript": "5.8.3", "typescript-eslint": "8.31.1" diff --git a/yarn.lock b/yarn.lock index fd164dcf..8311caf5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3283,10 +3283,9 @@ ts-node@^10.5.0: v8-compile-cache-lib "^3.0.0" yn "3.1.1" -"tsc-multi@https://github.com/stainless-api/tsc-multi/releases/download/v1.1.8/tsc-multi.tgz": - version "1.1.8" - uid f544b359b8f05e607771ffacc280e58201476b04 - resolved "https://github.com/stainless-api/tsc-multi/releases/download/v1.1.8/tsc-multi.tgz#f544b359b8f05e607771ffacc280e58201476b04" +"tsc-multi@https://github.com/stainless-api/tsc-multi/releases/download/v1.1.9/tsc-multi.tgz": + version "1.1.9" + resolved "https://github.com/stainless-api/tsc-multi/releases/download/v1.1.9/tsc-multi.tgz#777f6f5d9e26bf0e94e5170990dd3a841d6707cd" dependencies: debug "^4.3.7" fast-glob "^3.3.2" From 5d97e2735d53818e8053bbad35004d483aba6da7 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 22 Aug 2025 05:31:17 +0000 Subject: [PATCH 145/551] chore: add package to package.json --- package.json | 1 + scripts/bootstrap | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 43e0e2fe..2da5e1d0 100644 --- a/package.json +++ b/package.json @@ -46,6 +46,7 @@ "ts-node": "^10.5.0", "tsc-multi": "https://github.com/stainless-api/tsc-multi/releases/download/v1.1.9/tsc-multi.tgz", "tsconfig-paths": "^4.0.0", + "tslib": "^2.8.1", "typescript": "5.8.3", "typescript-eslint": "8.31.1" }, diff --git a/scripts/bootstrap b/scripts/bootstrap index 0af58e25..062a0349 100755 --- a/scripts/bootstrap +++ b/scripts/bootstrap @@ -15,4 +15,4 @@ echo "==> Installing Node dependencies…" PACKAGE_MANAGER=$(command -v yarn >/dev/null 2>&1 && echo "yarn" || echo "npm") -$PACKAGE_MANAGER install +$PACKAGE_MANAGER install "$@" From 5208507325a8a0952efa712d95a1374b0778cefc Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 22 Aug 2025 05:37:52 +0000 Subject: [PATCH 146/551] chore(client): qualify global Blob --- src/client.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client.ts b/src/client.ts index 4aa69648..ae4c60dc 100644 --- a/src/client.ts +++ b/src/client.ts @@ -729,7 +729,7 @@ export class Kernel { // Preserve legacy string encoding behavior for now headers.values.has('content-type')) || // `Blob` is superset of `File` - body instanceof Blob || + ((globalThis as any).Blob && body instanceof (globalThis as any).Blob) || // `FormData` -> `multipart/form-data` body instanceof FormData || // `URLSearchParams` -> `application/x-www-form-urlencoded` From c79d31464227cc8304a98db9b7578cc22048af3f Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 23 Aug 2025 04:24:37 +0000 Subject: [PATCH 147/551] chore: update CI script --- scripts/utils/upload-artifact.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/utils/upload-artifact.sh b/scripts/utils/upload-artifact.sh index 5580c062..ab5947d6 100755 --- a/scripts/utils/upload-artifact.sh +++ b/scripts/utils/upload-artifact.sh @@ -12,7 +12,7 @@ if [[ "$SIGNED_URL" == "null" ]]; then exit 1 fi -UPLOAD_RESPONSE=$(tar -cz dist | curl -v -X PUT \ +UPLOAD_RESPONSE=$(tar -cz "${BUILD_PATH:-dist}" | curl -v -X PUT \ -H "Content-Type: application/gzip" \ --data-binary @- "$SIGNED_URL" 2>&1) From 51c282d4aa2222eb25dff55c347dcfa0ef01f9d9 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 27 Aug 2025 17:38:48 +0000 Subject: [PATCH 148/551] feat(api): new process, fs, and log endpoints New endpoints for executing processes on browser instances, uploading / downloading whole directories as zip files, and streaming any log file on a browser instance --- .stats.yml | 8 +- api.md | 29 ++ src/resources/browsers/browsers.ts | 46 +++ src/resources/browsers/fs/fs.ts | 105 ++++++ src/resources/browsers/fs/index.ts | 3 + src/resources/browsers/index.ts | 19 + src/resources/browsers/logs.ts | 50 +++ src/resources/browsers/process.ts | 366 +++++++++++++++++++ tests/api-resources/browsers/fs/fs.test.ts | 48 +++ tests/api-resources/browsers/logs.test.ts | 32 ++ tests/api-resources/browsers/process.test.ts | 148 ++++++++ 11 files changed, 850 insertions(+), 4 deletions(-) create mode 100644 src/resources/browsers/logs.ts create mode 100644 src/resources/browsers/process.ts create mode 100644 tests/api-resources/browsers/logs.test.ts create mode 100644 tests/api-resources/browsers/process.test.ts diff --git a/.stats.yml b/.stats.yml index f6de080e..b791078d 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 31 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-b55c3e0424fa7733487139488b9fff00ad8949ff02ee3160ee36b9334e84b134.yml -openapi_spec_hash: 17f36677e3dc0a3aeb419654c8d5cae3 -config_hash: f67e4b33b2fb30c1405ee2fff8096320 +configured_endpoints: 41 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-a7c1df5070fe59642d7a1f168aa902a468227752bfc930cbf38930f7c205dbb6.yml +openapi_spec_hash: eab65e39aef4f0a0952b82adeecf6b5b +config_hash: 5de78bc29ac060562575cb54bb26826c diff --git a/api.md b/api.md index 19d1eca5..69fe6bff 100644 --- a/api.md +++ b/api.md @@ -97,11 +97,14 @@ Methods: - client.browsers.fs.createDirectory(id, { ...params }) -> void - client.browsers.fs.deleteDirectory(id, { ...params }) -> void - client.browsers.fs.deleteFile(id, { ...params }) -> void +- client.browsers.fs.downloadDirZip(id, { ...params }) -> Response - client.browsers.fs.fileInfo(id, { ...params }) -> FFileInfoResponse - client.browsers.fs.listFiles(id, { ...params }) -> FListFilesResponse - client.browsers.fs.move(id, { ...params }) -> void - client.browsers.fs.readFile(id, { ...params }) -> Response - client.browsers.fs.setFilePermissions(id, { ...params }) -> void +- client.browsers.fs.upload(id, { ...params }) -> void +- client.browsers.fs.uploadZip(id, { ...params }) -> void - client.browsers.fs.writeFile(id, contents, { ...params }) -> void ### Watch @@ -116,3 +119,29 @@ Methods: - client.browsers.fs.watch.events(watchID, { ...params }) -> WatchEventsResponse - client.browsers.fs.watch.start(id, { ...params }) -> WatchStartResponse - client.browsers.fs.watch.stop(watchID, { ...params }) -> void + +## Process + +Types: + +- ProcessExecResponse +- ProcessKillResponse +- ProcessSpawnResponse +- ProcessStatusResponse +- ProcessStdinResponse +- ProcessStdoutStreamResponse + +Methods: + +- client.browsers.process.exec(id, { ...params }) -> ProcessExecResponse +- client.browsers.process.kill(processID, { ...params }) -> ProcessKillResponse +- client.browsers.process.spawn(id, { ...params }) -> ProcessSpawnResponse +- client.browsers.process.status(processID, { ...params }) -> ProcessStatusResponse +- client.browsers.process.stdin(processID, { ...params }) -> ProcessStdinResponse +- client.browsers.process.stdoutStream(processID, { ...params }) -> ProcessStdoutStreamResponse + +## Logs + +Methods: + +- client.browsers.logs.stream(id, { ...params }) -> LogEvent diff --git a/src/resources/browsers/browsers.ts b/src/resources/browsers/browsers.ts index 3e37d792..20a3e0c8 100644 --- a/src/resources/browsers/browsers.ts +++ b/src/resources/browsers/browsers.ts @@ -2,6 +2,24 @@ import { APIResource } from '../../core/resource'; import * as BrowsersAPI from './browsers'; +import * as LogsAPI from './logs'; +import { LogStreamParams, Logs } from './logs'; +import * as ProcessAPI from './process'; +import { + Process, + ProcessExecParams, + ProcessExecResponse, + ProcessKillParams, + ProcessKillResponse, + ProcessSpawnParams, + ProcessSpawnResponse, + ProcessStatusParams, + ProcessStatusResponse, + ProcessStdinParams, + ProcessStdinResponse, + ProcessStdoutStreamParams, + ProcessStdoutStreamResponse, +} from './process'; import * as ReplaysAPI from './replays'; import { ReplayDownloadParams, @@ -16,6 +34,7 @@ import { FCreateDirectoryParams, FDeleteDirectoryParams, FDeleteFileParams, + FDownloadDirZipParams, FFileInfoParams, FFileInfoResponse, FListFilesParams, @@ -23,6 +42,8 @@ import { FMoveParams, FReadFileParams, FSetFilePermissionsParams, + FUploadParams, + FUploadZipParams, FWriteFileParams, Fs, } from './fs/fs'; @@ -34,6 +55,8 @@ import { path } from '../../internal/utils/path'; export class Browsers extends APIResource { replays: ReplaysAPI.Replays = new ReplaysAPI.Replays(this._client); fs: FsAPI.Fs = new FsAPI.Fs(this._client); + process: ProcessAPI.Process = new ProcessAPI.Process(this._client); + logs: LogsAPI.Logs = new LogsAPI.Logs(this._client); /** * Create a new browser session from within an action. @@ -296,6 +319,8 @@ export interface BrowserDeleteParams { Browsers.Replays = Replays; Browsers.Fs = Fs; +Browsers.Process = Process; +Browsers.Logs = Logs; export declare namespace Browsers { export { @@ -323,11 +348,32 @@ export declare namespace Browsers { type FCreateDirectoryParams as FCreateDirectoryParams, type FDeleteDirectoryParams as FDeleteDirectoryParams, type FDeleteFileParams as FDeleteFileParams, + type FDownloadDirZipParams as FDownloadDirZipParams, type FFileInfoParams as FFileInfoParams, type FListFilesParams as FListFilesParams, type FMoveParams as FMoveParams, type FReadFileParams as FReadFileParams, type FSetFilePermissionsParams as FSetFilePermissionsParams, + type FUploadParams as FUploadParams, + type FUploadZipParams as FUploadZipParams, type FWriteFileParams as FWriteFileParams, }; + + export { + Process as Process, + type ProcessExecResponse as ProcessExecResponse, + type ProcessKillResponse as ProcessKillResponse, + type ProcessSpawnResponse as ProcessSpawnResponse, + type ProcessStatusResponse as ProcessStatusResponse, + type ProcessStdinResponse as ProcessStdinResponse, + type ProcessStdoutStreamResponse as ProcessStdoutStreamResponse, + type ProcessExecParams as ProcessExecParams, + type ProcessKillParams as ProcessKillParams, + type ProcessSpawnParams as ProcessSpawnParams, + type ProcessStatusParams as ProcessStatusParams, + type ProcessStdinParams as ProcessStdinParams, + type ProcessStdoutStreamParams as ProcessStdoutStreamParams, + }; + + export { Logs as Logs, type LogStreamParams as LogStreamParams }; } diff --git a/src/resources/browsers/fs/fs.ts b/src/resources/browsers/fs/fs.ts index caaa1486..b6adb02e 100644 --- a/src/resources/browsers/fs/fs.ts +++ b/src/resources/browsers/fs/fs.ts @@ -11,8 +11,10 @@ import { WatchStopParams, } from './watch'; import { APIPromise } from '../../../core/api-promise'; +import { type Uploadable } from '../../../core/uploads'; import { buildHeaders } from '../../../internal/headers'; import { RequestOptions } from '../../../internal/request-options'; +import { multipartFormRequestOptions } from '../../../internal/uploads'; import { path } from '../../../internal/utils/path'; export class Fs extends APIResource { @@ -70,6 +72,29 @@ export class Fs extends APIResource { }); } + /** + * Returns a ZIP file containing the contents of the specified directory. + * + * @example + * ```ts + * const response = await client.browsers.fs.downloadDirZip( + * 'id', + * { path: '/J!' }, + * ); + * + * const content = await response.blob(); + * console.log(content); + * ``` + */ + downloadDirZip(id: string, query: FDownloadDirZipParams, options?: RequestOptions): APIPromise { + return this._client.get(path`/browsers/${id}/fs/download_dir_zip`, { + query, + ...options, + headers: buildHeaders([{ Accept: 'application/zip' }, options?.headers]), + __binaryResponse: true, + }); + } + /** * Get information about a file or directory * @@ -162,6 +187,52 @@ export class Fs extends APIResource { }); } + /** + * Allows uploading single or multiple files to the remote filesystem. + * + * @example + * ```ts + * await client.browsers.fs.upload('id', { + * files: [ + * { + * dest_path: '/J!', + * file: fs.createReadStream('path/to/file'), + * }, + * ], + * }); + * ``` + */ + upload(id: string, body: FUploadParams, options?: RequestOptions): APIPromise { + return this._client.post( + path`/browsers/${id}/fs/upload`, + multipartFormRequestOptions( + { body, ...options, headers: buildHeaders([{ Accept: '*/*' }, options?.headers]) }, + this._client, + ), + ); + } + + /** + * Upload a zip file and extract its contents to the specified destination path. + * + * @example + * ```ts + * await client.browsers.fs.uploadZip('id', { + * dest_path: '/J!', + * zip_file: fs.createReadStream('path/to/file'), + * }); + * ``` + */ + uploadZip(id: string, body: FUploadZipParams, options?: RequestOptions): APIPromise { + return this._client.post( + path`/browsers/${id}/fs/upload_zip`, + multipartFormRequestOptions( + { body, ...options, headers: buildHeaders([{ Accept: '*/*' }, options?.headers]) }, + this._client, + ), + ); + } + /** * Write or create a file * @@ -290,6 +361,13 @@ export interface FDeleteFileParams { path: string; } +export interface FDownloadDirZipParams { + /** + * Absolute directory path to archive and download. + */ + path: string; +} + export interface FFileInfoParams { /** * Absolute path of the file or directory. @@ -345,6 +423,30 @@ export interface FSetFilePermissionsParams { owner?: string; } +export interface FUploadParams { + files: Array; +} + +export namespace FUploadParams { + export interface File { + /** + * Absolute destination path to write the file. + */ + dest_path: string; + + file: Uploadable; + } +} + +export interface FUploadZipParams { + /** + * Absolute destination directory to extract the archive to. + */ + dest_path: string; + + zip_file: Uploadable; +} + export interface FWriteFileParams { /** * Query param: Destination absolute file path. @@ -366,11 +468,14 @@ export declare namespace Fs { type FCreateDirectoryParams as FCreateDirectoryParams, type FDeleteDirectoryParams as FDeleteDirectoryParams, type FDeleteFileParams as FDeleteFileParams, + type FDownloadDirZipParams as FDownloadDirZipParams, type FFileInfoParams as FFileInfoParams, type FListFilesParams as FListFilesParams, type FMoveParams as FMoveParams, type FReadFileParams as FReadFileParams, type FSetFilePermissionsParams as FSetFilePermissionsParams, + type FUploadParams as FUploadParams, + type FUploadZipParams as FUploadZipParams, type FWriteFileParams as FWriteFileParams, }; diff --git a/src/resources/browsers/fs/index.ts b/src/resources/browsers/fs/index.ts index 14c3cb81..0109d981 100644 --- a/src/resources/browsers/fs/index.ts +++ b/src/resources/browsers/fs/index.ts @@ -7,11 +7,14 @@ export { type FCreateDirectoryParams, type FDeleteDirectoryParams, type FDeleteFileParams, + type FDownloadDirZipParams, type FFileInfoParams, type FListFilesParams, type FMoveParams, type FReadFileParams, type FSetFilePermissionsParams, + type FUploadParams, + type FUploadZipParams, type FWriteFileParams, } from './fs'; export { diff --git a/src/resources/browsers/index.ts b/src/resources/browsers/index.ts index cc79adb5..3437de12 100644 --- a/src/resources/browsers/index.ts +++ b/src/resources/browsers/index.ts @@ -16,13 +16,32 @@ export { type FCreateDirectoryParams, type FDeleteDirectoryParams, type FDeleteFileParams, + type FDownloadDirZipParams, type FFileInfoParams, type FListFilesParams, type FMoveParams, type FReadFileParams, type FSetFilePermissionsParams, + type FUploadParams, + type FUploadZipParams, type FWriteFileParams, } from './fs/index'; +export { Logs, type LogStreamParams } from './logs'; +export { + Process, + type ProcessExecResponse, + type ProcessKillResponse, + type ProcessSpawnResponse, + type ProcessStatusResponse, + type ProcessStdinResponse, + type ProcessStdoutStreamResponse, + type ProcessExecParams, + type ProcessKillParams, + type ProcessSpawnParams, + type ProcessStatusParams, + type ProcessStdinParams, + type ProcessStdoutStreamParams, +} from './process'; export { Replays, type ReplayListResponse, diff --git a/src/resources/browsers/logs.ts b/src/resources/browsers/logs.ts new file mode 100644 index 00000000..485f9d7c --- /dev/null +++ b/src/resources/browsers/logs.ts @@ -0,0 +1,50 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../core/resource'; +import * as Shared from '../shared'; +import { APIPromise } from '../../core/api-promise'; +import { Stream } from '../../core/streaming'; +import { buildHeaders } from '../../internal/headers'; +import { RequestOptions } from '../../internal/request-options'; +import { path } from '../../internal/utils/path'; + +export class Logs extends APIResource { + /** + * Stream log files on the browser instance via SSE + * + * @example + * ```ts + * const logEvent = await client.browsers.logs.stream('id', { + * source: 'path', + * }); + * ``` + */ + stream(id: string, query: LogStreamParams, options?: RequestOptions): APIPromise> { + return this._client.get(path`/browsers/${id}/logs/stream`, { + query, + ...options, + headers: buildHeaders([{ Accept: 'text/event-stream' }, options?.headers]), + stream: true, + }) as APIPromise>; + } +} + +export interface LogStreamParams { + source: 'path' | 'supervisor'; + + follow?: boolean; + + /** + * only required if source is path + */ + path?: string; + + /** + * only required if source is supervisor + */ + supervisor_process?: string; +} + +export declare namespace Logs { + export { type LogStreamParams as LogStreamParams }; +} diff --git a/src/resources/browsers/process.ts b/src/resources/browsers/process.ts new file mode 100644 index 00000000..2a3be958 --- /dev/null +++ b/src/resources/browsers/process.ts @@ -0,0 +1,366 @@ +// 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 { Stream } from '../../core/streaming'; +import { buildHeaders } from '../../internal/headers'; +import { RequestOptions } from '../../internal/request-options'; +import { path } from '../../internal/utils/path'; + +export class Process extends APIResource { + /** + * Execute a command synchronously + * + * @example + * ```ts + * const response = await client.browsers.process.exec('id', { + * command: 'command', + * }); + * ``` + */ + exec(id: string, body: ProcessExecParams, options?: RequestOptions): APIPromise { + return this._client.post(path`/browsers/${id}/process/exec`, { body, ...options }); + } + + /** + * Send signal to process + * + * @example + * ```ts + * const response = await client.browsers.process.kill( + * '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', + * { id: 'id', signal: 'TERM' }, + * ); + * ``` + */ + kill( + processID: string, + params: ProcessKillParams, + options?: RequestOptions, + ): APIPromise { + const { id, ...body } = params; + return this._client.post(path`/browsers/${id}/process/${processID}/kill`, { body, ...options }); + } + + /** + * Execute a command asynchronously + * + * @example + * ```ts + * const response = await client.browsers.process.spawn('id', { + * command: 'command', + * }); + * ``` + */ + spawn(id: string, body: ProcessSpawnParams, options?: RequestOptions): APIPromise { + return this._client.post(path`/browsers/${id}/process/spawn`, { body, ...options }); + } + + /** + * Get process status + * + * @example + * ```ts + * const response = await client.browsers.process.status( + * '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', + * { id: 'id' }, + * ); + * ``` + */ + status( + processID: string, + params: ProcessStatusParams, + options?: RequestOptions, + ): APIPromise { + const { id } = params; + return this._client.get(path`/browsers/${id}/process/${processID}/status`, options); + } + + /** + * Write to process stdin + * + * @example + * ```ts + * const response = await client.browsers.process.stdin( + * '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', + * { id: 'id', data_b64: 'data_b64' }, + * ); + * ``` + */ + stdin( + processID: string, + params: ProcessStdinParams, + options?: RequestOptions, + ): APIPromise { + const { id, ...body } = params; + return this._client.post(path`/browsers/${id}/process/${processID}/stdin`, { body, ...options }); + } + + /** + * Stream process stdout via SSE + * + * @example + * ```ts + * const response = await client.browsers.process.stdoutStream( + * '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', + * { id: 'id' }, + * ); + * ``` + */ + stdoutStream( + processID: string, + params: ProcessStdoutStreamParams, + options?: RequestOptions, + ): APIPromise> { + const { id } = params; + return this._client.get(path`/browsers/${id}/process/${processID}/stdout/stream`, { + ...options, + headers: buildHeaders([{ Accept: 'text/event-stream' }, options?.headers]), + stream: true, + }) as APIPromise>; + } +} + +/** + * Result of a synchronous command execution. + */ +export interface ProcessExecResponse { + /** + * Execution duration in milliseconds. + */ + duration_ms?: number; + + /** + * Process exit code. + */ + exit_code?: number; + + /** + * Base64-encoded stderr buffer. + */ + stderr_b64?: string; + + /** + * Base64-encoded stdout buffer. + */ + stdout_b64?: string; +} + +/** + * Generic OK response. + */ +export interface ProcessKillResponse { + /** + * Indicates success. + */ + ok: boolean; +} + +/** + * Information about a spawned process. + */ +export interface ProcessSpawnResponse { + /** + * OS process ID. + */ + pid?: number; + + /** + * Server-assigned identifier for the process. + */ + process_id?: string; + + /** + * Timestamp when the process started. + */ + started_at?: string; +} + +/** + * Current status of a process. + */ +export interface ProcessStatusResponse { + /** + * Estimated CPU usage percentage. + */ + cpu_pct?: number; + + /** + * Exit code if the process has exited. + */ + exit_code?: number | null; + + /** + * Estimated resident memory usage in bytes. + */ + mem_bytes?: number; + + /** + * Process state. + */ + state?: 'running' | 'exited'; +} + +/** + * Result of writing to stdin. + */ +export interface ProcessStdinResponse { + /** + * Number of bytes written. + */ + written_bytes?: number; +} + +/** + * SSE payload representing process output or lifecycle events. + */ +export interface ProcessStdoutStreamResponse { + /** + * Base64-encoded data from the process stream. + */ + data_b64?: string; + + /** + * Lifecycle event type. + */ + event?: 'exit'; + + /** + * Exit code when the event is "exit". + */ + exit_code?: number; + + /** + * Source stream of the data chunk. + */ + stream?: 'stdout' | 'stderr'; +} + +export interface ProcessExecParams { + /** + * Executable or shell command to run. + */ + command: string; + + /** + * Command arguments. + */ + args?: Array; + + /** + * Run the process with root privileges. + */ + as_root?: boolean; + + /** + * Run the process as this user. + */ + as_user?: string | null; + + /** + * Working directory (absolute path) to run the command in. + */ + cwd?: string | null; + + /** + * Environment variables to set for the process. + */ + env?: { [key: string]: string }; + + /** + * Maximum execution time in seconds. + */ + timeout_sec?: number | null; +} + +export interface ProcessKillParams { + /** + * Path param: Browser session ID + */ + id: string; + + /** + * Body param: Signal to send. + */ + signal: 'TERM' | 'KILL' | 'INT' | 'HUP'; +} + +export interface ProcessSpawnParams { + /** + * Executable or shell command to run. + */ + command: string; + + /** + * Command arguments. + */ + args?: Array; + + /** + * Run the process with root privileges. + */ + as_root?: boolean; + + /** + * Run the process as this user. + */ + as_user?: string | null; + + /** + * Working directory (absolute path) to run the command in. + */ + cwd?: string | null; + + /** + * Environment variables to set for the process. + */ + env?: { [key: string]: string }; + + /** + * Maximum execution time in seconds. + */ + timeout_sec?: number | null; +} + +export interface ProcessStatusParams { + /** + * Browser session ID + */ + id: string; +} + +export interface ProcessStdinParams { + /** + * Path param: Browser session ID + */ + id: string; + + /** + * Body param: Base64-encoded data to write. + */ + data_b64: string; +} + +export interface ProcessStdoutStreamParams { + /** + * Browser session ID + */ + id: string; +} + +export declare namespace Process { + export { + type ProcessExecResponse as ProcessExecResponse, + type ProcessKillResponse as ProcessKillResponse, + type ProcessSpawnResponse as ProcessSpawnResponse, + type ProcessStatusResponse as ProcessStatusResponse, + type ProcessStdinResponse as ProcessStdinResponse, + type ProcessStdoutStreamResponse as ProcessStdoutStreamResponse, + type ProcessExecParams as ProcessExecParams, + type ProcessKillParams as ProcessKillParams, + type ProcessSpawnParams as ProcessSpawnParams, + type ProcessStatusParams as ProcessStatusParams, + type ProcessStdinParams as ProcessStdinParams, + type ProcessStdoutStreamParams as ProcessStdoutStreamParams, + }; +} diff --git a/tests/api-resources/browsers/fs/fs.test.ts b/tests/api-resources/browsers/fs/fs.test.ts index 87fbb3d3..92a0c9ce 100644 --- a/tests/api-resources/browsers/fs/fs.test.ts +++ b/tests/api-resources/browsers/fs/fs.test.ts @@ -59,6 +59,10 @@ describe('resource fs', () => { const response = await client.browsers.fs.deleteFile('id', { path: '/J!' }); }); + test('downloadDirZip: required and optional params', async () => { + const response = await client.browsers.fs.downloadDirZip('id', { path: '/J!' }); + }); + // Prism tests are disabled test.skip('fileInfo: only required params', async () => { const responsePromise = client.browsers.fs.fileInfo('id', { path: '/J!' }); @@ -136,6 +140,50 @@ describe('resource fs', () => { }); }); + // Prism tests are disabled + test.skip('upload: only required params', async () => { + const responsePromise = client.browsers.fs.upload('id', { + files: [{ dest_path: '/J!', file: await toFile(Buffer.from('# my file contents'), 'README.md') }], + }); + 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); + }); + + // Prism tests are disabled + test.skip('upload: required and optional params', async () => { + const response = await client.browsers.fs.upload('id', { + files: [{ dest_path: '/J!', file: await toFile(Buffer.from('# my file contents'), 'README.md') }], + }); + }); + + // Prism tests are disabled + test.skip('uploadZip: only required params', async () => { + const responsePromise = client.browsers.fs.uploadZip('id', { + dest_path: '/J!', + zip_file: await toFile(Buffer.from('# my file contents'), 'README.md'), + }); + 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); + }); + + // Prism tests are disabled + test.skip('uploadZip: required and optional params', async () => { + const response = await client.browsers.fs.uploadZip('id', { + dest_path: '/J!', + zip_file: await toFile(Buffer.from('# my file contents'), 'README.md'), + }); + }); + // Prism tests are disabled test.skip('writeFile: only required params', async () => { const responsePromise = client.browsers.fs.writeFile( diff --git a/tests/api-resources/browsers/logs.test.ts b/tests/api-resources/browsers/logs.test.ts new file mode 100644 index 00000000..0fa405ec --- /dev/null +++ b/tests/api-resources/browsers/logs.test.ts @@ -0,0 +1,32 @@ +// 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 logs', () => { + // Prism doesn't support text/event-stream responses + test.skip('stream: only required params', async () => { + const responsePromise = client.browsers.logs.stream('id', { source: 'path' }); + 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); + }); + + // Prism doesn't support text/event-stream responses + test.skip('stream: required and optional params', async () => { + const response = await client.browsers.logs.stream('id', { + source: 'path', + follow: true, + path: 'path', + supervisor_process: 'supervisor_process', + }); + }); +}); diff --git a/tests/api-resources/browsers/process.test.ts b/tests/api-resources/browsers/process.test.ts new file mode 100644 index 00000000..138070a4 --- /dev/null +++ b/tests/api-resources/browsers/process.test.ts @@ -0,0 +1,148 @@ +// 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 process', () => { + // Prism tests are disabled + test.skip('exec: only required params', async () => { + const responsePromise = client.browsers.process.exec('id', { command: 'command' }); + 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); + }); + + // Prism tests are disabled + test.skip('exec: required and optional params', async () => { + const response = await client.browsers.process.exec('id', { + command: 'command', + args: ['string'], + as_root: true, + as_user: 'as_user', + cwd: '/J!', + env: { foo: 'string' }, + timeout_sec: 0, + }); + }); + + // Prism tests are disabled + test.skip('kill: only required params', async () => { + const responsePromise = client.browsers.process.kill('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', { + id: 'id', + signal: 'TERM', + }); + 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); + }); + + // Prism tests are disabled + test.skip('kill: required and optional params', async () => { + const response = await client.browsers.process.kill('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', { + id: 'id', + signal: 'TERM', + }); + }); + + // Prism tests are disabled + test.skip('spawn: only required params', async () => { + const responsePromise = client.browsers.process.spawn('id', { command: 'command' }); + 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); + }); + + // Prism tests are disabled + test.skip('spawn: required and optional params', async () => { + const response = await client.browsers.process.spawn('id', { + command: 'command', + args: ['string'], + as_root: true, + as_user: 'as_user', + cwd: '/J!', + env: { foo: 'string' }, + timeout_sec: 0, + }); + }); + + // Prism tests are disabled + test.skip('status: only required params', async () => { + const responsePromise = client.browsers.process.status('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', { + 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); + }); + + // Prism tests are disabled + test.skip('status: required and optional params', async () => { + const response = await client.browsers.process.status('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', { + id: 'id', + }); + }); + + // Prism tests are disabled + test.skip('stdin: only required params', async () => { + const responsePromise = client.browsers.process.stdin('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', { + id: 'id', + data_b64: 'data_b64', + }); + 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); + }); + + // Prism tests are disabled + test.skip('stdin: required and optional params', async () => { + const response = await client.browsers.process.stdin('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', { + id: 'id', + data_b64: 'data_b64', + }); + }); + + // Prism doesn't support text/event-stream responses + test.skip('stdoutStream: only required params', async () => { + const responsePromise = client.browsers.process.stdoutStream('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', { + 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); + }); + + // Prism doesn't support text/event-stream responses + test.skip('stdoutStream: required and optional params', async () => { + const response = await client.browsers.process.stdoutStream('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', { + id: 'id', + }); + }); +}); From 6468dfb1de03e74b242dcd9bdb6001ada81fcd8d Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 27 Aug 2025 18:22:30 +0000 Subject: [PATCH 149/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index b28fea99..7d9b009d 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.9.1" + ".": "0.10.0" } diff --git a/package.json b/package.json index 2da5e1d0..af5ef848 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.9.1", + "version": "0.10.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 72f481f5..c2e5b969 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.9.1'; // x-release-please-version +export const VERSION = '0.10.0'; // x-release-please-version From e29c93d3429189464f813f8aaa0a5db379355a7e Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 29 Aug 2025 03:15:08 +0000 Subject: [PATCH 150/551] chore(internal): update global Error reference --- src/client.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client.ts b/src/client.ts index ae4c60dc..97aa3e9f 100644 --- a/src/client.ts +++ b/src/client.ts @@ -422,7 +422,7 @@ export class Kernel { const response = await this.fetchWithTimeout(url, req, timeout, controller).catch(castToError); const headersTime = Date.now(); - if (response instanceof Error) { + if (response instanceof globalThis.Error) { const retryMessage = `retrying, ${retriesRemaining} attempts remaining`; if (options.signal?.aborted) { throw new Errors.APIUserAbortError(); From 60452768c3f123ee0f173e95007407b93f473f14 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 4 Sep 2025 15:09:36 +0000 Subject: [PATCH 151/551] feat(api): adding support for browser profiles --- .stats.yml | 8 +- api.md | 15 ++++ src/client.ts | 11 +++ src/resources/browsers/browsers.ts | 79 +++++++++++++++++++ src/resources/browsers/index.ts | 1 + src/resources/index.ts | 2 + src/resources/profiles.ts | 67 ++++++++++++++++ tests/api-resources/browsers/browsers.test.ts | 1 + tests/api-resources/profiles.test.ts | 58 ++++++++++++++ 9 files changed, 238 insertions(+), 4 deletions(-) create mode 100644 src/resources/profiles.ts create mode 100644 tests/api-resources/profiles.test.ts diff --git a/.stats.yml b/.stats.yml index b791078d..6ac19baf 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 41 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-a7c1df5070fe59642d7a1f168aa902a468227752bfc930cbf38930f7c205dbb6.yml -openapi_spec_hash: eab65e39aef4f0a0952b82adeecf6b5b -config_hash: 5de78bc29ac060562575cb54bb26826c +configured_endpoints: 46 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-e98d46c55826cdf541a9ee0df04ce92806ac6d4d92957ae79f897270b7d85b23.yml +openapi_spec_hash: 8a1af54fc0a4417165b8a52e6354b685 +config_hash: 043ddc54629c6d8b889123770cb4769f diff --git a/api.md b/api.md index 69fe6bff..4c61dfb9 100644 --- a/api.md +++ b/api.md @@ -59,6 +59,7 @@ Methods: Types: - BrowserPersistence +- Profile - BrowserCreateResponse - BrowserRetrieveResponse - BrowserListResponse @@ -145,3 +146,17 @@ Methods: Methods: - client.browsers.logs.stream(id, { ...params }) -> LogEvent + +# Profiles + +Types: + +- ProfileListResponse + +Methods: + +- client.profiles.create({ ...params }) -> Profile +- client.profiles.retrieve(idOrName) -> Profile +- client.profiles.list() -> ProfileListResponse +- client.profiles.delete(idOrName) -> void +- client.profiles.download(idOrName) -> Response diff --git a/src/client.ts b/src/client.ts index 97aa3e9f..97b5ded3 100644 --- a/src/client.ts +++ b/src/client.ts @@ -38,6 +38,7 @@ import { InvocationUpdateResponse, Invocations, } from './resources/invocations'; +import { ProfileCreateParams, ProfileListResponse, Profiles } from './resources/profiles'; import { BrowserCreateParams, BrowserCreateResponse, @@ -46,6 +47,7 @@ import { BrowserPersistence, BrowserRetrieveResponse, Browsers, + Profile, } from './resources/browsers/browsers'; import { type Fetch } from './internal/builtin-types'; import { HeadersLike, NullableHeaders, buildHeaders } from './internal/headers'; @@ -772,12 +774,14 @@ export class Kernel { apps: API.Apps = new API.Apps(this); invocations: API.Invocations = new API.Invocations(this); browsers: API.Browsers = new API.Browsers(this); + profiles: API.Profiles = new API.Profiles(this); } Kernel.Deployments = Deployments; Kernel.Apps = Apps; Kernel.Invocations = Invocations; Kernel.Browsers = Browsers; +Kernel.Profiles = Profiles; export declare namespace Kernel { export type RequestOptions = Opts.RequestOptions; @@ -810,6 +814,7 @@ export declare namespace Kernel { export { Browsers as Browsers, type BrowserPersistence as BrowserPersistence, + type Profile as Profile, type BrowserCreateResponse as BrowserCreateResponse, type BrowserRetrieveResponse as BrowserRetrieveResponse, type BrowserListResponse as BrowserListResponse, @@ -817,6 +822,12 @@ export declare namespace Kernel { type BrowserDeleteParams as BrowserDeleteParams, }; + export { + Profiles as Profiles, + type ProfileListResponse as ProfileListResponse, + type ProfileCreateParams as ProfileCreateParams, + }; + export type AppAction = API.AppAction; export type ErrorDetail = API.ErrorDetail; export type ErrorEvent = API.ErrorEvent; diff --git a/src/resources/browsers/browsers.ts b/src/resources/browsers/browsers.ts index 20a3e0c8..5cc34155 100644 --- a/src/resources/browsers/browsers.ts +++ b/src/resources/browsers/browsers.ts @@ -146,6 +146,36 @@ export interface BrowserPersistence { id: string; } +/** + * Browser profile metadata. + */ +export interface Profile { + /** + * Unique identifier for the profile + */ + id: string; + + /** + * Timestamp when the profile was created + */ + created_at: string; + + /** + * Timestamp when the profile was last used + */ + last_used_at?: string; + + /** + * Optional, easier-to-reference name for the profile + */ + name?: string | null; + + /** + * Timestamp when the profile was last updated + */ + updated_at?: string; +} + export interface BrowserCreateResponse { /** * Websocket URL for Chrome DevTools Protocol connections to the browser session @@ -187,6 +217,11 @@ export interface BrowserCreateResponse { * Optional persistence configuration for the browser session. */ persistence?: BrowserPersistence; + + /** + * Browser profile metadata. + */ + profile?: Profile; } export interface BrowserRetrieveResponse { @@ -230,6 +265,11 @@ export interface BrowserRetrieveResponse { * Optional persistence configuration for the browser session. */ persistence?: BrowserPersistence; + + /** + * Browser profile metadata. + */ + profile?: Profile; } export type BrowserListResponse = Array; @@ -276,6 +316,11 @@ export namespace BrowserListResponse { * Optional persistence configuration for the browser session. */ persistence?: BrowsersAPI.BrowserPersistence; + + /** + * Browser profile metadata. + */ + profile?: BrowsersAPI.Profile; } } @@ -296,6 +341,13 @@ export interface BrowserCreateParams { */ persistence?: BrowserPersistence; + /** + * Profile selection for the browser session. Provide either id or name. If + * specified, the matching profile will be loaded into the browser session. + * Profiles must be created beforehand. + */ + profile?: BrowserCreateParams.Profile; + /** * If true, launches the browser in stealth mode to reduce detection by anti-bot * mechanisms. @@ -310,6 +362,32 @@ export interface BrowserCreateParams { timeout_seconds?: number; } +export namespace BrowserCreateParams { + /** + * Profile selection for the browser session. Provide either id or name. If + * specified, the matching profile will be loaded into the browser session. + * Profiles must be created beforehand. + */ + export interface Profile { + /** + * Profile ID to load for this browser session + */ + id?: string; + + /** + * Profile name to load for this browser session (instead of id). Must be 1-255 + * characters, using letters, numbers, dots, underscores, or hyphens. + */ + name?: string; + + /** + * If true, save changes made during the session back to the profile when the + * session ends. + */ + save_changes?: boolean; + } +} + export interface BrowserDeleteParams { /** * Persistent browser identifier @@ -325,6 +403,7 @@ Browsers.Logs = Logs; export declare namespace Browsers { export { type BrowserPersistence as BrowserPersistence, + type Profile as Profile, type BrowserCreateResponse as BrowserCreateResponse, type BrowserRetrieveResponse as BrowserRetrieveResponse, type BrowserListResponse as BrowserListResponse, diff --git a/src/resources/browsers/index.ts b/src/resources/browsers/index.ts index 3437de12..bcd5b403 100644 --- a/src/resources/browsers/index.ts +++ b/src/resources/browsers/index.ts @@ -3,6 +3,7 @@ export { Browsers, type BrowserPersistence, + type Profile, type BrowserCreateResponse, type BrowserRetrieveResponse, type BrowserListResponse, diff --git a/src/resources/index.ts b/src/resources/index.ts index a368fedb..6b0e380a 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -5,6 +5,7 @@ export { Apps, type AppListResponse, type AppListParams } from './apps'; export { Browsers, type BrowserPersistence, + type Profile, type BrowserCreateResponse, type BrowserRetrieveResponse, type BrowserListResponse, @@ -32,3 +33,4 @@ export { type InvocationCreateParams, type InvocationUpdateParams, } from './invocations'; +export { Profiles, type ProfileListResponse, type ProfileCreateParams } from './profiles'; diff --git a/src/resources/profiles.ts b/src/resources/profiles.ts new file mode 100644 index 00000000..774f7641 --- /dev/null +++ b/src/resources/profiles.ts @@ -0,0 +1,67 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../core/resource'; +import * as BrowsersAPI from './browsers/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 Profiles extends APIResource { + /** + * Create a browser profile that can be used to load state into future browser + * sessions. + */ + create(body: ProfileCreateParams, options?: RequestOptions): APIPromise { + return this._client.post('/profiles', { body, ...options }); + } + + /** + * Retrieve details for a single profile by its ID or name. + */ + retrieve(idOrName: string, options?: RequestOptions): APIPromise { + return this._client.get(path`/profiles/${idOrName}`, options); + } + + /** + * List profiles with optional filtering and pagination. + */ + list(options?: RequestOptions): APIPromise { + return this._client.get('/profiles', options); + } + + /** + * Delete a profile by its ID or by its name. + */ + delete(idOrName: string, options?: RequestOptions): APIPromise { + return this._client.delete(path`/profiles/${idOrName}`, { + ...options, + headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), + }); + } + + /** + * Download the profile. Profiles are JSON files containing the pieces of state + * that we save. + */ + download(idOrName: string, options?: RequestOptions): APIPromise { + return this._client.get(path`/profiles/${idOrName}/download`, { + ...options, + headers: buildHeaders([{ Accept: 'application/octet-stream' }, options?.headers]), + __binaryResponse: true, + }); + } +} + +export type ProfileListResponse = Array; + +export interface ProfileCreateParams { + /** + * Optional name of the profile. Must be unique within the organization. + */ + name?: string; +} + +export declare namespace Profiles { + export { type ProfileListResponse as ProfileListResponse, type ProfileCreateParams as ProfileCreateParams }; +} diff --git a/tests/api-resources/browsers/browsers.test.ts b/tests/api-resources/browsers/browsers.test.ts index 7685e689..5d360af4 100644 --- a/tests/api-resources/browsers/browsers.test.ts +++ b/tests/api-resources/browsers/browsers.test.ts @@ -29,6 +29,7 @@ describe('resource browsers', () => { headless: false, invocation_id: 'rr33xuugxj9h0bkf1rdt2bet', persistence: { id: 'my-awesome-browser-for-user-1234' }, + profile: { id: 'id', name: 'name', save_changes: true }, stealth: true, timeout_seconds: 0, }, diff --git a/tests/api-resources/profiles.test.ts b/tests/api-resources/profiles.test.ts new file mode 100644 index 00000000..9fe686a5 --- /dev/null +++ b/tests/api-resources/profiles.test.ts @@ -0,0 +1,58 @@ +// 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 profiles', () => { + // Prism tests are disabled + test.skip('create', async () => { + const responsePromise = client.profiles.create({}); + 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); + }); + + // Prism tests are disabled + test.skip('retrieve', async () => { + const responsePromise = client.profiles.retrieve('id_or_name'); + 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); + }); + + // Prism tests are disabled + test.skip('list', async () => { + const responsePromise = client.profiles.list(); + 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); + }); + + // Prism tests are disabled + test.skip('delete', async () => { + const responsePromise = client.profiles.delete('id_or_name'); + 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); + }); +}); From 0e88fd6311276421b5de3866065d96dedfef58e6 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 4 Sep 2025 15:18:38 +0000 Subject: [PATCH 152/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 7d9b009d..78e7f271 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.10.0" + ".": "0.11.0" } diff --git a/package.json b/package.json index af5ef848..75126b48 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.10.0", + "version": "0.11.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index c2e5b969..9085e9de 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.10.0'; // x-release-please-version +export const VERSION = '0.11.0'; // x-release-please-version From 12b3a3dead4b1779e6d3836bd771258fdd9d8245 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 5 Sep 2025 15:17:09 +0000 Subject: [PATCH 153/551] feat(api): add pagination to the deployments endpoint --- .stats.yml | 6 +- README.md | 31 +++++ api.md | 2 +- src/client.ts | 29 +++++ src/core/pagination.ts | 153 ++++++++++++++++++++++++ src/index.ts | 1 + src/pagination.ts | 2 + src/resources/deployments.ts | 96 ++++++++------- src/resources/index.ts | 1 + tests/api-resources/deployments.test.ts | 11 +- 10 files changed, 277 insertions(+), 55 deletions(-) create mode 100644 src/core/pagination.ts create mode 100644 src/pagination.ts diff --git a/.stats.yml b/.stats.yml index 6ac19baf..8943c2f3 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 46 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-e98d46c55826cdf541a9ee0df04ce92806ac6d4d92957ae79f897270b7d85b23.yml -openapi_spec_hash: 8a1af54fc0a4417165b8a52e6354b685 -config_hash: 043ddc54629c6d8b889123770cb4769f +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-33f1feaba7bde46bfa36d2fefb5c3bc9512967945bccf78045ad3f64aafc4eb0.yml +openapi_spec_hash: 52a448889d41216d1ca30e8a57115b14 +config_hash: 1f28d5c3c063f418ebd2799df1e4e781 diff --git a/README.md b/README.md index 98f3d75b..fa69c0cb 100644 --- a/README.md +++ b/README.md @@ -168,6 +168,37 @@ On timeout, an `APIConnectionTimeoutError` is thrown. Note that requests which time out will be [retried twice by default](#retries). +## Auto-pagination + +List methods in the Kernel API are paginated. +You can use the `for await … of` syntax to iterate through items across all pages: + +```ts +async function fetchAllDeploymentListResponses(params) { + const allDeploymentListResponses = []; + // Automatically fetches more pages as needed. + for await (const deploymentListResponse of client.deployments.list({ app_name: 'YOUR_APP', limit: 2 })) { + allDeploymentListResponses.push(deploymentListResponse); + } + return allDeploymentListResponses; +} +``` + +Alternatively, you can request a single page at a time: + +```ts +let page = await client.deployments.list({ app_name: 'YOUR_APP', limit: 2 }); +for (const deploymentListResponse of page.items) { + console.log(deploymentListResponse); +} + +// Convenience methods are provided for manually paginating: +while (page.hasNextPage()) { + page = await page.getNextPage(); + // ... +} +``` + ## Advanced Usage ### Accessing raw Response data (e.g., headers) diff --git a/api.md b/api.md index 4c61dfb9..86d03479 100644 --- a/api.md +++ b/api.md @@ -23,7 +23,7 @@ Methods: - client.deployments.create({ ...params }) -> DeploymentCreateResponse - client.deployments.retrieve(id) -> DeploymentRetrieveResponse -- client.deployments.list({ ...params }) -> DeploymentListResponse +- client.deployments.list({ ...params }) -> DeploymentListResponsesOffsetPagination - client.deployments.follow(id, { ...params }) -> DeploymentFollowResponse # Apps diff --git a/src/client.ts b/src/client.ts index 97b5ded3..e5208698 100644 --- a/src/client.ts +++ b/src/client.ts @@ -13,6 +13,8 @@ import * as Shims from './internal/shims'; import * as Opts from './internal/request-options'; import { VERSION } from './version'; import * as Errors from './core/error'; +import * as Pagination from './core/pagination'; +import { AbstractPage, type OffsetPaginationParams, OffsetPaginationResponse } from './core/pagination'; import * as Uploads from './core/uploads'; import * as API from './resources/index'; import { APIPromise } from './core/api-promise'; @@ -24,6 +26,7 @@ import { DeploymentFollowResponse, DeploymentListParams, DeploymentListResponse, + DeploymentListResponsesOffsetPagination, DeploymentRetrieveResponse, DeploymentStateEvent, Deployments, @@ -538,6 +541,25 @@ export class Kernel { return { response, options, controller, requestLogID, retryOfRequestLogID, startTime }; } + getAPIList = Pagination.AbstractPage>( + path: string, + Page: new (...args: any[]) => PageClass, + opts?: RequestOptions, + ): Pagination.PagePromise { + return this.requestAPIList(Page, { method: 'get', path, ...opts }); + } + + requestAPIList< + Item = unknown, + PageClass extends Pagination.AbstractPage = Pagination.AbstractPage, + >( + Page: new (...args: ConstructorParameters) => PageClass, + options: FinalRequestOptions, + ): Pagination.PagePromise { + const request = this.makeRequest(options, null, undefined); + return new Pagination.PagePromise(this as any as Kernel, request, Page); + } + async fetchWithTimeout( url: RequestInfo, init: RequestInit | undefined, @@ -786,6 +808,12 @@ Kernel.Profiles = Profiles; export declare namespace Kernel { export type RequestOptions = Opts.RequestOptions; + export import OffsetPagination = Pagination.OffsetPagination; + export { + type OffsetPaginationParams as OffsetPaginationParams, + type OffsetPaginationResponse as OffsetPaginationResponse, + }; + export { Deployments as Deployments, type DeploymentStateEvent as DeploymentStateEvent, @@ -793,6 +821,7 @@ export declare namespace Kernel { type DeploymentRetrieveResponse as DeploymentRetrieveResponse, type DeploymentListResponse as DeploymentListResponse, type DeploymentFollowResponse as DeploymentFollowResponse, + type DeploymentListResponsesOffsetPagination as DeploymentListResponsesOffsetPagination, type DeploymentCreateParams as DeploymentCreateParams, type DeploymentListParams as DeploymentListParams, type DeploymentFollowParams as DeploymentFollowParams, diff --git a/src/core/pagination.ts b/src/core/pagination.ts new file mode 100644 index 00000000..afa83307 --- /dev/null +++ b/src/core/pagination.ts @@ -0,0 +1,153 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { KernelError } from './error'; +import { FinalRequestOptions } from '../internal/request-options'; +import { defaultParseResponse } from '../internal/parse'; +import { type Kernel } from '../client'; +import { APIPromise } from './api-promise'; +import { type APIResponseProps } from '../internal/parse'; +import { maybeObj } from '../internal/utils/values'; + +export type PageRequestOptions = Pick; + +export abstract class AbstractPage implements AsyncIterable { + #client: Kernel; + protected options: FinalRequestOptions; + + protected response: Response; + protected body: unknown; + + constructor(client: Kernel, response: Response, body: unknown, options: FinalRequestOptions) { + this.#client = client; + this.options = options; + this.response = response; + this.body = body; + } + + abstract nextPageRequestOptions(): PageRequestOptions | null; + + abstract getPaginatedItems(): Item[]; + + hasNextPage(): boolean { + const items = this.getPaginatedItems(); + if (!items.length) return false; + return this.nextPageRequestOptions() != null; + } + + async getNextPage(): Promise { + const nextOptions = this.nextPageRequestOptions(); + if (!nextOptions) { + throw new KernelError( + 'No next page expected; please check `.hasNextPage()` before calling `.getNextPage()`.', + ); + } + + return await this.#client.requestAPIList(this.constructor as any, nextOptions); + } + + async *iterPages(): AsyncGenerator { + let page: this = this; + yield page; + while (page.hasNextPage()) { + page = await page.getNextPage(); + yield page; + } + } + + async *[Symbol.asyncIterator](): AsyncGenerator { + for await (const page of this.iterPages()) { + for (const item of page.getPaginatedItems()) { + yield item; + } + } + } +} + +/** + * This subclass of Promise will resolve to an instantiated Page once the request completes. + * + * It also implements AsyncIterable to allow auto-paginating iteration on an unawaited list call, eg: + * + * for await (const item of client.items.list()) { + * console.log(item) + * } + */ +export class PagePromise< + PageClass extends AbstractPage, + Item = ReturnType[number], + > + extends APIPromise + implements AsyncIterable +{ + constructor( + client: Kernel, + request: Promise, + Page: new (...args: ConstructorParameters) => PageClass, + ) { + super( + client, + request, + async (client, props) => + new Page(client, props.response, await defaultParseResponse(client, props), props.options), + ); + } + + /** + * Allow auto-paginating iteration on an unawaited list call, eg: + * + * for await (const item of client.items.list()) { + * console.log(item) + * } + */ + async *[Symbol.asyncIterator](): AsyncGenerator { + const page = await this; + for await (const item of page) { + yield item; + } + } +} + +export type OffsetPaginationResponse = Item[]; + +export interface OffsetPaginationParams { + offset?: number; + + limit?: number; +} + +export class OffsetPagination extends AbstractPage { + items: Array; + + constructor( + client: Kernel, + response: Response, + body: OffsetPaginationResponse, + options: FinalRequestOptions, + ) { + super(client, response, body, options); + + this.items = body || []; + } + + getPaginatedItems(): Item[] { + return this.items ?? []; + } + + nextPageRequestOptions(): PageRequestOptions | null { + const offset = (this.options.query as OffsetPaginationParams).offset ?? 0; + if (!offset) { + return null; + } + + const length = this.getPaginatedItems().length; + const currentCount = offset + length; + + return { + ...this.options, + query: { + ...maybeObj(this.options.query), + offset: currentCount, + }, + }; + } +} diff --git a/src/index.ts b/src/index.ts index 114bf2c3..b7901867 100644 --- a/src/index.ts +++ b/src/index.ts @@ -5,6 +5,7 @@ export { Kernel as default } from './client'; export { type Uploadable, toFile } from './core/uploads'; export { APIPromise } from './core/api-promise'; export { Kernel, type ClientOptions } from './client'; +export { PagePromise } from './core/pagination'; export { KernelError, APIError, diff --git a/src/pagination.ts b/src/pagination.ts new file mode 100644 index 00000000..90bf015e --- /dev/null +++ b/src/pagination.ts @@ -0,0 +1,2 @@ +/** @deprecated Import from ./core/pagination instead */ +export * from './core/pagination'; diff --git a/src/resources/deployments.ts b/src/resources/deployments.ts index 6cb5672e..225c7943 100644 --- a/src/resources/deployments.ts +++ b/src/resources/deployments.ts @@ -3,6 +3,7 @@ import { APIResource } from '../core/resource'; import * as Shared from './shared'; import { APIPromise } from '../core/api-promise'; +import { OffsetPagination, type OffsetPaginationParams, PagePromise } from '../core/pagination'; import { Stream } from '../core/streaming'; import { type Uploadable } from '../core/uploads'; import { buildHeaders } from '../internal/headers'; @@ -43,14 +44,22 @@ export class Deployments extends APIResource { * * @example * ```ts - * const deployments = await client.deployments.list(); + * // Automatically fetches more pages as needed. + * for await (const deploymentListResponse of client.deployments.list( + * { app_name: 'app_name' }, + * )) { + * // ... + * } * ``` */ list( - query: DeploymentListParams | null | undefined = {}, + query: DeploymentListParams, options?: RequestOptions, - ): APIPromise { - return this._client.get('/deployments', { query, ...options }); + ): PagePromise { + return this._client.getAPIList('/deployments', OffsetPagination, { + query, + ...options, + }); } /** @@ -77,6 +86,8 @@ export class Deployments extends APIResource { } } +export type DeploymentListResponsesOffsetPagination = OffsetPagination; + /** * An event representing the current state of a deployment. */ @@ -234,53 +245,49 @@ export interface DeploymentRetrieveResponse { updated_at?: string | null; } -export type DeploymentListResponse = Array; - -export namespace DeploymentListResponse { +/** + * Deployment record information. + */ +export interface DeploymentListResponse { /** - * Deployment record information. + * Unique identifier for the deployment */ - export interface DeploymentListResponseItem { - /** - * Unique identifier for the deployment - */ - id: string; + id: string; - /** - * Timestamp when the deployment was created - */ - created_at: string; + /** + * Timestamp when the deployment was created + */ + created_at: string; - /** - * Deployment region code - */ - region: 'aws.us-east-1a'; + /** + * Deployment region code + */ + region: 'aws.us-east-1a'; - /** - * Current status of the deployment - */ - status: 'queued' | 'in_progress' | 'running' | 'failed' | 'stopped'; + /** + * Current status of the deployment + */ + status: 'queued' | 'in_progress' | 'running' | 'failed' | 'stopped'; - /** - * Relative path to the application entrypoint - */ - entrypoint_rel_path?: string; + /** + * Relative path to the application entrypoint + */ + entrypoint_rel_path?: string; - /** - * Environment variables configured for this deployment - */ - env_vars?: { [key: string]: string }; + /** + * Environment variables configured for this deployment + */ + env_vars?: { [key: string]: string }; - /** - * Status reason - */ - status_reason?: string; + /** + * Status reason + */ + status_reason?: string; - /** - * Timestamp when the deployment was last updated - */ - updated_at?: string | null; - } + /** + * Timestamp when the deployment was last updated + */ + updated_at?: string | null; } /** @@ -373,11 +380,11 @@ export interface DeploymentCreateParams { version?: string; } -export interface DeploymentListParams { +export interface DeploymentListParams extends OffsetPaginationParams { /** * Filter results by application name. */ - app_name?: string; + app_name: string; } export interface DeploymentFollowParams { @@ -394,6 +401,7 @@ export declare namespace Deployments { type DeploymentRetrieveResponse as DeploymentRetrieveResponse, type DeploymentListResponse as DeploymentListResponse, type DeploymentFollowResponse as DeploymentFollowResponse, + type DeploymentListResponsesOffsetPagination as DeploymentListResponsesOffsetPagination, type DeploymentCreateParams as DeploymentCreateParams, type DeploymentListParams as DeploymentListParams, type DeploymentFollowParams as DeploymentFollowParams, diff --git a/src/resources/index.ts b/src/resources/index.ts index 6b0e380a..6482d4fc 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -22,6 +22,7 @@ export { type DeploymentCreateParams, type DeploymentListParams, type DeploymentFollowParams, + type DeploymentListResponsesOffsetPagination, } from './deployments'; export { Invocations, diff --git a/tests/api-resources/deployments.test.ts b/tests/api-resources/deployments.test.ts index 289fe0c6..517dc9db 100644 --- a/tests/api-resources/deployments.test.ts +++ b/tests/api-resources/deployments.test.ts @@ -48,8 +48,8 @@ describe('resource deployments', () => { }); // Prism tests are disabled - test.skip('list', async () => { - const responsePromise = client.deployments.list(); + test.skip('list: only required params', async () => { + const responsePromise = client.deployments.list({ app_name: 'app_name' }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -60,11 +60,8 @@ describe('resource deployments', () => { }); // Prism tests are disabled - test.skip('list: 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.deployments.list({ app_name: 'app_name' }, { path: '/_stainless_unknown_path' }), - ).rejects.toThrow(Kernel.NotFoundError); + test.skip('list: required and optional params', async () => { + const response = await client.deployments.list({ app_name: 'app_name', limit: 1, offset: 0 }); }); // Prism doesn't support text/event-stream responses From 68267ae907dce3a1a90e229bf50c631353e75911 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 5 Sep 2025 15:19:46 +0000 Subject: [PATCH 154/551] feat(api): update API spec with pagination headers --- .stats.yml | 4 ++-- src/resources/deployments.ts | 8 +++----- tests/api-resources/deployments.test.ts | 14 ++++++++++---- 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/.stats.yml b/.stats.yml index 8943c2f3..9635bb22 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 46 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-33f1feaba7bde46bfa36d2fefb5c3bc9512967945bccf78045ad3f64aafc4eb0.yml -openapi_spec_hash: 52a448889d41216d1ca30e8a57115b14 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-cb38560915edce03abce2ae3ef5bc745489dbe9b6f80c2b4ff42edf8c2ff276d.yml +openapi_spec_hash: a869194d6c864ba28d79ec0105439c3e config_hash: 1f28d5c3c063f418ebd2799df1e4e781 diff --git a/src/resources/deployments.ts b/src/resources/deployments.ts index 225c7943..b9dfe5a0 100644 --- a/src/resources/deployments.ts +++ b/src/resources/deployments.ts @@ -45,15 +45,13 @@ export class Deployments extends APIResource { * @example * ```ts * // Automatically fetches more pages as needed. - * for await (const deploymentListResponse of client.deployments.list( - * { app_name: 'app_name' }, - * )) { + * for await (const deploymentListResponse of client.deployments.list()) { * // ... * } * ``` */ list( - query: DeploymentListParams, + query: DeploymentListParams | null | undefined = {}, options?: RequestOptions, ): PagePromise { return this._client.getAPIList('/deployments', OffsetPagination, { @@ -384,7 +382,7 @@ export interface DeploymentListParams extends OffsetPaginationParams { /** * Filter results by application name. */ - app_name: string; + app_name?: string; } export interface DeploymentFollowParams { diff --git a/tests/api-resources/deployments.test.ts b/tests/api-resources/deployments.test.ts index 517dc9db..80f430f2 100644 --- a/tests/api-resources/deployments.test.ts +++ b/tests/api-resources/deployments.test.ts @@ -48,8 +48,8 @@ describe('resource deployments', () => { }); // Prism tests are disabled - test.skip('list: only required params', async () => { - const responsePromise = client.deployments.list({ app_name: 'app_name' }); + test.skip('list', async () => { + const responsePromise = client.deployments.list(); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -60,8 +60,14 @@ describe('resource deployments', () => { }); // Prism tests are disabled - test.skip('list: required and optional params', async () => { - const response = await client.deployments.list({ app_name: 'app_name', limit: 1, offset: 0 }); + test.skip('list: 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.deployments.list( + { app_name: 'app_name', limit: 1, offset: 0 }, + { path: '/_stainless_unknown_path' }, + ), + ).rejects.toThrow(Kernel.NotFoundError); }); // Prism doesn't support text/event-stream responses From 2f107a14fb506bd80c0d4cc09bcfa8a7ff1010b4 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 5 Sep 2025 18:00:42 +0000 Subject: [PATCH 155/551] feat(api): pagination properties added to response (has_more, next_offset) --- .stats.yml | 2 +- src/core/pagination.ts | 18 ++++++++++++++++-- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/.stats.yml b/.stats.yml index 9635bb22..7fb3d31e 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 46 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-cb38560915edce03abce2ae3ef5bc745489dbe9b6f80c2b4ff42edf8c2ff276d.yml openapi_spec_hash: a869194d6c864ba28d79ec0105439c3e -config_hash: 1f28d5c3c063f418ebd2799df1e4e781 +config_hash: ed56f95781ec9b2e73c97e1a66606071 diff --git a/src/core/pagination.ts b/src/core/pagination.ts index afa83307..c3266cdc 100644 --- a/src/core/pagination.ts +++ b/src/core/pagination.ts @@ -6,7 +6,7 @@ import { defaultParseResponse } from '../internal/parse'; import { type Kernel } from '../client'; import { APIPromise } from './api-promise'; import { type APIResponseProps } from '../internal/parse'; -import { maybeObj } from '../internal/utils/values'; +import { maybeCoerceBoolean, maybeCoerceInteger, maybeObj } from '../internal/utils/values'; export type PageRequestOptions = Pick; @@ -118,6 +118,10 @@ export interface OffsetPaginationParams { export class OffsetPagination extends AbstractPage { items: Array; + has_more: boolean | null; + + next_offset: number | null; + constructor( client: Kernel, response: Response, @@ -127,14 +131,24 @@ export class OffsetPagination extends AbstractPage { super(client, response, body, options); this.items = body || []; + this.has_more = maybeCoerceBoolean(this.response.headers.get('x-has-more')) ?? null; + this.next_offset = maybeCoerceInteger(this.response.headers.get('x-next-offset')) ?? null; } getPaginatedItems(): Item[] { return this.items ?? []; } + override hasNextPage(): boolean { + if (this.has_more === false) { + return false; + } + + return super.hasNextPage(); + } + nextPageRequestOptions(): PageRequestOptions | null { - const offset = (this.options.query as OffsetPaginationParams).offset ?? 0; + const offset = this.next_offset; if (!offset) { return null; } From 5c818ea07775d4ea727e3e8c9ec95d60e30bc5d8 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 6 Sep 2025 03:52:51 +0000 Subject: [PATCH 156/551] chore: ci build action --- scripts/utils/upload-artifact.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/utils/upload-artifact.sh b/scripts/utils/upload-artifact.sh index ab5947d6..38abeb4a 100755 --- a/scripts/utils/upload-artifact.sh +++ b/scripts/utils/upload-artifact.sh @@ -12,7 +12,7 @@ if [[ "$SIGNED_URL" == "null" ]]; then exit 1 fi -UPLOAD_RESPONSE=$(tar -cz "${BUILD_PATH:-dist}" | curl -v -X PUT \ +UPLOAD_RESPONSE=$(tar "${BASE_PATH:+-C$BASE_PATH}" -cz "${ARTIFACT_PATH:-dist}" | curl -v -X PUT \ -H "Content-Type: application/gzip" \ --data-binary @- "$SIGNED_URL" 2>&1) From 5f87915af1615b650ed5f82f61462149b12b9ab1 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 8 Sep 2025 18:57:07 +0000 Subject: [PATCH 157/551] fix: coerce nullable values to undefined --- src/internal/utils/values.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/internal/utils/values.ts b/src/internal/utils/values.ts index 667646d6..1fc2af6e 100644 --- a/src/internal/utils/values.ts +++ b/src/internal/utils/values.ts @@ -76,21 +76,21 @@ export const coerceBoolean = (value: unknown): boolean => { }; export const maybeCoerceInteger = (value: unknown): number | undefined => { - if (value === undefined) { + if (value == null) { return undefined; } return coerceInteger(value); }; export const maybeCoerceFloat = (value: unknown): number | undefined => { - if (value === undefined) { + if (value == null) { return undefined; } return coerceFloat(value); }; export const maybeCoerceBoolean = (value: unknown): boolean | undefined => { - if (value === undefined) { + if (value == null) { return undefined; } return coerceBoolean(value); From b5153797e9b48081d6ed7da13d6288f3ab95f07e Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 9 Sep 2025 15:53:49 +0000 Subject: [PATCH 158/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 78e7f271..ddfa3e36 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.11.0" + ".": "0.11.1" } diff --git a/package.json b/package.json index 75126b48..bae10178 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.11.0", + "version": "0.11.1", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 9085e9de..945825f9 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.11.0'; // x-release-please-version +export const VERSION = '0.11.1'; // x-release-please-version From aff9d90f6b3b61393726f7bb18b3c2b6d4456fd0 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 20 Sep 2025 03:02:18 +0000 Subject: [PATCH 159/551] chore: do not install brew dependencies in ./scripts/bootstrap by default --- scripts/bootstrap | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/scripts/bootstrap b/scripts/bootstrap index 062a0349..a8b69ff3 100755 --- a/scripts/bootstrap +++ b/scripts/bootstrap @@ -4,10 +4,18 @@ set -e cd "$(dirname "$0")/.." -if [ -f "Brewfile" ] && [ "$(uname -s)" = "Darwin" ] && [ "$SKIP_BREW" != "1" ]; then +if [ -f "Brewfile" ] && [ "$(uname -s)" = "Darwin" ] && [ "$SKIP_BREW" != "1" ] && [ -t 0 ]; then brew bundle check >/dev/null 2>&1 || { - echo "==> Installing Homebrew dependencies…" - brew bundle + echo -n "==> Install Homebrew dependencies? (y/N): " + read -r response + case "$response" in + [yY][eE][sS]|[yY]) + brew bundle + ;; + *) + ;; + esac + echo } fi From 54dd88510698b5e61b0ee184dd16834bd27200ee Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 24 Sep 2025 17:28:01 +0000 Subject: [PATCH 160/551] feat: Add stainless CI --- .stats.yml | 8 +- api.md | 15 + src/client.ts | 17 + src/resources/browsers/browsers.ts | 11 +- src/resources/index.ts | 7 + src/resources/invocations.ts | 3 +- src/resources/proxies.ts | 876 ++++++++++++++++++ tests/api-resources/browsers/browsers.test.ts | 3 +- tests/api-resources/proxies.test.ts | 67 ++ 9 files changed, 1000 insertions(+), 7 deletions(-) create mode 100644 src/resources/proxies.ts create mode 100644 tests/api-resources/proxies.test.ts diff --git a/.stats.yml b/.stats.yml index 7fb3d31e..385372f3 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 46 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-cb38560915edce03abce2ae3ef5bc745489dbe9b6f80c2b4ff42edf8c2ff276d.yml -openapi_spec_hash: a869194d6c864ba28d79ec0105439c3e -config_hash: ed56f95781ec9b2e73c97e1a66606071 +configured_endpoints: 50 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-d3a597bbbb25c131e2c06eb9b47d70932d14a97a6f916677a195a128e196f4db.yml +openapi_spec_hash: c967b384624017eed0abff1b53a74530 +config_hash: 0d150b61cae2dc57d3648ceae7784966 diff --git a/api.md b/api.md index 86d03479..7c4d2d72 100644 --- a/api.md +++ b/api.md @@ -160,3 +160,18 @@ Methods: - client.profiles.list() -> ProfileListResponse - client.profiles.delete(idOrName) -> void - client.profiles.download(idOrName) -> Response + +# Proxies + +Types: + +- ProxyCreateResponse +- ProxyRetrieveResponse +- ProxyListResponse + +Methods: + +- client.proxies.create({ ...params }) -> ProxyCreateResponse +- client.proxies.retrieve(id) -> ProxyRetrieveResponse +- client.proxies.list() -> ProxyListResponse +- client.proxies.delete(id) -> void diff --git a/src/client.ts b/src/client.ts index e5208698..f1460675 100644 --- a/src/client.ts +++ b/src/client.ts @@ -42,6 +42,13 @@ import { Invocations, } from './resources/invocations'; import { ProfileCreateParams, ProfileListResponse, Profiles } from './resources/profiles'; +import { + Proxies, + ProxyCreateParams, + ProxyCreateResponse, + ProxyListResponse, + ProxyRetrieveResponse, +} from './resources/proxies'; import { BrowserCreateParams, BrowserCreateResponse, @@ -797,6 +804,7 @@ export class Kernel { invocations: API.Invocations = new API.Invocations(this); browsers: API.Browsers = new API.Browsers(this); profiles: API.Profiles = new API.Profiles(this); + proxies: API.Proxies = new API.Proxies(this); } Kernel.Deployments = Deployments; @@ -804,6 +812,7 @@ Kernel.Apps = Apps; Kernel.Invocations = Invocations; Kernel.Browsers = Browsers; Kernel.Profiles = Profiles; +Kernel.Proxies = Proxies; export declare namespace Kernel { export type RequestOptions = Opts.RequestOptions; @@ -857,6 +866,14 @@ export declare namespace Kernel { type ProfileCreateParams as ProfileCreateParams, }; + export { + Proxies as Proxies, + type ProxyCreateResponse as ProxyCreateResponse, + type ProxyRetrieveResponse as ProxyRetrieveResponse, + type ProxyListResponse as ProxyListResponse, + type ProxyCreateParams as ProxyCreateParams, + }; + export type AppAction = API.AppAction; export type ErrorDetail = API.ErrorDetail; export type ErrorEvent = API.ErrorEvent; diff --git a/src/resources/browsers/browsers.ts b/src/resources/browsers/browsers.ts index 5cc34155..5f70d049 100644 --- a/src/resources/browsers/browsers.ts +++ b/src/resources/browsers/browsers.ts @@ -348,6 +348,12 @@ export interface BrowserCreateParams { */ profile?: BrowserCreateParams.Profile; + /** + * Optional proxy to associate to the browser session. Must reference a proxy + * belonging to the caller's org. + */ + proxy_id?: string; + /** * If true, launches the browser in stealth mode to reduce detection by anti-bot * mechanisms. @@ -357,7 +363,10 @@ export interface BrowserCreateParams { /** * The number of seconds of inactivity before the browser session is terminated. * Only applicable to non-persistent browsers. Activity includes CDP connections - * and live view connections. Defaults to 60 seconds. + * and live view connections. Defaults to 60 seconds. Minimum allowed is 10 + * seconds. Maximum allowed is 86400 (24 hours). We check for inactivity every 5 + * seconds, so the actual timeout behavior you will see is +/- 5 seconds around the + * specified value. */ timeout_seconds?: number; } diff --git a/src/resources/index.ts b/src/resources/index.ts index 6482d4fc..96c91377 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -35,3 +35,10 @@ export { type InvocationUpdateParams, } from './invocations'; export { Profiles, type ProfileListResponse, type ProfileCreateParams } from './profiles'; +export { + Proxies, + type ProxyCreateResponse, + type ProxyRetrieveResponse, + type ProxyListResponse, + type ProxyCreateParams, +} from './proxies'; diff --git a/src/resources/invocations.ts b/src/resources/invocations.ts index 89bc359c..6ff470a8 100644 --- a/src/resources/invocations.ts +++ b/src/resources/invocations.ts @@ -40,7 +40,8 @@ export class Invocations extends APIResource { } /** - * Update an invocation's status or output. + * Update an invocation's status or output. This can used to cancel an invocation + * by setting the status to "failed". * * @example * ```ts diff --git a/src/resources/proxies.ts b/src/resources/proxies.ts new file mode 100644 index 00000000..20ceea6b --- /dev/null +++ b/src/resources/proxies.ts @@ -0,0 +1,876 @@ +// 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 Proxies extends APIResource { + /** + * Create a new proxy configuration for the caller's organization. + */ + create(body: ProxyCreateParams, options?: RequestOptions): APIPromise { + return this._client.post('/proxies', { body, ...options }); + } + + /** + * Retrieve a proxy belonging to the caller's organization by ID. + */ + retrieve(id: string, options?: RequestOptions): APIPromise { + return this._client.get(path`/proxies/${id}`, options); + } + + /** + * List proxies owned by the caller's organization. + */ + list(options?: RequestOptions): APIPromise { + return this._client.get('/proxies', options); + } + + /** + * Soft delete a proxy. Sessions referencing it are not modified. + */ + delete(id: string, options?: RequestOptions): APIPromise { + return this._client.delete(path`/proxies/${id}`, { + ...options, + headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), + }); + } +} + +/** + * Configuration for routing traffic through a proxy. + */ +export interface ProxyCreateResponse { + /** + * Proxy type to use. In terms of quality for avoiding bot-detection, from best to + * worst: `mobile` > `residential` > `isp` > `datacenter`. + */ + type: 'datacenter' | 'isp' | 'residential' | 'mobile' | 'custom'; + + id?: string; + + /** + * Configuration specific to the selected proxy `type`. + */ + config?: + | ProxyCreateResponse.DatacenterProxyConfig + | ProxyCreateResponse.IspProxyConfig + | ProxyCreateResponse.ResidentialProxyConfig + | ProxyCreateResponse.MobileProxyConfig + | ProxyCreateResponse.CustomProxyConfig; + + /** + * Readable name of the proxy. + */ + name?: string; +} + +export namespace ProxyCreateResponse { + /** + * Configuration for a datacenter proxy. + */ + export interface DatacenterProxyConfig { + /** + * ISO 3166 country code or EU for the proxy exit node. + */ + country: string; + } + + /** + * Configuration for an ISP proxy. + */ + export interface IspProxyConfig { + /** + * ISO 3166 country code or EU for the proxy exit node. + */ + country: string; + } + + /** + * Configuration for residential proxies. + */ + export interface ResidentialProxyConfig { + /** + * Autonomous system number. See https://bgp.potaroo.net/cidr/autnums.html + */ + asn?: string; + + /** + * City name (no spaces, e.g. `sanfrancisco`). If provided, `country` must also be + * provided. + */ + city?: string; + + /** + * ISO 3166 country code or EU for the proxy exit node. Required if `city` is + * provided. + */ + country?: string; + + /** + * Operating system of the residential device. + */ + os?: 'windows' | 'macos' | 'android'; + + /** + * Two-letter state code. + */ + state?: string; + + /** + * US ZIP code. + */ + zip?: string; + } + + /** + * Configuration for mobile proxies. + */ + export interface MobileProxyConfig { + /** + * Autonomous system number. See https://bgp.potaroo.net/cidr/autnums.html + */ + asn?: string; + + /** + * Mobile carrier. + */ + carrier?: + | 'a1' + | 'aircel' + | 'airtel' + | 'att' + | 'celcom' + | 'chinamobile' + | 'claro' + | 'comcast' + | 'cox' + | 'digi' + | 'dt' + | 'docomo' + | 'dtac' + | 'etisalat' + | 'idea' + | 'kyivstar' + | 'meo' + | 'megafon' + | 'mtn' + | 'mtnza' + | 'mts' + | 'optus' + | 'orange' + | 'qwest' + | 'reliance_jio' + | 'robi' + | 'sprint' + | 'telefonica' + | 'telstra' + | 'tmobile' + | 'tigo' + | 'tim' + | 'verizon' + | 'vimpelcom' + | 'vodacomza' + | 'vodafone' + | 'vivo' + | 'zain' + | 'vivabo' + | 'telenormyanmar' + | 'kcelljsc' + | 'swisscom' + | 'singtel' + | 'asiacell' + | 'windit' + | 'cellc' + | 'ooredoo' + | 'drei' + | 'umobile' + | 'cableone' + | 'proximus' + | 'tele2' + | 'mobitel' + | 'o2' + | 'bouygues' + | 'free' + | 'sfr' + | 'digicel'; + + /** + * City name (no spaces, e.g. `sanfrancisco`). If provided, `country` must also be + * provided. + */ + city?: string; + + /** + * ISO 3166 country code or EU for the proxy exit node. Required if `city` is + * provided. + */ + country?: string; + + /** + * Two-letter state code. + */ + state?: string; + + /** + * US ZIP code. + */ + zip?: string; + } + + /** + * Configuration for a custom proxy (e.g., private proxy server). + */ + export interface CustomProxyConfig { + /** + * Proxy host address or IP. + */ + host: string; + + /** + * Proxy port. + */ + port: number; + + /** + * Whether the proxy has a password. + */ + has_password?: boolean; + + /** + * Username for proxy authentication. + */ + username?: string; + } +} + +/** + * Configuration for routing traffic through a proxy. + */ +export interface ProxyRetrieveResponse { + /** + * Proxy type to use. In terms of quality for avoiding bot-detection, from best to + * worst: `mobile` > `residential` > `isp` > `datacenter`. + */ + type: 'datacenter' | 'isp' | 'residential' | 'mobile' | 'custom'; + + id?: string; + + /** + * Configuration specific to the selected proxy `type`. + */ + config?: + | ProxyRetrieveResponse.DatacenterProxyConfig + | ProxyRetrieveResponse.IspProxyConfig + | ProxyRetrieveResponse.ResidentialProxyConfig + | ProxyRetrieveResponse.MobileProxyConfig + | ProxyRetrieveResponse.CustomProxyConfig; + + /** + * Readable name of the proxy. + */ + name?: string; +} + +export namespace ProxyRetrieveResponse { + /** + * Configuration for a datacenter proxy. + */ + export interface DatacenterProxyConfig { + /** + * ISO 3166 country code or EU for the proxy exit node. + */ + country: string; + } + + /** + * Configuration for an ISP proxy. + */ + export interface IspProxyConfig { + /** + * ISO 3166 country code or EU for the proxy exit node. + */ + country: string; + } + + /** + * Configuration for residential proxies. + */ + export interface ResidentialProxyConfig { + /** + * Autonomous system number. See https://bgp.potaroo.net/cidr/autnums.html + */ + asn?: string; + + /** + * City name (no spaces, e.g. `sanfrancisco`). If provided, `country` must also be + * provided. + */ + city?: string; + + /** + * ISO 3166 country code or EU for the proxy exit node. Required if `city` is + * provided. + */ + country?: string; + + /** + * Operating system of the residential device. + */ + os?: 'windows' | 'macos' | 'android'; + + /** + * Two-letter state code. + */ + state?: string; + + /** + * US ZIP code. + */ + zip?: string; + } + + /** + * Configuration for mobile proxies. + */ + export interface MobileProxyConfig { + /** + * Autonomous system number. See https://bgp.potaroo.net/cidr/autnums.html + */ + asn?: string; + + /** + * Mobile carrier. + */ + carrier?: + | 'a1' + | 'aircel' + | 'airtel' + | 'att' + | 'celcom' + | 'chinamobile' + | 'claro' + | 'comcast' + | 'cox' + | 'digi' + | 'dt' + | 'docomo' + | 'dtac' + | 'etisalat' + | 'idea' + | 'kyivstar' + | 'meo' + | 'megafon' + | 'mtn' + | 'mtnza' + | 'mts' + | 'optus' + | 'orange' + | 'qwest' + | 'reliance_jio' + | 'robi' + | 'sprint' + | 'telefonica' + | 'telstra' + | 'tmobile' + | 'tigo' + | 'tim' + | 'verizon' + | 'vimpelcom' + | 'vodacomza' + | 'vodafone' + | 'vivo' + | 'zain' + | 'vivabo' + | 'telenormyanmar' + | 'kcelljsc' + | 'swisscom' + | 'singtel' + | 'asiacell' + | 'windit' + | 'cellc' + | 'ooredoo' + | 'drei' + | 'umobile' + | 'cableone' + | 'proximus' + | 'tele2' + | 'mobitel' + | 'o2' + | 'bouygues' + | 'free' + | 'sfr' + | 'digicel'; + + /** + * City name (no spaces, e.g. `sanfrancisco`). If provided, `country` must also be + * provided. + */ + city?: string; + + /** + * ISO 3166 country code or EU for the proxy exit node. Required if `city` is + * provided. + */ + country?: string; + + /** + * Two-letter state code. + */ + state?: string; + + /** + * US ZIP code. + */ + zip?: string; + } + + /** + * Configuration for a custom proxy (e.g., private proxy server). + */ + export interface CustomProxyConfig { + /** + * Proxy host address or IP. + */ + host: string; + + /** + * Proxy port. + */ + port: number; + + /** + * Whether the proxy has a password. + */ + has_password?: boolean; + + /** + * Username for proxy authentication. + */ + username?: string; + } +} + +export type ProxyListResponse = Array; + +export namespace ProxyListResponse { + /** + * Configuration for routing traffic through a proxy. + */ + export interface ProxyListResponseItem { + /** + * Proxy type to use. In terms of quality for avoiding bot-detection, from best to + * worst: `mobile` > `residential` > `isp` > `datacenter`. + */ + type: 'datacenter' | 'isp' | 'residential' | 'mobile' | 'custom'; + + id?: string; + + /** + * Configuration specific to the selected proxy `type`. + */ + config?: + | ProxyListResponseItem.DatacenterProxyConfig + | ProxyListResponseItem.IspProxyConfig + | ProxyListResponseItem.ResidentialProxyConfig + | ProxyListResponseItem.MobileProxyConfig + | ProxyListResponseItem.CustomProxyConfig; + + /** + * Readable name of the proxy. + */ + name?: string; + } + + export namespace ProxyListResponseItem { + /** + * Configuration for a datacenter proxy. + */ + export interface DatacenterProxyConfig { + /** + * ISO 3166 country code or EU for the proxy exit node. + */ + country: string; + } + + /** + * Configuration for an ISP proxy. + */ + export interface IspProxyConfig { + /** + * ISO 3166 country code or EU for the proxy exit node. + */ + country: string; + } + + /** + * Configuration for residential proxies. + */ + export interface ResidentialProxyConfig { + /** + * Autonomous system number. See https://bgp.potaroo.net/cidr/autnums.html + */ + asn?: string; + + /** + * City name (no spaces, e.g. `sanfrancisco`). If provided, `country` must also be + * provided. + */ + city?: string; + + /** + * ISO 3166 country code or EU for the proxy exit node. Required if `city` is + * provided. + */ + country?: string; + + /** + * Operating system of the residential device. + */ + os?: 'windows' | 'macos' | 'android'; + + /** + * Two-letter state code. + */ + state?: string; + + /** + * US ZIP code. + */ + zip?: string; + } + + /** + * Configuration for mobile proxies. + */ + export interface MobileProxyConfig { + /** + * Autonomous system number. See https://bgp.potaroo.net/cidr/autnums.html + */ + asn?: string; + + /** + * Mobile carrier. + */ + carrier?: + | 'a1' + | 'aircel' + | 'airtel' + | 'att' + | 'celcom' + | 'chinamobile' + | 'claro' + | 'comcast' + | 'cox' + | 'digi' + | 'dt' + | 'docomo' + | 'dtac' + | 'etisalat' + | 'idea' + | 'kyivstar' + | 'meo' + | 'megafon' + | 'mtn' + | 'mtnza' + | 'mts' + | 'optus' + | 'orange' + | 'qwest' + | 'reliance_jio' + | 'robi' + | 'sprint' + | 'telefonica' + | 'telstra' + | 'tmobile' + | 'tigo' + | 'tim' + | 'verizon' + | 'vimpelcom' + | 'vodacomza' + | 'vodafone' + | 'vivo' + | 'zain' + | 'vivabo' + | 'telenormyanmar' + | 'kcelljsc' + | 'swisscom' + | 'singtel' + | 'asiacell' + | 'windit' + | 'cellc' + | 'ooredoo' + | 'drei' + | 'umobile' + | 'cableone' + | 'proximus' + | 'tele2' + | 'mobitel' + | 'o2' + | 'bouygues' + | 'free' + | 'sfr' + | 'digicel'; + + /** + * City name (no spaces, e.g. `sanfrancisco`). If provided, `country` must also be + * provided. + */ + city?: string; + + /** + * ISO 3166 country code or EU for the proxy exit node. Required if `city` is + * provided. + */ + country?: string; + + /** + * Two-letter state code. + */ + state?: string; + + /** + * US ZIP code. + */ + zip?: string; + } + + /** + * Configuration for a custom proxy (e.g., private proxy server). + */ + export interface CustomProxyConfig { + /** + * Proxy host address or IP. + */ + host: string; + + /** + * Proxy port. + */ + port: number; + + /** + * Whether the proxy has a password. + */ + has_password?: boolean; + + /** + * Username for proxy authentication. + */ + username?: string; + } + } +} + +export interface ProxyCreateParams { + /** + * Proxy type to use. In terms of quality for avoiding bot-detection, from best to + * worst: `mobile` > `residential` > `isp` > `datacenter`. + */ + type: 'datacenter' | 'isp' | 'residential' | 'mobile' | 'custom'; + + /** + * Configuration specific to the selected proxy `type`. + */ + config?: + | ProxyCreateParams.DatacenterProxyConfig + | ProxyCreateParams.IspProxyConfig + | ProxyCreateParams.ResidentialProxyConfig + | ProxyCreateParams.MobileProxyConfig + | ProxyCreateParams.CreateCustomProxyConfig; + + /** + * Readable name of the proxy. + */ + name?: string; +} + +export namespace ProxyCreateParams { + /** + * Configuration for a datacenter proxy. + */ + export interface DatacenterProxyConfig { + /** + * ISO 3166 country code or EU for the proxy exit node. + */ + country: string; + } + + /** + * Configuration for an ISP proxy. + */ + export interface IspProxyConfig { + /** + * ISO 3166 country code or EU for the proxy exit node. + */ + country: string; + } + + /** + * Configuration for residential proxies. + */ + export interface ResidentialProxyConfig { + /** + * Autonomous system number. See https://bgp.potaroo.net/cidr/autnums.html + */ + asn?: string; + + /** + * City name (no spaces, e.g. `sanfrancisco`). If provided, `country` must also be + * provided. + */ + city?: string; + + /** + * ISO 3166 country code or EU for the proxy exit node. Required if `city` is + * provided. + */ + country?: string; + + /** + * Operating system of the residential device. + */ + os?: 'windows' | 'macos' | 'android'; + + /** + * Two-letter state code. + */ + state?: string; + + /** + * US ZIP code. + */ + zip?: string; + } + + /** + * Configuration for mobile proxies. + */ + export interface MobileProxyConfig { + /** + * Autonomous system number. See https://bgp.potaroo.net/cidr/autnums.html + */ + asn?: string; + + /** + * Mobile carrier. + */ + carrier?: + | 'a1' + | 'aircel' + | 'airtel' + | 'att' + | 'celcom' + | 'chinamobile' + | 'claro' + | 'comcast' + | 'cox' + | 'digi' + | 'dt' + | 'docomo' + | 'dtac' + | 'etisalat' + | 'idea' + | 'kyivstar' + | 'meo' + | 'megafon' + | 'mtn' + | 'mtnza' + | 'mts' + | 'optus' + | 'orange' + | 'qwest' + | 'reliance_jio' + | 'robi' + | 'sprint' + | 'telefonica' + | 'telstra' + | 'tmobile' + | 'tigo' + | 'tim' + | 'verizon' + | 'vimpelcom' + | 'vodacomza' + | 'vodafone' + | 'vivo' + | 'zain' + | 'vivabo' + | 'telenormyanmar' + | 'kcelljsc' + | 'swisscom' + | 'singtel' + | 'asiacell' + | 'windit' + | 'cellc' + | 'ooredoo' + | 'drei' + | 'umobile' + | 'cableone' + | 'proximus' + | 'tele2' + | 'mobitel' + | 'o2' + | 'bouygues' + | 'free' + | 'sfr' + | 'digicel'; + + /** + * City name (no spaces, e.g. `sanfrancisco`). If provided, `country` must also be + * provided. + */ + city?: string; + + /** + * ISO 3166 country code or EU for the proxy exit node. Required if `city` is + * provided. + */ + country?: string; + + /** + * Two-letter state code. + */ + state?: string; + + /** + * US ZIP code. + */ + zip?: string; + } + + /** + * Configuration for a custom proxy (e.g., private proxy server). + */ + export interface CreateCustomProxyConfig { + /** + * Proxy host address or IP. + */ + host: string; + + /** + * Proxy port. + */ + port: number; + + /** + * Password for proxy authentication. + */ + password?: string; + + /** + * Username for proxy authentication. + */ + username?: string; + } +} + +export declare namespace Proxies { + export { + type ProxyCreateResponse as ProxyCreateResponse, + type ProxyRetrieveResponse as ProxyRetrieveResponse, + type ProxyListResponse as ProxyListResponse, + type ProxyCreateParams as ProxyCreateParams, + }; +} diff --git a/tests/api-resources/browsers/browsers.test.ts b/tests/api-resources/browsers/browsers.test.ts index 5d360af4..3434e726 100644 --- a/tests/api-resources/browsers/browsers.test.ts +++ b/tests/api-resources/browsers/browsers.test.ts @@ -30,8 +30,9 @@ describe('resource browsers', () => { invocation_id: 'rr33xuugxj9h0bkf1rdt2bet', persistence: { id: 'my-awesome-browser-for-user-1234' }, profile: { id: 'id', name: 'name', save_changes: true }, + proxy_id: 'proxy_id', stealth: true, - timeout_seconds: 0, + timeout_seconds: 10, }, { path: '/_stainless_unknown_path' }, ), diff --git a/tests/api-resources/proxies.test.ts b/tests/api-resources/proxies.test.ts new file mode 100644 index 00000000..97087a29 --- /dev/null +++ b/tests/api-resources/proxies.test.ts @@ -0,0 +1,67 @@ +// 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 proxies', () => { + // Prism tests are disabled + test.skip('create: only required params', async () => { + const responsePromise = client.proxies.create({ type: 'datacenter' }); + 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); + }); + + // Prism tests are disabled + test.skip('create: required and optional params', async () => { + const response = await client.proxies.create({ + type: 'datacenter', + config: { country: 'US' }, + name: 'name', + }); + }); + + // Prism tests are disabled + test.skip('retrieve', async () => { + const responsePromise = client.proxies.retrieve('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); + }); + + // Prism tests are disabled + test.skip('list', async () => { + const responsePromise = client.proxies.list(); + 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); + }); + + // Prism tests are disabled + test.skip('delete', async () => { + const responsePromise = client.proxies.delete('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); + }); +}); From fae34f8945b3fee6a16f665ff078a9fc01b6aa44 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 24 Sep 2025 17:42:31 +0000 Subject: [PATCH 161/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index ddfa3e36..8ad7375d 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.11.1" + ".": "0.11.2" } diff --git a/package.json b/package.json index bae10178..f94a5315 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.11.1", + "version": "0.11.2", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 945825f9..b818b4ca 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.11.1'; // x-release-please-version +export const VERSION = '0.11.2'; // x-release-please-version From 53c0a40bb8de0793f656b7d1a2f3af458242a552 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 24 Sep 2025 20:29:47 +0000 Subject: [PATCH 162/551] feat: Per Invocation Logs --- .stats.yml | 4 ++-- api.md | 2 +- src/client.ts | 2 ++ src/resources/index.ts | 1 + src/resources/invocations.ts | 15 ++++++++++++++- tests/api-resources/invocations.test.ts | 12 ++++++++++++ 6 files changed, 32 insertions(+), 4 deletions(-) diff --git a/.stats.yml b/.stats.yml index 385372f3..4039b103 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 50 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-d3a597bbbb25c131e2c06eb9b47d70932d14a97a6f916677a195a128e196f4db.yml -openapi_spec_hash: c967b384624017eed0abff1b53a74530 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-5ee2116982adf46664acf84b8ba4b56ba65780983506c63d9b005dab49def757.yml +openapi_spec_hash: 42a3a519301d0e2bb2b5a71018915b55 config_hash: 0d150b61cae2dc57d3648ceae7784966 diff --git a/api.md b/api.md index 7c4d2d72..cbf98aac 100644 --- a/api.md +++ b/api.md @@ -52,7 +52,7 @@ Methods: - client.invocations.retrieve(id) -> InvocationRetrieveResponse - client.invocations.update(id, { ...params }) -> InvocationUpdateResponse - client.invocations.deleteBrowsers(id) -> void -- client.invocations.follow(id) -> InvocationFollowResponse +- client.invocations.follow(id, { ...params }) -> InvocationFollowResponse # Browsers diff --git a/src/client.ts b/src/client.ts index f1460675..376d277b 100644 --- a/src/client.ts +++ b/src/client.ts @@ -34,6 +34,7 @@ import { import { InvocationCreateParams, InvocationCreateResponse, + InvocationFollowParams, InvocationFollowResponse, InvocationRetrieveResponse, InvocationStateEvent, @@ -847,6 +848,7 @@ export declare namespace Kernel { type InvocationFollowResponse as InvocationFollowResponse, type InvocationCreateParams as InvocationCreateParams, type InvocationUpdateParams as InvocationUpdateParams, + type InvocationFollowParams as InvocationFollowParams, }; export { diff --git a/src/resources/index.ts b/src/resources/index.ts index 96c91377..3d63b756 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -33,6 +33,7 @@ export { type InvocationFollowResponse, type InvocationCreateParams, type InvocationUpdateParams, + type InvocationFollowParams, } from './invocations'; export { Profiles, type ProfileListResponse, type ProfileCreateParams } from './profiles'; export { diff --git a/src/resources/invocations.ts b/src/resources/invocations.ts index 6ff470a8..bc326309 100644 --- a/src/resources/invocations.ts +++ b/src/resources/invocations.ts @@ -83,8 +83,13 @@ export class Invocations extends APIResource { * const response = await client.invocations.follow('id'); * ``` */ - follow(id: string, options?: RequestOptions): APIPromise> { + follow( + id: string, + query: InvocationFollowParams | undefined = {}, + options?: RequestOptions, + ): APIPromise> { return this._client.get(path`/invocations/${id}/events`, { + query, ...options, headers: buildHeaders([{ Accept: 'text/event-stream' }, options?.headers]), stream: true, @@ -335,6 +340,13 @@ export interface InvocationUpdateParams { output?: string; } +export interface InvocationFollowParams { + /** + * Show logs since the given time (RFC timestamps or durations like 5m). + */ + since?: string; +} + export declare namespace Invocations { export { type InvocationStateEvent as InvocationStateEvent, @@ -344,5 +356,6 @@ export declare namespace Invocations { type InvocationFollowResponse as InvocationFollowResponse, type InvocationCreateParams as InvocationCreateParams, type InvocationUpdateParams as InvocationUpdateParams, + type InvocationFollowParams as InvocationFollowParams, }; } diff --git a/tests/api-resources/invocations.test.ts b/tests/api-resources/invocations.test.ts index baa3790e..309612ad 100644 --- a/tests/api-resources/invocations.test.ts +++ b/tests/api-resources/invocations.test.ts @@ -87,4 +87,16 @@ describe('resource invocations', () => { expect(dataAndResponse.data).toBe(response); expect(dataAndResponse.response).toBe(rawResponse); }); + + // Prism doesn't support text/event-stream responses + test.skip('follow: 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.invocations.follow( + 'id', + { since: '2025-06-20T12:00:00Z' }, + { path: '/_stainless_unknown_path' }, + ), + ).rejects.toThrow(Kernel.NotFoundError); + }); }); From 15dd773ce089b67874f9930299a33878e566129a Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 24 Sep 2025 20:56:33 +0000 Subject: [PATCH 163/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 8ad7375d..89688e25 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.11.2" + ".": "0.11.3" } diff --git a/package.json b/package.json index f94a5315..19e5d151 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.11.2", + "version": "0.11.3", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index b818b4ca..e2bf0d13 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.11.2'; // x-release-please-version +export const VERSION = '0.11.3'; // x-release-please-version From 93873331956d83a6fefc2a791703874783d755b7 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 25 Sep 2025 18:14:04 +0000 Subject: [PATCH 164/551] feat: getInvocations endpoint --- .stats.yml | 8 +- api.md | 2 + src/client.ts | 6 ++ src/resources/index.ts | 3 + src/resources/invocations.ts | 105 ++++++++++++++++++++++++ tests/api-resources/invocations.test.ts | 31 +++++++ 6 files changed, 151 insertions(+), 4 deletions(-) diff --git a/.stats.yml b/.stats.yml index 4039b103..be90d46e 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 50 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-5ee2116982adf46664acf84b8ba4b56ba65780983506c63d9b005dab49def757.yml -openapi_spec_hash: 42a3a519301d0e2bb2b5a71018915b55 -config_hash: 0d150b61cae2dc57d3648ceae7784966 +configured_endpoints: 51 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-8b5a722e4964d2d1dcdc34afccb6d742e1c927cbbd622264c8734f132e31a0f5.yml +openapi_spec_hash: ed101ff177c2e962653ca65acf939336 +config_hash: 49c2ff978aaa5ccb4ce324a72f116010 diff --git a/api.md b/api.md index cbf98aac..9165c58a 100644 --- a/api.md +++ b/api.md @@ -44,6 +44,7 @@ Types: - InvocationCreateResponse - InvocationRetrieveResponse - InvocationUpdateResponse +- InvocationListResponse - InvocationFollowResponse Methods: @@ -51,6 +52,7 @@ Methods: - client.invocations.create({ ...params }) -> InvocationCreateResponse - client.invocations.retrieve(id) -> InvocationRetrieveResponse - client.invocations.update(id, { ...params }) -> InvocationUpdateResponse +- client.invocations.list({ ...params }) -> InvocationListResponsesOffsetPagination - client.invocations.deleteBrowsers(id) -> void - client.invocations.follow(id, { ...params }) -> InvocationFollowResponse diff --git a/src/client.ts b/src/client.ts index 376d277b..4d0906f3 100644 --- a/src/client.ts +++ b/src/client.ts @@ -36,6 +36,9 @@ import { InvocationCreateResponse, InvocationFollowParams, InvocationFollowResponse, + InvocationListParams, + InvocationListResponse, + InvocationListResponsesOffsetPagination, InvocationRetrieveResponse, InvocationStateEvent, InvocationUpdateParams, @@ -845,9 +848,12 @@ export declare namespace Kernel { type InvocationCreateResponse as InvocationCreateResponse, type InvocationRetrieveResponse as InvocationRetrieveResponse, type InvocationUpdateResponse as InvocationUpdateResponse, + type InvocationListResponse as InvocationListResponse, type InvocationFollowResponse as InvocationFollowResponse, + type InvocationListResponsesOffsetPagination as InvocationListResponsesOffsetPagination, type InvocationCreateParams as InvocationCreateParams, type InvocationUpdateParams as InvocationUpdateParams, + type InvocationListParams as InvocationListParams, type InvocationFollowParams as InvocationFollowParams, }; diff --git a/src/resources/index.ts b/src/resources/index.ts index 3d63b756..0288a65b 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -30,10 +30,13 @@ export { type InvocationCreateResponse, type InvocationRetrieveResponse, type InvocationUpdateResponse, + type InvocationListResponse, type InvocationFollowResponse, type InvocationCreateParams, type InvocationUpdateParams, + type InvocationListParams, type InvocationFollowParams, + type InvocationListResponsesOffsetPagination, } from './invocations'; export { Profiles, type ProfileListResponse, type ProfileCreateParams } from './profiles'; export { diff --git a/src/resources/invocations.ts b/src/resources/invocations.ts index bc326309..5db5a3e7 100644 --- a/src/resources/invocations.ts +++ b/src/resources/invocations.ts @@ -3,6 +3,7 @@ import { APIResource } from '../core/resource'; import * as Shared from './shared'; import { APIPromise } from '../core/api-promise'; +import { OffsetPagination, type OffsetPaginationParams, PagePromise } from '../core/pagination'; import { Stream } from '../core/streaming'; import { buildHeaders } from '../internal/headers'; import { RequestOptions } from '../internal/request-options'; @@ -58,6 +59,28 @@ export class Invocations extends APIResource { return this._client.patch(path`/invocations/${id}`, { body, ...options }); } + /** + * List invocations. Optionally filter by application name, action name, status, + * deployment ID, or start time. + * + * @example + * ```ts + * // Automatically fetches more pages as needed. + * for await (const invocationListResponse of client.invocations.list()) { + * // ... + * } + * ``` + */ + list( + query: InvocationListParams | null | undefined = {}, + options?: RequestOptions, + ): PagePromise { + return this._client.getAPIList('/invocations', OffsetPagination, { + query, + ...options, + }); + } + /** * Delete all browser sessions created within the specified invocation. * @@ -97,6 +120,8 @@ export class Invocations extends APIResource { } } +export type InvocationListResponsesOffsetPagination = OffsetPagination; + /** * An event representing the current state of an invocation. */ @@ -291,6 +316,55 @@ export interface InvocationUpdateResponse { status_reason?: string; } +export interface InvocationListResponse { + /** + * ID of the invocation + */ + id: string; + + /** + * Name of the action invoked + */ + action_name: string; + + /** + * Name of the application + */ + app_name: string; + + /** + * RFC 3339 Nanoseconds timestamp when the invocation started + */ + started_at: string; + + /** + * Status of the invocation + */ + status: 'queued' | 'running' | 'succeeded' | 'failed'; + + /** + * RFC 3339 Nanoseconds timestamp when the invocation finished (null if still + * running) + */ + finished_at?: string | null; + + /** + * Output produced by the action, rendered as a JSON string. This could be: string, + * number, boolean, array, object, or null. + */ + output?: string; + + /** + * Payload provided to the invocation. This is a string that can be parsed as JSON. + */ + payload?: string; + + /** + * Status reason + */ + status_reason?: string; +} + /** * Union type representing any invocation event. */ @@ -340,6 +414,34 @@ export interface InvocationUpdateParams { output?: string; } +export interface InvocationListParams extends OffsetPaginationParams { + /** + * Filter results by action name. + */ + action_name?: string; + + /** + * Filter results by application name. + */ + app_name?: string; + + /** + * Filter results by deployment ID. + */ + deployment_id?: string; + + /** + * Show invocations that have started since the given time (RFC timestamps or + * durations like 5m). + */ + since?: string; + + /** + * Filter results by invocation status. + */ + status?: 'queued' | 'running' | 'succeeded' | 'failed'; +} + export interface InvocationFollowParams { /** * Show logs since the given time (RFC timestamps or durations like 5m). @@ -353,9 +455,12 @@ export declare namespace Invocations { type InvocationCreateResponse as InvocationCreateResponse, type InvocationRetrieveResponse as InvocationRetrieveResponse, type InvocationUpdateResponse as InvocationUpdateResponse, + type InvocationListResponse as InvocationListResponse, type InvocationFollowResponse as InvocationFollowResponse, + type InvocationListResponsesOffsetPagination as InvocationListResponsesOffsetPagination, type InvocationCreateParams as InvocationCreateParams, type InvocationUpdateParams as InvocationUpdateParams, + type InvocationListParams as InvocationListParams, type InvocationFollowParams as InvocationFollowParams, }; } diff --git a/tests/api-resources/invocations.test.ts b/tests/api-resources/invocations.test.ts index 309612ad..38aa2d2d 100644 --- a/tests/api-resources/invocations.test.ts +++ b/tests/api-resources/invocations.test.ts @@ -64,6 +64,37 @@ describe('resource invocations', () => { const response = await client.invocations.update('id', { status: 'succeeded', output: 'output' }); }); + // Prism tests are disabled + test.skip('list', async () => { + const responsePromise = client.invocations.list(); + 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); + }); + + // Prism tests are disabled + test.skip('list: 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.invocations.list( + { + action_name: 'action_name', + app_name: 'app_name', + deployment_id: 'deployment_id', + limit: 1, + offset: 0, + since: '2025-06-20T12:00:00Z', + status: 'queued', + }, + { path: '/_stainless_unknown_path' }, + ), + ).rejects.toThrow(Kernel.NotFoundError); + }); + // Prism tests are disabled test.skip('deleteBrowsers', async () => { const responsePromise = client.invocations.deleteBrowsers('id'); From 65882d1fa0422a59e909685a565fc3f70c519e9b Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 25 Sep 2025 18:20:51 +0000 Subject: [PATCH 165/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 89688e25..d1eff552 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.11.3" + ".": "0.11.4" } diff --git a/package.json b/package.json index 19e5d151..7e71329f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.11.3", + "version": "0.11.4", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index e2bf0d13..667a403d 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.11.3'; // x-release-please-version +export const VERSION = '0.11.4'; // x-release-please-version From e8e05ba4ff968090915514d23b8c6bd385bb31dd Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 26 Sep 2025 02:30:29 +0000 Subject: [PATCH 166/551] perf: faster formatting --- scripts/fast-format | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100755 scripts/fast-format diff --git a/scripts/fast-format b/scripts/fast-format new file mode 100755 index 00000000..ef42df58 --- /dev/null +++ b/scripts/fast-format @@ -0,0 +1,40 @@ +#!/usr/bin/env bash + +set -euo pipefail + +echo "Script started with $# arguments" +echo "Arguments: $*" +echo "Script location: $(dirname "$0")" + +cd "$(dirname "$0")/.." +echo "Changed to directory: $(pwd)" + +if [ $# -eq 0 ]; then + echo "Usage: $0 [additional-formatter-args...]" + echo "The file should contain one file path per line" + exit 1 +fi + +FILE_LIST="$1" + +echo "Looking for file: $FILE_LIST" + +if [ ! -f "$FILE_LIST" ]; then + echo "Error: File '$FILE_LIST' not found" + exit 1 +fi + +echo "==> Running eslint --fix" +ESLINT_FILES="$(grep '\.ts$' "$FILE_LIST" || true)" +if ! [ -z "$ESLINT_FILES" ]; then + echo "$ESLINT_FILES" | xargs ./node_modules/.bin/eslint --cache --fix +fi + +echo "==> Running prettier --write" +# format things eslint didn't +PRETTIER_FILES="$(grep '\.\(js\|json\)$' "$FILE_LIST" || true)" +if ! [ -z "$PRETTIER_FILES" ]; then + echo "$PRETTIER_FILES" | xargs ./node_modules/.bin/prettier \ + --write --cache --cache-strategy metadata \ + '!**/dist' '!**/*.ts' '!**/*.mts' '!**/*.cts' '!**/*.js' '!**/*.mjs' '!**/*.cjs' +fi From 1d28c12facd71656cbae838e0ca64920594f8a9c Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 26 Sep 2025 02:31:35 +0000 Subject: [PATCH 167/551] chore(internal): remove deprecated `compilerOptions.baseUrl` from tsconfig.json This allows sdks to be built using tsgo - see https://github.com/microsoft/typescript-go/issues/474 --- tsconfig.build.json | 4 ++-- tsconfig.json | 5 ++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/tsconfig.build.json b/tsconfig.build.json index 7a7d5e09..762269d0 100644 --- a/tsconfig.build.json +++ b/tsconfig.build.json @@ -5,8 +5,8 @@ "compilerOptions": { "rootDir": "./dist/src", "paths": { - "@onkernel/sdk/*": ["dist/src/*"], - "@onkernel/sdk": ["dist/src/index.ts"] + "@onkernel/sdk/*": ["./dist/src/*"], + "@onkernel/sdk": ["./dist/src/index.ts"] }, "noEmit": false, "declaration": true, diff --git a/tsconfig.json b/tsconfig.json index ffa29592..73ce2185 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -7,10 +7,9 @@ "module": "commonjs", "moduleResolution": "node", "esModuleInterop": true, - "baseUrl": "./", "paths": { - "@onkernel/sdk/*": ["src/*"], - "@onkernel/sdk": ["src/index.ts"] + "@onkernel/sdk/*": ["./src/*"], + "@onkernel/sdk": ["./src/index.ts"] }, "noEmit": true, From 9fe2c59ca97333b2b693244088c22298ed4ea42a Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 26 Sep 2025 20:24:26 +0000 Subject: [PATCH 168/551] feat: Fix my incorrect grammer --- .eslintcache | 1 + .stats.yml | 4 ++-- src/resources/invocations.ts | 4 ++-- 3 files changed, 5 insertions(+), 4 deletions(-) create mode 100644 .eslintcache diff --git a/.eslintcache b/.eslintcache new file mode 100644 index 00000000..733f8c90 --- /dev/null +++ b/.eslintcache @@ -0,0 +1 @@ +[{"/home/tempuser-jrpkli/run/codegen-output/kernel/kernel-typescript/src/resources/invocations.ts":"1"},{"size":10552,"mtime":1758918263853}] \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index be90d46e..81ff9672 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 51 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-8b5a722e4964d2d1dcdc34afccb6d742e1c927cbbd622264c8734f132e31a0f5.yml -openapi_spec_hash: ed101ff177c2e962653ca65acf939336 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-bfdb7e3d38870a8ba1628f4f83a3a719d470bf4f7fbecb67a6fad110447c9b6a.yml +openapi_spec_hash: fed29c80f9c25f8a7216b8c6de2051ab config_hash: 49c2ff978aaa5ccb4ce324a72f116010 diff --git a/src/resources/invocations.ts b/src/resources/invocations.ts index 5db5a3e7..215326c8 100644 --- a/src/resources/invocations.ts +++ b/src/resources/invocations.ts @@ -41,8 +41,8 @@ export class Invocations extends APIResource { } /** - * Update an invocation's status or output. This can used to cancel an invocation - * by setting the status to "failed". + * Update an invocation's status or output. This can be used to cancel an + * invocation by setting the status to "failed". * * @example * ```ts From 0b9d2b3d3ecf0f767a54a0e68311e9a7a9cf7a78 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 27 Sep 2025 02:42:31 +0000 Subject: [PATCH 169/551] chore(internal): fix incremental formatting in some cases --- scripts/fast-format | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/fast-format b/scripts/fast-format index ef42df58..53721ac0 100755 --- a/scripts/fast-format +++ b/scripts/fast-format @@ -35,6 +35,6 @@ echo "==> Running prettier --write" PRETTIER_FILES="$(grep '\.\(js\|json\)$' "$FILE_LIST" || true)" if ! [ -z "$PRETTIER_FILES" ]; then echo "$PRETTIER_FILES" | xargs ./node_modules/.bin/prettier \ - --write --cache --cache-strategy metadata \ + --write --cache --cache-strategy metadata --no-error-on-unmatched-pattern \ '!**/dist' '!**/*.ts' '!**/*.mts' '!**/*.cts' '!**/*.js' '!**/*.mjs' '!**/*.cjs' fi From 191cf1a9b4eb07a78b77db3722a5061923c1fa24 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 27 Sep 2025 02:46:01 +0000 Subject: [PATCH 170/551] chore(internal): codegen related update --- .eslintcache | 2 +- .github/workflows/release-doctor.yml | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.eslintcache b/.eslintcache index 733f8c90..9b28c31a 100644 --- a/.eslintcache +++ b/.eslintcache @@ -1 +1 @@ -[{"/home/tempuser-jrpkli/run/codegen-output/kernel/kernel-typescript/src/resources/invocations.ts":"1"},{"size":10552,"mtime":1758918263853}] \ No newline at end of file +[{"/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/jest.config.ts":"1","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/api-promise.ts":"2","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/client.ts":"3","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/core/api-promise.ts":"4","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/core/error.ts":"5","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/core/pagination.ts":"6","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/core/resource.ts":"7","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/core/streaming.ts":"8","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/core/uploads.ts":"9","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/internal/builtin-types.ts":"10","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/index.ts":"11","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/error.ts":"12","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/internal/decoders/line.ts":"13","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/internal/detect-platform.ts":"14","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/internal/errors.ts":"15","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/internal/headers.ts":"16","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/internal/parse.ts":"17","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/internal/request-options.ts":"18","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/internal/shim-types.ts":"19","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/internal/shims.ts":"20","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/internal/to-file.ts":"21","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/internal/types.ts":"22","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/internal/uploads.ts":"23","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/internal/utils/base64.ts":"24","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/internal/utils/bytes.ts":"25","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/internal/utils/env.ts":"26","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/internal/utils/log.ts":"27","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/internal/utils/path.ts":"28","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/internal/utils/sleep.ts":"29","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/internal/utils/uuid.ts":"30","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/internal/utils/values.ts":"31","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/internal/utils.ts":"32","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/pagination.ts":"33","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/resource.ts":"34","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/resources/apps.ts":"35","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/resources/browsers/browsers.ts":"36","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/resources/browsers/fs/fs.ts":"37","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/resources/browsers/fs/index.ts":"38","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/resources/browsers/fs/watch.ts":"39","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/resources/browsers/fs.ts":"40","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/resources/browsers/index.ts":"41","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/resources/browsers/logs.ts":"42","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/resources/browsers/process.ts":"43","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/resources/browsers/replays.ts":"44","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/resources/browsers.ts":"45","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/resources/deployments.ts":"46","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/resources/index.ts":"47","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/resources/invocations.ts":"48","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/resources/profiles.ts":"49","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/resources/shared.ts":"50","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/resources/proxies.ts":"51","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/resources.ts":"52","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/streaming.ts":"53","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/uploads.ts":"54","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/version.ts":"55","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/tests/api-resources/apps.test.ts":"56","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/tests/api-resources/browsers/browsers.test.ts":"57","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/tests/api-resources/browsers/fs/fs.test.ts":"58","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/tests/api-resources/browsers/fs/watch.test.ts":"59","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/tests/api-resources/browsers/logs.test.ts":"60","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/tests/api-resources/browsers/process.test.ts":"61","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/tests/api-resources/browsers/replays.test.ts":"62","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/tests/api-resources/deployments.test.ts":"63","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/tests/api-resources/invocations.test.ts":"64","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/tests/api-resources/profiles.test.ts":"65","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/tests/api-resources/proxies.test.ts":"66","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/tests/base64.test.ts":"67","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/tests/buildHeaders.test.ts":"68","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/tests/form.test.ts":"69","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/tests/index.test.ts":"70","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/tests/internal/decoders/line.test.ts":"71","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/tests/path.test.ts":"72","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/tests/streaming.test.ts":"73","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/tests/uploads.test.ts":"74","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/tests/stringifyQuery.test.ts":"75"},{"size":606,"mtime":1758941141033,"results":"76","hashOfConfig":"77"},{"size":92,"mtime":1758941154253},{"size":31381,"mtime":1758941154253},{"size":3120,"mtime":1758941154253},{"size":3975,"mtime":1758941154253},{"size":4431,"mtime":1758941154253},{"size":261,"mtime":1758941141141,"results":"78","hashOfConfig":"77"},{"size":8850,"mtime":1758941154253},{"size":119,"mtime":1758941141049,"results":"79","hashOfConfig":"77"},{"size":2917,"mtime":1758941154253},{"size":620,"mtime":1758941154253},{"size":80,"mtime":1758941154253},{"size":3888,"mtime":1758941141053,"results":"80","hashOfConfig":"77"},{"size":6407,"mtime":1758941154253},{"size":1187,"mtime":1758941154253},{"size":3026,"mtime":1758941154253},{"size":2089,"mtime":1758941154253},{"size":2548,"mtime":1758941154253},{"size":929,"mtime":1758941154253},{"size":3524,"mtime":1758941154253},{"size":5211,"mtime":1758941154253},{"size":6352,"mtime":1758941154253},{"size":6736,"mtime":1758941141053,"results":"81","hashOfConfig":"77"},{"size":1269,"mtime":1758941141129,"results":"82","hashOfConfig":"77"},{"size":831,"mtime":1758941141053,"results":"83","hashOfConfig":"77"},{"size":612,"mtime":1758941141129,"results":"84","hashOfConfig":"77"},{"size":3104,"mtime":1758941154253},{"size":3207,"mtime":1758941141053,"results":"85","hashOfConfig":"77"},{"size":182,"mtime":1758941141129,"results":"86","hashOfConfig":"77"},{"size":601,"mtime":1758941154253},{"size":3128,"mtime":1758941141129,"results":"87","hashOfConfig":"77"},{"size":271,"mtime":1758941141125,"results":"88","hashOfConfig":"77"},{"size":90,"mtime":1758941154253},{"size":86,"mtime":1758941154253},{"size":1734,"mtime":1758941154253},{"size":11724,"mtime":1758941154253},{"size":10834,"mtime":1758941154253},{"size":612,"mtime":1758941154253},{"size":3062,"mtime":1758941154257},{"size":116,"mtime":1758941141505,"results":"89","hashOfConfig":"77"},{"size":1258,"mtime":1758941154257},{"size":1394,"mtime":1758941154257},{"size":7598,"mtime":1758941154257},{"size":3965,"mtime":1758941154257},{"size":122,"mtime":1758941141381,"results":"90","hashOfConfig":"77"},{"size":9202,"mtime":1758941154257},{"size":1361,"mtime":1758941154257},{"size":10552,"mtime":1758941154257},{"size":2222,"mtime":1758941154257},{"size":1589,"mtime":1758941154257},{"size":16202,"mtime":1758941154257},{"size":35,"mtime":1758941141057,"results":"91","hashOfConfig":"77"},{"size":88,"mtime":1758941154257},{"size":84,"mtime":1758941154257},{"size":60,"mtime":1758941154257},{"size":1207,"mtime":1758941154257},{"size":3735,"mtime":1758941154257},{"size":8650,"mtime":1758941154257},{"size":2591,"mtime":1758941154257},{"size":1157,"mtime":1758941154257},{"size":5347,"mtime":1758941154257},{"size":2656,"mtime":1758941154257},{"size":3707,"mtime":1758941154257},{"size":5008,"mtime":1758941154257},{"size":2340,"mtime":1758941154257},{"size":2579,"mtime":1758941154257},{"size":2067,"mtime":1758941141057,"results":"92","hashOfConfig":"93"},{"size":2187,"mtime":1758941141057,"results":"94","hashOfConfig":"93"},{"size":1898,"mtime":1758941141057,"results":"95","hashOfConfig":"93"},{"size":23402,"mtime":1758941154257},{"size":5370,"mtime":1758941141057,"results":"96","hashOfConfig":"93"},{"size":17595,"mtime":1758941141061,"results":"97","hashOfConfig":"93"},{"size":7233,"mtime":1758941154257},{"size":3489,"mtime":1758941141061,"results":"98","hashOfConfig":"93"},{"size":922,"mtime":1758941154257},{"filePath":"99","messages":"100","suppressedMessages":"101","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"o0ill6",{"filePath":"102","messages":"103","suppressedMessages":"104","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"105","messages":"106","suppressedMessages":"107","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"108","messages":"109","suppressedMessages":"110","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"111","messages":"112","suppressedMessages":"113","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"114","messages":"115","suppressedMessages":"116","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"117","messages":"118","suppressedMessages":"119","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"120","messages":"121","suppressedMessages":"122","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"123","messages":"124","suppressedMessages":"125","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"126","messages":"127","suppressedMessages":"128","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"129","messages":"130","suppressedMessages":"131","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"132","messages":"133","suppressedMessages":"134","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"135","messages":"136","suppressedMessages":"137","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"138","messages":"139","suppressedMessages":"140","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"141","messages":"142","suppressedMessages":"143","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"144","messages":"145","suppressedMessages":"146","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"46bmhf",{"filePath":"147","messages":"148","suppressedMessages":"149","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"150","messages":"151","suppressedMessages":"152","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"153","messages":"154","suppressedMessages":"155","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"156","messages":"157","suppressedMessages":"158","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"159","messages":"160","suppressedMessages":"161","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/jest.config.ts",[],[],"/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/core/resource.ts",[],[],"/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/core/uploads.ts",[],[],"/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/internal/decoders/line.ts",[],[],"/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/internal/uploads.ts",[],[],"/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/internal/utils/base64.ts",[],[],"/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/internal/utils/bytes.ts",[],[],"/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/internal/utils/env.ts",[],[],"/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/internal/utils/path.ts",[],[],"/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/internal/utils/sleep.ts",[],[],"/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/internal/utils/values.ts",[],[],"/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/internal/utils.ts",[],[],"/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/resources/browsers/fs.ts",[],[],"/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/resources/browsers.ts",[],[],"/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/resources.ts",[],[],"/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/tests/base64.test.ts",[],[],"/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/tests/buildHeaders.test.ts",[],[],"/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/tests/form.test.ts",[],[],"/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/tests/internal/decoders/line.test.ts",[],[],"/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/tests/path.test.ts",[],[],"/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/tests/uploads.test.ts",[],[]] \ No newline at end of file diff --git a/.github/workflows/release-doctor.yml b/.github/workflows/release-doctor.yml index 56150c7e..9e9b38d1 100644 --- a/.github/workflows/release-doctor.yml +++ b/.github/workflows/release-doctor.yml @@ -19,3 +19,4 @@ jobs: bash ./bin/check-release-environment env: NPM_TOKEN: ${{ secrets.KERNEL_NPM_TOKEN || secrets.NPM_TOKEN }} + From a0e6a0cb4ef5ba297a81ae7bb7ee1973eede4cd6 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 27 Sep 2025 02:48:21 +0000 Subject: [PATCH 171/551] chore(internal): ignore .eslintcache --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index d98d51a8..2412bb77 100644 --- a/.gitignore +++ b/.gitignore @@ -7,4 +7,5 @@ dist dist-deno /*.tgz .idea/ +.eslintcache From de1a93b51aa3f7d5b778d70161025fe548689ce7 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 29 Sep 2025 18:11:53 +0000 Subject: [PATCH 172/551] feat: Add App Version to Invocation and add filtering on App Version --- .eslintcache | 2 +- .stats.yml | 4 ++-- src/resources/invocations.ts | 25 +++++++++++++++++++++++++ tests/api-resources/invocations.test.ts | 1 + 4 files changed, 29 insertions(+), 3 deletions(-) diff --git a/.eslintcache b/.eslintcache index 9b28c31a..8a180779 100644 --- a/.eslintcache +++ b/.eslintcache @@ -1 +1 @@ -[{"/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/jest.config.ts":"1","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/api-promise.ts":"2","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/client.ts":"3","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/core/api-promise.ts":"4","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/core/error.ts":"5","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/core/pagination.ts":"6","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/core/resource.ts":"7","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/core/streaming.ts":"8","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/core/uploads.ts":"9","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/internal/builtin-types.ts":"10","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/index.ts":"11","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/error.ts":"12","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/internal/decoders/line.ts":"13","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/internal/detect-platform.ts":"14","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/internal/errors.ts":"15","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/internal/headers.ts":"16","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/internal/parse.ts":"17","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/internal/request-options.ts":"18","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/internal/shim-types.ts":"19","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/internal/shims.ts":"20","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/internal/to-file.ts":"21","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/internal/types.ts":"22","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/internal/uploads.ts":"23","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/internal/utils/base64.ts":"24","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/internal/utils/bytes.ts":"25","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/internal/utils/env.ts":"26","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/internal/utils/log.ts":"27","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/internal/utils/path.ts":"28","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/internal/utils/sleep.ts":"29","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/internal/utils/uuid.ts":"30","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/internal/utils/values.ts":"31","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/internal/utils.ts":"32","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/pagination.ts":"33","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/resource.ts":"34","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/resources/apps.ts":"35","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/resources/browsers/browsers.ts":"36","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/resources/browsers/fs/fs.ts":"37","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/resources/browsers/fs/index.ts":"38","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/resources/browsers/fs/watch.ts":"39","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/resources/browsers/fs.ts":"40","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/resources/browsers/index.ts":"41","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/resources/browsers/logs.ts":"42","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/resources/browsers/process.ts":"43","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/resources/browsers/replays.ts":"44","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/resources/browsers.ts":"45","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/resources/deployments.ts":"46","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/resources/index.ts":"47","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/resources/invocations.ts":"48","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/resources/profiles.ts":"49","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/resources/shared.ts":"50","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/resources/proxies.ts":"51","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/resources.ts":"52","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/streaming.ts":"53","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/uploads.ts":"54","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/version.ts":"55","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/tests/api-resources/apps.test.ts":"56","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/tests/api-resources/browsers/browsers.test.ts":"57","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/tests/api-resources/browsers/fs/fs.test.ts":"58","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/tests/api-resources/browsers/fs/watch.test.ts":"59","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/tests/api-resources/browsers/logs.test.ts":"60","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/tests/api-resources/browsers/process.test.ts":"61","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/tests/api-resources/browsers/replays.test.ts":"62","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/tests/api-resources/deployments.test.ts":"63","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/tests/api-resources/invocations.test.ts":"64","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/tests/api-resources/profiles.test.ts":"65","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/tests/api-resources/proxies.test.ts":"66","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/tests/base64.test.ts":"67","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/tests/buildHeaders.test.ts":"68","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/tests/form.test.ts":"69","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/tests/index.test.ts":"70","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/tests/internal/decoders/line.test.ts":"71","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/tests/path.test.ts":"72","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/tests/streaming.test.ts":"73","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/tests/uploads.test.ts":"74","/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/tests/stringifyQuery.test.ts":"75"},{"size":606,"mtime":1758941141033,"results":"76","hashOfConfig":"77"},{"size":92,"mtime":1758941154253},{"size":31381,"mtime":1758941154253},{"size":3120,"mtime":1758941154253},{"size":3975,"mtime":1758941154253},{"size":4431,"mtime":1758941154253},{"size":261,"mtime":1758941141141,"results":"78","hashOfConfig":"77"},{"size":8850,"mtime":1758941154253},{"size":119,"mtime":1758941141049,"results":"79","hashOfConfig":"77"},{"size":2917,"mtime":1758941154253},{"size":620,"mtime":1758941154253},{"size":80,"mtime":1758941154253},{"size":3888,"mtime":1758941141053,"results":"80","hashOfConfig":"77"},{"size":6407,"mtime":1758941154253},{"size":1187,"mtime":1758941154253},{"size":3026,"mtime":1758941154253},{"size":2089,"mtime":1758941154253},{"size":2548,"mtime":1758941154253},{"size":929,"mtime":1758941154253},{"size":3524,"mtime":1758941154253},{"size":5211,"mtime":1758941154253},{"size":6352,"mtime":1758941154253},{"size":6736,"mtime":1758941141053,"results":"81","hashOfConfig":"77"},{"size":1269,"mtime":1758941141129,"results":"82","hashOfConfig":"77"},{"size":831,"mtime":1758941141053,"results":"83","hashOfConfig":"77"},{"size":612,"mtime":1758941141129,"results":"84","hashOfConfig":"77"},{"size":3104,"mtime":1758941154253},{"size":3207,"mtime":1758941141053,"results":"85","hashOfConfig":"77"},{"size":182,"mtime":1758941141129,"results":"86","hashOfConfig":"77"},{"size":601,"mtime":1758941154253},{"size":3128,"mtime":1758941141129,"results":"87","hashOfConfig":"77"},{"size":271,"mtime":1758941141125,"results":"88","hashOfConfig":"77"},{"size":90,"mtime":1758941154253},{"size":86,"mtime":1758941154253},{"size":1734,"mtime":1758941154253},{"size":11724,"mtime":1758941154253},{"size":10834,"mtime":1758941154253},{"size":612,"mtime":1758941154253},{"size":3062,"mtime":1758941154257},{"size":116,"mtime":1758941141505,"results":"89","hashOfConfig":"77"},{"size":1258,"mtime":1758941154257},{"size":1394,"mtime":1758941154257},{"size":7598,"mtime":1758941154257},{"size":3965,"mtime":1758941154257},{"size":122,"mtime":1758941141381,"results":"90","hashOfConfig":"77"},{"size":9202,"mtime":1758941154257},{"size":1361,"mtime":1758941154257},{"size":10552,"mtime":1758941154257},{"size":2222,"mtime":1758941154257},{"size":1589,"mtime":1758941154257},{"size":16202,"mtime":1758941154257},{"size":35,"mtime":1758941141057,"results":"91","hashOfConfig":"77"},{"size":88,"mtime":1758941154257},{"size":84,"mtime":1758941154257},{"size":60,"mtime":1758941154257},{"size":1207,"mtime":1758941154257},{"size":3735,"mtime":1758941154257},{"size":8650,"mtime":1758941154257},{"size":2591,"mtime":1758941154257},{"size":1157,"mtime":1758941154257},{"size":5347,"mtime":1758941154257},{"size":2656,"mtime":1758941154257},{"size":3707,"mtime":1758941154257},{"size":5008,"mtime":1758941154257},{"size":2340,"mtime":1758941154257},{"size":2579,"mtime":1758941154257},{"size":2067,"mtime":1758941141057,"results":"92","hashOfConfig":"93"},{"size":2187,"mtime":1758941141057,"results":"94","hashOfConfig":"93"},{"size":1898,"mtime":1758941141057,"results":"95","hashOfConfig":"93"},{"size":23402,"mtime":1758941154257},{"size":5370,"mtime":1758941141057,"results":"96","hashOfConfig":"93"},{"size":17595,"mtime":1758941141061,"results":"97","hashOfConfig":"93"},{"size":7233,"mtime":1758941154257},{"size":3489,"mtime":1758941141061,"results":"98","hashOfConfig":"93"},{"size":922,"mtime":1758941154257},{"filePath":"99","messages":"100","suppressedMessages":"101","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"o0ill6",{"filePath":"102","messages":"103","suppressedMessages":"104","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"105","messages":"106","suppressedMessages":"107","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"108","messages":"109","suppressedMessages":"110","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"111","messages":"112","suppressedMessages":"113","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"114","messages":"115","suppressedMessages":"116","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"117","messages":"118","suppressedMessages":"119","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"120","messages":"121","suppressedMessages":"122","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"123","messages":"124","suppressedMessages":"125","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"126","messages":"127","suppressedMessages":"128","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"129","messages":"130","suppressedMessages":"131","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"132","messages":"133","suppressedMessages":"134","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"135","messages":"136","suppressedMessages":"137","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"138","messages":"139","suppressedMessages":"140","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"141","messages":"142","suppressedMessages":"143","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"144","messages":"145","suppressedMessages":"146","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"46bmhf",{"filePath":"147","messages":"148","suppressedMessages":"149","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"150","messages":"151","suppressedMessages":"152","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"153","messages":"154","suppressedMessages":"155","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"156","messages":"157","suppressedMessages":"158","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"159","messages":"160","suppressedMessages":"161","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/jest.config.ts",[],[],"/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/core/resource.ts",[],[],"/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/core/uploads.ts",[],[],"/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/internal/decoders/line.ts",[],[],"/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/internal/uploads.ts",[],[],"/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/internal/utils/base64.ts",[],[],"/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/internal/utils/bytes.ts",[],[],"/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/internal/utils/env.ts",[],[],"/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/internal/utils/path.ts",[],[],"/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/internal/utils/sleep.ts",[],[],"/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/internal/utils/values.ts",[],[],"/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/internal/utils.ts",[],[],"/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/resources/browsers/fs.ts",[],[],"/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/resources/browsers.ts",[],[],"/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/src/resources.ts",[],[],"/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/tests/base64.test.ts",[],[],"/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/tests/buildHeaders.test.ts",[],[],"/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/tests/form.test.ts",[],[],"/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/tests/internal/decoders/line.test.ts",[],[],"/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/tests/path.test.ts",[],[],"/home/tempuser-a29hxt/run/codegen-output/kernel/kernel-typescript/tests/uploads.test.ts",[],[]] \ No newline at end of file +[{"/home/tempuser-szo6ty/run/codegen-output/kernel/kernel-typescript/src/resources/invocations.ts":"1","/home/tempuser-szo6ty/run/codegen-output/kernel/kernel-typescript/tests/api-resources/invocations.test.ts":"2"},{"size":10921,"mtime":1759169510096},{"size":5028,"mtime":1759169510096}] \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index 81ff9672..2b8a4b66 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 51 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-bfdb7e3d38870a8ba1628f4f83a3a719d470bf4f7fbecb67a6fad110447c9b6a.yml -openapi_spec_hash: fed29c80f9c25f8a7216b8c6de2051ab +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-da8bfd5cfb5a6d9ccb7e4edd123b49284f4eccb32fc9b6fb7165548535122e12.yml +openapi_spec_hash: fd6ded34689331831b5c077f71b5f08f config_hash: 49c2ff978aaa5ccb4ce324a72f116010 diff --git a/src/resources/invocations.ts b/src/resources/invocations.ts index 215326c8..95d36e3e 100644 --- a/src/resources/invocations.ts +++ b/src/resources/invocations.ts @@ -166,6 +166,11 @@ export namespace InvocationStateEvent { */ status: 'queued' | 'running' | 'succeeded' | 'failed'; + /** + * Version label for the application + */ + version: string; + /** * RFC 3339 Nanoseconds timestamp when the invocation finished (null if still * running) @@ -244,6 +249,11 @@ export interface InvocationRetrieveResponse { */ status: 'queued' | 'running' | 'succeeded' | 'failed'; + /** + * Version label for the application + */ + version: string; + /** * RFC 3339 Nanoseconds timestamp when the invocation finished (null if still * running) @@ -293,6 +303,11 @@ export interface InvocationUpdateResponse { */ status: 'queued' | 'running' | 'succeeded' | 'failed'; + /** + * Version label for the application + */ + version: string; + /** * RFC 3339 Nanoseconds timestamp when the invocation finished (null if still * running) @@ -342,6 +357,11 @@ export interface InvocationListResponse { */ status: 'queued' | 'running' | 'succeeded' | 'failed'; + /** + * Version label for the application + */ + version: string; + /** * RFC 3339 Nanoseconds timestamp when the invocation finished (null if still * running) @@ -440,6 +460,11 @@ export interface InvocationListParams extends OffsetPaginationParams { * Filter results by invocation status. */ status?: 'queued' | 'running' | 'succeeded' | 'failed'; + + /** + * Filter results by application version. + */ + version?: string; } export interface InvocationFollowParams { diff --git a/tests/api-resources/invocations.test.ts b/tests/api-resources/invocations.test.ts index 38aa2d2d..bf3ba646 100644 --- a/tests/api-resources/invocations.test.ts +++ b/tests/api-resources/invocations.test.ts @@ -89,6 +89,7 @@ describe('resource invocations', () => { offset: 0, since: '2025-06-20T12:00:00Z', status: 'queued', + version: 'version', }, { path: '/_stainless_unknown_path' }, ), From f9c66e253b8f3d6e4056b6f0b442d764e1fd2334 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 29 Sep 2025 19:29:27 +0000 Subject: [PATCH 173/551] chore(internal): version bump --- .eslintcache | 2 +- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.eslintcache b/.eslintcache index 8a180779..72e84f97 100644 --- a/.eslintcache +++ b/.eslintcache @@ -1 +1 @@ -[{"/home/tempuser-szo6ty/run/codegen-output/kernel/kernel-typescript/src/resources/invocations.ts":"1","/home/tempuser-szo6ty/run/codegen-output/kernel/kernel-typescript/tests/api-resources/invocations.test.ts":"2"},{"size":10921,"mtime":1759169510096},{"size":5028,"mtime":1759169510096}] \ No newline at end of file +[{"/home/tempuser-i9hupy/run/codegen-output/kernel/kernel-typescript/src/version.ts":"1"},{"size":60,"mtime":1759174164452}] \ No newline at end of file diff --git a/.release-please-manifest.json b/.release-please-manifest.json index d1eff552..5a36a413 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.11.4" + ".": "0.11.5" } diff --git a/package.json b/package.json index 7e71329f..3203809c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.11.4", + "version": "0.11.5", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 667a403d..af718326 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.11.4'; // x-release-please-version +export const VERSION = '0.11.5'; // x-release-please-version From 23248852989617c8e31d798cccac569cbcf72c1e Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 30 Sep 2025 16:05:28 +0000 Subject: [PATCH 174/551] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 2b8a4b66..1127c15d 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 51 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-da8bfd5cfb5a6d9ccb7e4edd123b49284f4eccb32fc9b6fb7165548535122e12.yml -openapi_spec_hash: fd6ded34689331831b5c077f71b5f08f +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-d79b0e3a9f9b6022bf845589a1eeff5bd7318d764a9f82e914c764fbbab5dac4.yml +openapi_spec_hash: c623d561039d0ec82f7841652ed82965 config_hash: 49c2ff978aaa5ccb4ce324a72f116010 From cbc4b2de8469e830c47ff58f0717e54e93fb711d Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 30 Sep 2025 16:48:31 +0000 Subject: [PATCH 175/551] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 1127c15d..4ada0071 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 51 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-d79b0e3a9f9b6022bf845589a1eeff5bd7318d764a9f82e914c764fbbab5dac4.yml -openapi_spec_hash: c623d561039d0ec82f7841652ed82965 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-a3d897b2f8f50d61df2555cbe888dfd2479a8a3faf9d9e2292cfdad3131485c5.yml +openapi_spec_hash: 6adc963fd957cd9f96bb16e62bdaed58 config_hash: 49c2ff978aaa5ccb4ce324a72f116010 From 5801c73c3e0321ae8a217568344d64fe3c18c6d5 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 30 Sep 2025 23:52:36 +0000 Subject: [PATCH 176/551] feat: Return proxy ID in browsers response --- .eslintcache | 2 +- .stats.yml | 4 ++-- src/resources/browsers/browsers.ts | 15 +++++++++++++++ 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/.eslintcache b/.eslintcache index 72e84f97..476b6d4a 100644 --- a/.eslintcache +++ b/.eslintcache @@ -1 +1 @@ -[{"/home/tempuser-i9hupy/run/codegen-output/kernel/kernel-typescript/src/version.ts":"1"},{"size":60,"mtime":1759174164452}] \ No newline at end of file +[{"/home/tempuser-rxv3c3/run/codegen-output/kernel/kernel-typescript/src/resources/browsers/browsers.ts":"1"},{"size":12035,"mtime":1759276353459}] \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index 4ada0071..a1c1d77e 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 51 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-a3d897b2f8f50d61df2555cbe888dfd2479a8a3faf9d9e2292cfdad3131485c5.yml -openapi_spec_hash: 6adc963fd957cd9f96bb16e62bdaed58 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-d0090ff3ef876c554e7a1281d5cbe1666cf68aebfc60e05cb7f4302ee377b372.yml +openapi_spec_hash: 33fef541c420a28125f18cd1efc0d585 config_hash: 49c2ff978aaa5ccb4ce324a72f116010 diff --git a/src/resources/browsers/browsers.ts b/src/resources/browsers/browsers.ts index 5f70d049..83681942 100644 --- a/src/resources/browsers/browsers.ts +++ b/src/resources/browsers/browsers.ts @@ -222,6 +222,11 @@ export interface BrowserCreateResponse { * Browser profile metadata. */ profile?: Profile; + + /** + * ID of the proxy associated with this browser session, if any. + */ + proxy_id?: string; } export interface BrowserRetrieveResponse { @@ -270,6 +275,11 @@ export interface BrowserRetrieveResponse { * Browser profile metadata. */ profile?: Profile; + + /** + * ID of the proxy associated with this browser session, if any. + */ + proxy_id?: string; } export type BrowserListResponse = Array; @@ -321,6 +331,11 @@ export namespace BrowserListResponse { * Browser profile metadata. */ profile?: BrowsersAPI.Profile; + + /** + * ID of the proxy associated with this browser session, if any. + */ + proxy_id?: string; } } From 021c66546684af6cd8d73e38344d3e9b36e2ffa9 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 30 Sep 2025 23:55:25 +0000 Subject: [PATCH 177/551] chore(internal): version bump --- .eslintcache | 2 +- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.eslintcache b/.eslintcache index 476b6d4a..c4433879 100644 --- a/.eslintcache +++ b/.eslintcache @@ -1 +1 @@ -[{"/home/tempuser-rxv3c3/run/codegen-output/kernel/kernel-typescript/src/resources/browsers/browsers.ts":"1"},{"size":12035,"mtime":1759276353459}] \ No newline at end of file +[{"/home/tempuser-h40j8e/run/codegen-output/kernel/kernel-typescript/src/version.ts":"1"},{"size":60,"mtime":1759276522735}] \ No newline at end of file diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 5a36a413..8032c17e 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.11.5" + ".": "0.12.0" } diff --git a/package.json b/package.json index 3203809c..a2c1b60d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.11.5", + "version": "0.12.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index af718326..ce6b8992 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.11.5'; // x-release-please-version +export const VERSION = '0.12.0'; // x-release-please-version From dd02d7d5125f2c3e17fb835e377b9ed27e76d902 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 1 Oct 2025 02:20:03 +0000 Subject: [PATCH 178/551] chore(internal): codegen related update --- .eslintcache | 1 - 1 file changed, 1 deletion(-) delete mode 100644 .eslintcache diff --git a/.eslintcache b/.eslintcache deleted file mode 100644 index c4433879..00000000 --- a/.eslintcache +++ /dev/null @@ -1 +0,0 @@ -[{"/home/tempuser-h40j8e/run/codegen-output/kernel/kernel-typescript/src/version.ts":"1"},{"size":60,"mtime":1759276522735}] \ No newline at end of file From 4eb401f568ffe500a0150a5593a805626fef8466 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 1 Oct 2025 21:39:50 +0000 Subject: [PATCH 179/551] feat: Update oAPI and data model for proxy status --- .stats.yml | 4 ++-- src/resources/proxies.ts | 30 ++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index a1c1d77e..2223539e 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 51 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-d0090ff3ef876c554e7a1281d5cbe1666cf68aebfc60e05cb7f4302ee377b372.yml -openapi_spec_hash: 33fef541c420a28125f18cd1efc0d585 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-a880f2209deafc4a011da42eb52f1dac0308d18ae1daa1d7253edc3385c9b1c4.yml +openapi_spec_hash: ae5af3810d28e49a68b12f2bb2d2af0e config_hash: 49c2ff978aaa5ccb4ce324a72f116010 diff --git a/src/resources/proxies.ts b/src/resources/proxies.ts index 20ceea6b..f31138ef 100644 --- a/src/resources/proxies.ts +++ b/src/resources/proxies.ts @@ -61,10 +61,20 @@ export interface ProxyCreateResponse { | ProxyCreateResponse.MobileProxyConfig | ProxyCreateResponse.CustomProxyConfig; + /** + * Timestamp of the last health check performed on this proxy. + */ + last_checked?: string; + /** * Readable name of the proxy. */ name?: string; + + /** + * Current health status of the proxy. + */ + status?: 'available' | 'unavailable'; } export namespace ProxyCreateResponse { @@ -268,10 +278,20 @@ export interface ProxyRetrieveResponse { | ProxyRetrieveResponse.MobileProxyConfig | ProxyRetrieveResponse.CustomProxyConfig; + /** + * Timestamp of the last health check performed on this proxy. + */ + last_checked?: string; + /** * Readable name of the proxy. */ name?: string; + + /** + * Current health status of the proxy. + */ + status?: 'available' | 'unavailable'; } export namespace ProxyRetrieveResponse { @@ -478,10 +498,20 @@ export namespace ProxyListResponse { | ProxyListResponseItem.MobileProxyConfig | ProxyListResponseItem.CustomProxyConfig; + /** + * Timestamp of the last health check performed on this proxy. + */ + last_checked?: string; + /** * Readable name of the proxy. */ name?: string; + + /** + * Current health status of the proxy. + */ + status?: 'available' | 'unavailable'; } export namespace ProxyListResponseItem { From 21a64124f9ae72798a237eb870647109d01e4112 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 3 Oct 2025 17:27:39 +0000 Subject: [PATCH 180/551] feat: Http proxy --- .stats.yml | 4 ++-- src/resources/proxies.ts | 20 ++++++++++++++++++++ tests/api-resources/proxies.test.ts | 1 + 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 2223539e..0af2575f 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 51 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-a880f2209deafc4a011da42eb52f1dac0308d18ae1daa1d7253edc3385c9b1c4.yml -openapi_spec_hash: ae5af3810d28e49a68b12f2bb2d2af0e +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-8a6175a75caa75c3de5400edf97a34e526ac3f62c63955375437461581deb0c2.yml +openapi_spec_hash: 1a880e4ce337a0e44630e6d87ef5162a config_hash: 49c2ff978aaa5ccb4ce324a72f116010 diff --git a/src/resources/proxies.ts b/src/resources/proxies.ts index f31138ef..9aaaf842 100644 --- a/src/resources/proxies.ts +++ b/src/resources/proxies.ts @@ -71,6 +71,11 @@ export interface ProxyCreateResponse { */ name?: string; + /** + * Protocol to use for the proxy connection. + */ + protocol?: 'http' | 'https'; + /** * Current health status of the proxy. */ @@ -288,6 +293,11 @@ export interface ProxyRetrieveResponse { */ name?: string; + /** + * Protocol to use for the proxy connection. + */ + protocol?: 'http' | 'https'; + /** * Current health status of the proxy. */ @@ -508,6 +518,11 @@ export namespace ProxyListResponse { */ name?: string; + /** + * Protocol to use for the proxy connection. + */ + protocol?: 'http' | 'https'; + /** * Current health status of the proxy. */ @@ -715,6 +730,11 @@ export interface ProxyCreateParams { * Readable name of the proxy. */ name?: string; + + /** + * Protocol to use for the proxy connection. + */ + protocol?: 'http' | 'https'; } export namespace ProxyCreateParams { diff --git a/tests/api-resources/proxies.test.ts b/tests/api-resources/proxies.test.ts index 97087a29..ebc101ad 100644 --- a/tests/api-resources/proxies.test.ts +++ b/tests/api-resources/proxies.test.ts @@ -26,6 +26,7 @@ describe('resource proxies', () => { type: 'datacenter', config: { country: 'US' }, name: 'name', + protocol: 'http', }); }); From 5cae68fd63e4adcad255f5a8eeeed546ac087d39 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 3 Oct 2025 17:32:51 +0000 Subject: [PATCH 181/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 8032c17e..ed21d28c 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.12.0" + ".": "0.13.0" } diff --git a/package.json b/package.json index a2c1b60d..92fc936e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.12.0", + "version": "0.13.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index ce6b8992..9d013cc2 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.12.0'; // x-release-please-version +export const VERSION = '0.13.0'; // x-release-please-version From 8fa1955c8a08283a5c635a726c4b77af8dcaebb5 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 4 Oct 2025 02:21:20 +0000 Subject: [PATCH 182/551] =?UTF-8?q?chore(jsdoc):=20fix=20@link=20annotatio?= =?UTF-8?q?ns=20to=20refer=20only=20to=20parts=20of=20the=20package?= =?UTF-8?q?=E2=80=98s=20public=20interface?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/internal/to-file.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/internal/to-file.ts b/src/internal/to-file.ts index 245e8493..30eada32 100644 --- a/src/internal/to-file.ts +++ b/src/internal/to-file.ts @@ -73,7 +73,7 @@ export type ToFileInput = /** * Helper for creating a {@link File} to pass to an SDK upload method from a variety of different data formats - * @param value the raw content of the file. Can be an {@link Uploadable}, {@link BlobLikePart}, or {@link AsyncIterable} of {@link BlobLikePart}s + * @param value the raw content of the file. Can be an {@link Uploadable}, BlobLikePart, or AsyncIterable of BlobLikeParts * @param {string=} name the name of the file. If omitted, toFile will try to determine a file name from bits if possible * @param {Object=} options additional properties * @param {string=} options.type the MIME type of the content From 1ccb2847a2cf9613c9e19d6b7e06c1cc4cb9d2c0 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 7 Oct 2025 02:47:17 +0000 Subject: [PATCH 183/551] chore(internal): use npm pack for build uploads --- scripts/utils/upload-artifact.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/scripts/utils/upload-artifact.sh b/scripts/utils/upload-artifact.sh index 38abeb4a..efeeb16a 100755 --- a/scripts/utils/upload-artifact.sh +++ b/scripts/utils/upload-artifact.sh @@ -12,9 +12,11 @@ if [[ "$SIGNED_URL" == "null" ]]; then exit 1 fi -UPLOAD_RESPONSE=$(tar "${BASE_PATH:+-C$BASE_PATH}" -cz "${ARTIFACT_PATH:-dist}" | curl -v -X PUT \ +TARBALL=$(cd dist && npm pack --silent) + +UPLOAD_RESPONSE=$(curl -v -X PUT \ -H "Content-Type: application/gzip" \ - --data-binary @- "$SIGNED_URL" 2>&1) + --data-binary "@dist/$TARBALL" "$SIGNED_URL" 2>&1) if echo "$UPLOAD_RESPONSE" | grep -q "HTTP/[0-9.]* 200"; then echo -e "\033[32mUploaded build to Stainless storage.\033[0m" From 261ce8d9ba3ceb0fa556490a4b03a46696ea2ff3 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 7 Oct 2025 13:43:59 +0000 Subject: [PATCH 184/551] feat: WIP browser extensions --- .stats.yml | 8 +- api.md | 16 ++ src/client.ts | 19 ++ src/resources/browsers/browsers.ts | 77 +++++++ src/resources/browsers/index.ts | 1 + src/resources/extensions.ts | 200 ++++++++++++++++++ src/resources/index.ts | 8 + tests/api-resources/browsers/browsers.test.ts | 24 ++- tests/api-resources/extensions.test.ts | 60 ++++++ 9 files changed, 408 insertions(+), 5 deletions(-) create mode 100644 src/resources/extensions.ts create mode 100644 tests/api-resources/extensions.test.ts diff --git a/.stats.yml b/.stats.yml index 0af2575f..b296ff8f 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 51 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-8a6175a75caa75c3de5400edf97a34e526ac3f62c63955375437461581deb0c2.yml -openapi_spec_hash: 1a880e4ce337a0e44630e6d87ef5162a -config_hash: 49c2ff978aaa5ccb4ce324a72f116010 +configured_endpoints: 57 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-936db268b3dcae5d64bd5d590506d8134304ffcbf67389eb9b1555b3febfd4cb.yml +openapi_spec_hash: 145485087adf1b28c052bacb4df68462 +config_hash: 5236f9b34e39dc1930e36a88c714abd4 diff --git a/api.md b/api.md index 9165c58a..9bf2b7d6 100644 --- a/api.md +++ b/api.md @@ -73,6 +73,7 @@ Methods: - client.browsers.list() -> BrowserListResponse - client.browsers.delete({ ...params }) -> void - client.browsers.deleteByID(id) -> void +- client.browsers.uploadExtensions(id, { ...params }) -> void ## Replays @@ -177,3 +178,18 @@ Methods: - client.proxies.retrieve(id) -> ProxyRetrieveResponse - client.proxies.list() -> ProxyListResponse - client.proxies.delete(id) -> void + +# Extensions + +Types: + +- ExtensionListResponse +- ExtensionUploadResponse + +Methods: + +- client.extensions.list() -> ExtensionListResponse +- client.extensions.delete(idOrName) -> void +- client.extensions.download(idOrName) -> Response +- client.extensions.downloadFromChromeStore({ ...params }) -> Response +- client.extensions.upload({ ...params }) -> ExtensionUploadResponse diff --git a/src/client.ts b/src/client.ts index 4d0906f3..39dcfce7 100644 --- a/src/client.ts +++ b/src/client.ts @@ -31,6 +31,13 @@ import { DeploymentStateEvent, Deployments, } from './resources/deployments'; +import { + ExtensionDownloadFromChromeStoreParams, + ExtensionListResponse, + ExtensionUploadParams, + ExtensionUploadResponse, + Extensions, +} from './resources/extensions'; import { InvocationCreateParams, InvocationCreateResponse, @@ -60,6 +67,7 @@ import { BrowserListResponse, BrowserPersistence, BrowserRetrieveResponse, + BrowserUploadExtensionsParams, Browsers, Profile, } from './resources/browsers/browsers'; @@ -809,6 +817,7 @@ export class Kernel { browsers: API.Browsers = new API.Browsers(this); profiles: API.Profiles = new API.Profiles(this); proxies: API.Proxies = new API.Proxies(this); + extensions: API.Extensions = new API.Extensions(this); } Kernel.Deployments = Deployments; @@ -817,6 +826,7 @@ Kernel.Invocations = Invocations; Kernel.Browsers = Browsers; Kernel.Profiles = Profiles; Kernel.Proxies = Proxies; +Kernel.Extensions = Extensions; export declare namespace Kernel { export type RequestOptions = Opts.RequestOptions; @@ -866,6 +876,7 @@ export declare namespace Kernel { type BrowserListResponse as BrowserListResponse, type BrowserCreateParams as BrowserCreateParams, type BrowserDeleteParams as BrowserDeleteParams, + type BrowserUploadExtensionsParams as BrowserUploadExtensionsParams, }; export { @@ -882,6 +893,14 @@ export declare namespace Kernel { type ProxyCreateParams as ProxyCreateParams, }; + export { + Extensions as Extensions, + type ExtensionListResponse as ExtensionListResponse, + type ExtensionUploadResponse as ExtensionUploadResponse, + type ExtensionDownloadFromChromeStoreParams as ExtensionDownloadFromChromeStoreParams, + type ExtensionUploadParams as ExtensionUploadParams, + }; + export type AppAction = API.AppAction; export type ErrorDetail = API.ErrorDetail; export type ErrorEvent = API.ErrorEvent; diff --git a/src/resources/browsers/browsers.ts b/src/resources/browsers/browsers.ts index 83681942..32681daf 100644 --- a/src/resources/browsers/browsers.ts +++ b/src/resources/browsers/browsers.ts @@ -48,8 +48,10 @@ import { Fs, } from './fs/fs'; import { APIPromise } from '../../core/api-promise'; +import { type Uploadable } from '../../core/uploads'; import { buildHeaders } from '../../internal/headers'; import { RequestOptions } from '../../internal/request-options'; +import { multipartFormRequestOptions } from '../../internal/uploads'; import { path } from '../../internal/utils/path'; export class Browsers extends APIResource { @@ -134,6 +136,36 @@ export class Browsers extends APIResource { headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), }); } + + /** + * Loads one or more unpacked extensions and restarts Chromium on the browser + * instance. + * + * @example + * ```ts + * await client.browsers.uploadExtensions('id', { + * extensions: [ + * { + * name: 'name', + * zip_file: fs.createReadStream('path/to/file'), + * }, + * ], + * }); + * ``` + */ + uploadExtensions( + id: string, + body: BrowserUploadExtensionsParams, + options?: RequestOptions, + ): APIPromise { + return this._client.post( + path`/browsers/${id}/extensions`, + multipartFormRequestOptions( + { body, ...options, headers: buildHeaders([{ Accept: '*/*' }, options?.headers]) }, + this._client, + ), + ); + } } /** @@ -340,6 +372,11 @@ export namespace BrowserListResponse { } export interface BrowserCreateParams { + /** + * List of browser extensions to load into the session. Provide each by id or name. + */ + extensions?: Array; + /** * If true, launches the browser using a headless image (no VNC/GUI). Defaults to * false. @@ -387,6 +424,23 @@ export interface BrowserCreateParams { } export namespace BrowserCreateParams { + /** + * Extension selection for the browser session. Provide either id or name of an + * extension uploaded to Kernel. + */ + export interface Extension { + /** + * Extension ID to load for this browser session + */ + id?: string; + + /** + * Extension name to load for this browser session (instead of id). Must be 1-255 + * characters, using letters, numbers, dots, underscores, or hyphens. + */ + name?: string; + } + /** * Profile selection for the browser session. Provide either id or name. If * specified, the matching profile will be loaded into the browser session. @@ -419,6 +473,28 @@ export interface BrowserDeleteParams { persistent_id: string; } +export interface BrowserUploadExtensionsParams { + /** + * List of extensions to upload and activate + */ + extensions: Array; +} + +export namespace BrowserUploadExtensionsParams { + export interface Extension { + /** + * Folder name to place the extension under /home/kernel/extensions/ + */ + name: string; + + /** + * Zip archive containing an unpacked Chromium extension (must include + * manifest.json) + */ + zip_file: Uploadable; + } +} + Browsers.Replays = Replays; Browsers.Fs = Fs; Browsers.Process = Process; @@ -433,6 +509,7 @@ export declare namespace Browsers { type BrowserListResponse as BrowserListResponse, type BrowserCreateParams as BrowserCreateParams, type BrowserDeleteParams as BrowserDeleteParams, + type BrowserUploadExtensionsParams as BrowserUploadExtensionsParams, }; export { diff --git a/src/resources/browsers/index.ts b/src/resources/browsers/index.ts index bcd5b403..71eab3bf 100644 --- a/src/resources/browsers/index.ts +++ b/src/resources/browsers/index.ts @@ -9,6 +9,7 @@ export { type BrowserListResponse, type BrowserCreateParams, type BrowserDeleteParams, + type BrowserUploadExtensionsParams, } from './browsers'; export { Fs, diff --git a/src/resources/extensions.ts b/src/resources/extensions.ts new file mode 100644 index 00000000..5697a075 --- /dev/null +++ b/src/resources/extensions.ts @@ -0,0 +1,200 @@ +// 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 { type Uploadable } from '../core/uploads'; +import { buildHeaders } from '../internal/headers'; +import { RequestOptions } from '../internal/request-options'; +import { multipartFormRequestOptions } from '../internal/uploads'; +import { path } from '../internal/utils/path'; + +export class Extensions extends APIResource { + /** + * List extensions owned by the caller's organization. + * + * @example + * ```ts + * const extensions = await client.extensions.list(); + * ``` + */ + list(options?: RequestOptions): APIPromise { + return this._client.get('/extensions', options); + } + + /** + * Delete an extension by its ID or by its name. + * + * @example + * ```ts + * await client.extensions.delete('id_or_name'); + * ``` + */ + delete(idOrName: string, options?: RequestOptions): APIPromise { + return this._client.delete(path`/extensions/${idOrName}`, { + ...options, + headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), + }); + } + + /** + * Download the extension as a ZIP archive by ID or name. + * + * @example + * ```ts + * const response = await client.extensions.download( + * 'id_or_name', + * ); + * + * const content = await response.blob(); + * console.log(content); + * ``` + */ + download(idOrName: string, options?: RequestOptions): APIPromise { + return this._client.get(path`/extensions/${idOrName}`, { + ...options, + headers: buildHeaders([{ Accept: 'application/octet-stream' }, options?.headers]), + __binaryResponse: true, + }); + } + + /** + * Returns a ZIP archive containing the unpacked extension fetched from the Chrome + * Web Store. + * + * @example + * ```ts + * const response = + * await client.extensions.downloadFromChromeStore({ + * url: 'url', + * }); + * + * const content = await response.blob(); + * console.log(content); + * ``` + */ + downloadFromChromeStore( + query: ExtensionDownloadFromChromeStoreParams, + options?: RequestOptions, + ): APIPromise { + return this._client.get('/extensions/from_chrome_store', { + query, + ...options, + headers: buildHeaders([{ Accept: 'application/octet-stream' }, options?.headers]), + __binaryResponse: true, + }); + } + + /** + * Upload a zip file containing an unpacked browser extension. Optionally provide a + * unique name for later reference. + * + * @example + * ```ts + * const response = await client.extensions.upload({ + * file: fs.createReadStream('path/to/file'), + * }); + * ``` + */ + upload(body: ExtensionUploadParams, options?: RequestOptions): APIPromise { + return this._client.post('/extensions', multipartFormRequestOptions({ body, ...options }, this._client)); + } +} + +export type ExtensionListResponse = Array; + +export namespace ExtensionListResponse { + /** + * A browser extension uploaded to Kernel. + */ + export interface ExtensionListResponseItem { + /** + * Unique identifier for the extension + */ + id: string; + + /** + * Timestamp when the extension was created + */ + created_at: string; + + /** + * Size of the extension archive in bytes + */ + size_bytes: number; + + /** + * Timestamp when the extension was last used + */ + last_used_at?: string | null; + + /** + * Optional, easier-to-reference name for the extension. Must be unique within the + * organization. + */ + name?: string | null; + } +} + +/** + * A browser extension uploaded to Kernel. + */ +export interface ExtensionUploadResponse { + /** + * Unique identifier for the extension + */ + id: string; + + /** + * Timestamp when the extension was created + */ + created_at: string; + + /** + * Size of the extension archive in bytes + */ + size_bytes: number; + + /** + * Timestamp when the extension was last used + */ + last_used_at?: string | null; + + /** + * Optional, easier-to-reference name for the extension. Must be unique within the + * organization. + */ + name?: string | null; +} + +export interface ExtensionDownloadFromChromeStoreParams { + /** + * Chrome Web Store URL for the extension. + */ + url: string; + + /** + * Target operating system for the extension package. Defaults to linux. + */ + os?: 'win' | 'mac' | 'linux'; +} + +export interface ExtensionUploadParams { + /** + * ZIP file containing the browser extension. + */ + file: Uploadable; + + /** + * Optional unique name within the organization to reference this extension. + */ + name?: string; +} + +export declare namespace Extensions { + export { + type ExtensionListResponse as ExtensionListResponse, + type ExtensionUploadResponse as ExtensionUploadResponse, + type ExtensionDownloadFromChromeStoreParams as ExtensionDownloadFromChromeStoreParams, + type ExtensionUploadParams as ExtensionUploadParams, + }; +} diff --git a/src/resources/index.ts b/src/resources/index.ts index 0288a65b..37026ae0 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -11,6 +11,7 @@ export { type BrowserListResponse, type BrowserCreateParams, type BrowserDeleteParams, + type BrowserUploadExtensionsParams, } from './browsers/browsers'; export { Deployments, @@ -24,6 +25,13 @@ export { type DeploymentFollowParams, type DeploymentListResponsesOffsetPagination, } from './deployments'; +export { + Extensions, + type ExtensionListResponse, + type ExtensionUploadResponse, + type ExtensionDownloadFromChromeStoreParams, + type ExtensionUploadParams, +} from './extensions'; export { Invocations, type InvocationStateEvent, diff --git a/tests/api-resources/browsers/browsers.test.ts b/tests/api-resources/browsers/browsers.test.ts index 3434e726..8d573b64 100644 --- a/tests/api-resources/browsers/browsers.test.ts +++ b/tests/api-resources/browsers/browsers.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Kernel from '@onkernel/sdk'; +import Kernel, { toFile } from '@onkernel/sdk'; const client = new Kernel({ apiKey: 'My API Key', @@ -26,6 +26,7 @@ describe('resource browsers', () => { await expect( client.browsers.create( { + extensions: [{ id: 'id', name: 'name' }], headless: false, invocation_id: 'rr33xuugxj9h0bkf1rdt2bet', persistence: { id: 'my-awesome-browser-for-user-1234' }, @@ -91,4 +92,25 @@ describe('resource browsers', () => { expect(dataAndResponse.data).toBe(response); expect(dataAndResponse.response).toBe(rawResponse); }); + + // Prism tests are disabled + test.skip('uploadExtensions: only required params', async () => { + const responsePromise = client.browsers.uploadExtensions('id', { + extensions: [{ name: 'name', zip_file: await toFile(Buffer.from('# my file contents'), 'README.md') }], + }); + 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); + }); + + // Prism tests are disabled + test.skip('uploadExtensions: required and optional params', async () => { + const response = await client.browsers.uploadExtensions('id', { + extensions: [{ name: 'name', zip_file: await toFile(Buffer.from('# my file contents'), 'README.md') }], + }); + }); }); diff --git a/tests/api-resources/extensions.test.ts b/tests/api-resources/extensions.test.ts new file mode 100644 index 00000000..515415fe --- /dev/null +++ b/tests/api-resources/extensions.test.ts @@ -0,0 +1,60 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import Kernel, { toFile } 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 extensions', () => { + // Prism tests are disabled + test.skip('list', async () => { + const responsePromise = client.extensions.list(); + 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); + }); + + // Prism tests are disabled + test.skip('delete', async () => { + const responsePromise = client.extensions.delete('id_or_name'); + 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); + }); + + test('downloadFromChromeStore: required and optional params', async () => { + const response = await client.extensions.downloadFromChromeStore({ url: 'url', os: 'win' }); + }); + + // Prism tests are disabled + test.skip('upload: only required params', async () => { + const responsePromise = client.extensions.upload({ + file: await toFile(Buffer.from('# my file contents'), 'README.md'), + }); + 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); + }); + + // Prism tests are disabled + test.skip('upload: required and optional params', async () => { + const response = await client.extensions.upload({ + file: await toFile(Buffer.from('# my file contents'), 'README.md'), + name: 'name', + }); + }); +}); From 52922aee5d191406fd44781c59e97f78bee9b20d Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 7 Oct 2025 13:51:57 +0000 Subject: [PATCH 185/551] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index b296ff8f..f577dd04 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 57 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-936db268b3dcae5d64bd5d590506d8134304ffcbf67389eb9b1555b3febfd4cb.yml openapi_spec_hash: 145485087adf1b28c052bacb4df68462 -config_hash: 5236f9b34e39dc1930e36a88c714abd4 +config_hash: 15cd063f8e308686ac71bf9ee9634625 From 17135fada7e816029a26b2a5a03cec9e89080a7a Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 7 Oct 2025 14:11:26 +0000 Subject: [PATCH 186/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index ed21d28c..727e2bea 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.13.0" + ".": "0.14.0" } diff --git a/package.json b/package.json index 92fc936e..eebd87bc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.13.0", + "version": "0.14.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 9d013cc2..e2b0672c 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.13.0'; // x-release-please-version +export const VERSION = '0.14.0'; // x-release-please-version From 0c59ba686b880411e59b2d3d3a4cc9c2b199110c Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 7 Oct 2025 15:01:50 +0000 Subject: [PATCH 187/551] feat: Hide and deprecate mobile proxy type --- .stats.yml | 4 ++-- src/resources/proxies.ts | 48 +++++++++++++++++----------------------- 2 files changed, 22 insertions(+), 30 deletions(-) diff --git a/.stats.yml b/.stats.yml index f577dd04..136236ae 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 57 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-936db268b3dcae5d64bd5d590506d8134304ffcbf67389eb9b1555b3febfd4cb.yml -openapi_spec_hash: 145485087adf1b28c052bacb4df68462 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-592ab7a96084f7241d77b4cc1ce2a074795b0dc40d8247e1a0129fe3f89c1ed4.yml +openapi_spec_hash: 3a23b4c9c05946251be45c5c4e7a415d config_hash: 15cd063f8e308686ac71bf9ee9634625 diff --git a/src/resources/proxies.ts b/src/resources/proxies.ts index 9aaaf842..e6841d70 100644 --- a/src/resources/proxies.ts +++ b/src/resources/proxies.ts @@ -88,7 +88,7 @@ export namespace ProxyCreateResponse { */ export interface DatacenterProxyConfig { /** - * ISO 3166 country code or EU for the proxy exit node. + * ISO 3166 country code. */ country: string; } @@ -98,7 +98,7 @@ export namespace ProxyCreateResponse { */ export interface IspProxyConfig { /** - * ISO 3166 country code or EU for the proxy exit node. + * ISO 3166 country code. */ country: string; } @@ -119,13 +119,12 @@ export namespace ProxyCreateResponse { city?: string; /** - * ISO 3166 country code or EU for the proxy exit node. Required if `city` is - * provided. + * ISO 3166 country code. */ country?: string; /** - * Operating system of the residential device. + * @deprecated Operating system of the residential device. */ os?: 'windows' | 'macos' | 'android'; @@ -219,8 +218,7 @@ export namespace ProxyCreateResponse { city?: string; /** - * ISO 3166 country code or EU for the proxy exit node. Required if `city` is - * provided. + * ISO 3166 country code */ country?: string; @@ -310,7 +308,7 @@ export namespace ProxyRetrieveResponse { */ export interface DatacenterProxyConfig { /** - * ISO 3166 country code or EU for the proxy exit node. + * ISO 3166 country code. */ country: string; } @@ -320,7 +318,7 @@ export namespace ProxyRetrieveResponse { */ export interface IspProxyConfig { /** - * ISO 3166 country code or EU for the proxy exit node. + * ISO 3166 country code. */ country: string; } @@ -341,13 +339,12 @@ export namespace ProxyRetrieveResponse { city?: string; /** - * ISO 3166 country code or EU for the proxy exit node. Required if `city` is - * provided. + * ISO 3166 country code. */ country?: string; /** - * Operating system of the residential device. + * @deprecated Operating system of the residential device. */ os?: 'windows' | 'macos' | 'android'; @@ -441,8 +438,7 @@ export namespace ProxyRetrieveResponse { city?: string; /** - * ISO 3166 country code or EU for the proxy exit node. Required if `city` is - * provided. + * ISO 3166 country code */ country?: string; @@ -535,7 +531,7 @@ export namespace ProxyListResponse { */ export interface DatacenterProxyConfig { /** - * ISO 3166 country code or EU for the proxy exit node. + * ISO 3166 country code. */ country: string; } @@ -545,7 +541,7 @@ export namespace ProxyListResponse { */ export interface IspProxyConfig { /** - * ISO 3166 country code or EU for the proxy exit node. + * ISO 3166 country code. */ country: string; } @@ -566,13 +562,12 @@ export namespace ProxyListResponse { city?: string; /** - * ISO 3166 country code or EU for the proxy exit node. Required if `city` is - * provided. + * ISO 3166 country code. */ country?: string; /** - * Operating system of the residential device. + * @deprecated Operating system of the residential device. */ os?: 'windows' | 'macos' | 'android'; @@ -666,8 +661,7 @@ export namespace ProxyListResponse { city?: string; /** - * ISO 3166 country code or EU for the proxy exit node. Required if `city` is - * provided. + * ISO 3166 country code */ country?: string; @@ -743,7 +737,7 @@ export namespace ProxyCreateParams { */ export interface DatacenterProxyConfig { /** - * ISO 3166 country code or EU for the proxy exit node. + * ISO 3166 country code. */ country: string; } @@ -753,7 +747,7 @@ export namespace ProxyCreateParams { */ export interface IspProxyConfig { /** - * ISO 3166 country code or EU for the proxy exit node. + * ISO 3166 country code. */ country: string; } @@ -774,13 +768,12 @@ export namespace ProxyCreateParams { city?: string; /** - * ISO 3166 country code or EU for the proxy exit node. Required if `city` is - * provided. + * ISO 3166 country code. */ country?: string; /** - * Operating system of the residential device. + * @deprecated Operating system of the residential device. */ os?: 'windows' | 'macos' | 'android'; @@ -874,8 +867,7 @@ export namespace ProxyCreateParams { city?: string; /** - * ISO 3166 country code or EU for the proxy exit node. Required if `city` is - * provided. + * ISO 3166 country code */ country?: string; From e3fdac214c63f35c1a08f425851d04bf1d87f866 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 13 Oct 2025 15:40:59 +0000 Subject: [PATCH 188/551] feat: WIP: Configurable Viewport --- .stats.yml | 6 +- api.md | 2 +- src/client.ts | 4 +- src/resources/browsers/browsers.ts | 182 +++++++++++++++++- src/resources/browsers/index.ts | 2 +- src/resources/index.ts | 2 +- tests/api-resources/browsers/browsers.test.ts | 9 +- 7 files changed, 185 insertions(+), 22 deletions(-) diff --git a/.stats.yml b/.stats.yml index 136236ae..99609550 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 57 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-592ab7a96084f7241d77b4cc1ce2a074795b0dc40d8247e1a0129fe3f89c1ed4.yml -openapi_spec_hash: 3a23b4c9c05946251be45c5c4e7a415d -config_hash: 15cd063f8e308686ac71bf9ee9634625 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-1cd328ccf61f0e888d6df27b091c30b38c392ab9ca8ce7fd0ead8f10aaf71ffa.yml +openapi_spec_hash: af761c48d1955f11822f3b95f9c46750 +config_hash: deadfc4d2b0a947673bcf559b5db6e1b diff --git a/api.md b/api.md index 9bf2b7d6..92e5d8d5 100644 --- a/api.md +++ b/api.md @@ -73,7 +73,7 @@ Methods: - client.browsers.list() -> BrowserListResponse - client.browsers.delete({ ...params }) -> void - client.browsers.deleteByID(id) -> void -- client.browsers.uploadExtensions(id, { ...params }) -> void +- client.browsers.loadExtensions(id, { ...params }) -> void ## Replays diff --git a/src/client.ts b/src/client.ts index 39dcfce7..510d650b 100644 --- a/src/client.ts +++ b/src/client.ts @@ -65,9 +65,9 @@ import { BrowserCreateResponse, BrowserDeleteParams, BrowserListResponse, + BrowserLoadExtensionsParams, BrowserPersistence, BrowserRetrieveResponse, - BrowserUploadExtensionsParams, Browsers, Profile, } from './resources/browsers/browsers'; @@ -876,7 +876,7 @@ export declare namespace Kernel { type BrowserListResponse as BrowserListResponse, type BrowserCreateParams as BrowserCreateParams, type BrowserDeleteParams as BrowserDeleteParams, - type BrowserUploadExtensionsParams as BrowserUploadExtensionsParams, + type BrowserLoadExtensionsParams as BrowserLoadExtensionsParams, }; export { diff --git a/src/resources/browsers/browsers.ts b/src/resources/browsers/browsers.ts index 32681daf..29716502 100644 --- a/src/resources/browsers/browsers.ts +++ b/src/resources/browsers/browsers.ts @@ -143,7 +143,7 @@ export class Browsers extends APIResource { * * @example * ```ts - * await client.browsers.uploadExtensions('id', { + * await client.browsers.loadExtensions('id', { * extensions: [ * { * name: 'name', @@ -153,11 +153,7 @@ export class Browsers extends APIResource { * }); * ``` */ - uploadExtensions( - id: string, - body: BrowserUploadExtensionsParams, - options?: RequestOptions, - ): APIPromise { + loadExtensions(id: string, body: BrowserLoadExtensionsParams, options?: RequestOptions): APIPromise { return this._client.post( path`/browsers/${id}/extensions`, multipartFormRequestOptions( @@ -259,6 +255,48 @@ export interface BrowserCreateResponse { * ID of the proxy associated with this browser session, if any. */ proxy_id?: string; + + /** + * Initial browser window size in pixels with optional refresh rate. If omitted, + * image defaults apply (commonly 1024x768@60). Only specific viewport + * configurations are supported. The server will reject unsupported combinations. + * Supported resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25, + * 1440x900@25, 1024x768@60 If refresh_rate is not provided, it will be + * automatically determined from the width and height if they match a supported + * configuration exactly. Note: Higher resolutions may affect the responsiveness of + * live view browser + */ + viewport?: BrowserCreateResponse.Viewport; +} + +export namespace BrowserCreateResponse { + /** + * Initial browser window size in pixels with optional refresh rate. If omitted, + * image defaults apply (commonly 1024x768@60). Only specific viewport + * configurations are supported. The server will reject unsupported combinations. + * Supported resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25, + * 1440x900@25, 1024x768@60 If refresh_rate is not provided, it will be + * automatically determined from the width and height if they match a supported + * configuration exactly. Note: Higher resolutions may affect the responsiveness of + * live view browser + */ + export interface Viewport { + /** + * Browser window height in pixels. + */ + height: number; + + /** + * Browser window width in pixels. + */ + width: number; + + /** + * Display refresh rate in Hz. If omitted, automatically determined from width and + * height. + */ + refresh_rate?: number; + } } export interface BrowserRetrieveResponse { @@ -312,6 +350,48 @@ export interface BrowserRetrieveResponse { * ID of the proxy associated with this browser session, if any. */ proxy_id?: string; + + /** + * Initial browser window size in pixels with optional refresh rate. If omitted, + * image defaults apply (commonly 1024x768@60). Only specific viewport + * configurations are supported. The server will reject unsupported combinations. + * Supported resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25, + * 1440x900@25, 1024x768@60 If refresh_rate is not provided, it will be + * automatically determined from the width and height if they match a supported + * configuration exactly. Note: Higher resolutions may affect the responsiveness of + * live view browser + */ + viewport?: BrowserRetrieveResponse.Viewport; +} + +export namespace BrowserRetrieveResponse { + /** + * Initial browser window size in pixels with optional refresh rate. If omitted, + * image defaults apply (commonly 1024x768@60). Only specific viewport + * configurations are supported. The server will reject unsupported combinations. + * Supported resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25, + * 1440x900@25, 1024x768@60 If refresh_rate is not provided, it will be + * automatically determined from the width and height if they match a supported + * configuration exactly. Note: Higher resolutions may affect the responsiveness of + * live view browser + */ + export interface Viewport { + /** + * Browser window height in pixels. + */ + height: number; + + /** + * Browser window width in pixels. + */ + width: number; + + /** + * Display refresh rate in Hz. If omitted, automatically determined from width and + * height. + */ + refresh_rate?: number; + } } export type BrowserListResponse = Array; @@ -368,6 +448,48 @@ export namespace BrowserListResponse { * ID of the proxy associated with this browser session, if any. */ proxy_id?: string; + + /** + * Initial browser window size in pixels with optional refresh rate. If omitted, + * image defaults apply (commonly 1024x768@60). Only specific viewport + * configurations are supported. The server will reject unsupported combinations. + * Supported resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25, + * 1440x900@25, 1024x768@60 If refresh_rate is not provided, it will be + * automatically determined from the width and height if they match a supported + * configuration exactly. Note: Higher resolutions may affect the responsiveness of + * live view browser + */ + viewport?: BrowserListResponseItem.Viewport; + } + + export namespace BrowserListResponseItem { + /** + * Initial browser window size in pixels with optional refresh rate. If omitted, + * image defaults apply (commonly 1024x768@60). Only specific viewport + * configurations are supported. The server will reject unsupported combinations. + * Supported resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25, + * 1440x900@25, 1024x768@60 If refresh_rate is not provided, it will be + * automatically determined from the width and height if they match a supported + * configuration exactly. Note: Higher resolutions may affect the responsiveness of + * live view browser + */ + export interface Viewport { + /** + * Browser window height in pixels. + */ + height: number; + + /** + * Browser window width in pixels. + */ + width: number; + + /** + * Display refresh rate in Hz. If omitted, automatically determined from width and + * height. + */ + refresh_rate?: number; + } } } @@ -421,6 +543,18 @@ export interface BrowserCreateParams { * specified value. */ timeout_seconds?: number; + + /** + * Initial browser window size in pixels with optional refresh rate. If omitted, + * image defaults apply (commonly 1024x768@60). Only specific viewport + * configurations are supported. The server will reject unsupported combinations. + * Supported resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25, + * 1440x900@25, 1024x768@60 If refresh_rate is not provided, it will be + * automatically determined from the width and height if they match a supported + * configuration exactly. Note: Higher resolutions may affect the responsiveness of + * live view browser + */ + viewport?: BrowserCreateParams.Viewport; } export namespace BrowserCreateParams { @@ -464,6 +598,34 @@ export namespace BrowserCreateParams { */ save_changes?: boolean; } + + /** + * Initial browser window size in pixels with optional refresh rate. If omitted, + * image defaults apply (commonly 1024x768@60). Only specific viewport + * configurations are supported. The server will reject unsupported combinations. + * Supported resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25, + * 1440x900@25, 1024x768@60 If refresh_rate is not provided, it will be + * automatically determined from the width and height if they match a supported + * configuration exactly. Note: Higher resolutions may affect the responsiveness of + * live view browser + */ + export interface Viewport { + /** + * Browser window height in pixels. + */ + height: number; + + /** + * Browser window width in pixels. + */ + width: number; + + /** + * Display refresh rate in Hz. If omitted, automatically determined from width and + * height. + */ + refresh_rate?: number; + } } export interface BrowserDeleteParams { @@ -473,14 +635,14 @@ export interface BrowserDeleteParams { persistent_id: string; } -export interface BrowserUploadExtensionsParams { +export interface BrowserLoadExtensionsParams { /** * List of extensions to upload and activate */ - extensions: Array; + extensions: Array; } -export namespace BrowserUploadExtensionsParams { +export namespace BrowserLoadExtensionsParams { export interface Extension { /** * Folder name to place the extension under /home/kernel/extensions/ @@ -509,7 +671,7 @@ export declare namespace Browsers { type BrowserListResponse as BrowserListResponse, type BrowserCreateParams as BrowserCreateParams, type BrowserDeleteParams as BrowserDeleteParams, - type BrowserUploadExtensionsParams as BrowserUploadExtensionsParams, + type BrowserLoadExtensionsParams as BrowserLoadExtensionsParams, }; export { diff --git a/src/resources/browsers/index.ts b/src/resources/browsers/index.ts index 71eab3bf..53bb8a9f 100644 --- a/src/resources/browsers/index.ts +++ b/src/resources/browsers/index.ts @@ -9,7 +9,7 @@ export { type BrowserListResponse, type BrowserCreateParams, type BrowserDeleteParams, - type BrowserUploadExtensionsParams, + type BrowserLoadExtensionsParams, } from './browsers'; export { Fs, diff --git a/src/resources/index.ts b/src/resources/index.ts index 37026ae0..83e43128 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -11,7 +11,7 @@ export { type BrowserListResponse, type BrowserCreateParams, type BrowserDeleteParams, - type BrowserUploadExtensionsParams, + type BrowserLoadExtensionsParams, } from './browsers/browsers'; export { Deployments, diff --git a/tests/api-resources/browsers/browsers.test.ts b/tests/api-resources/browsers/browsers.test.ts index 8d573b64..9c96f46e 100644 --- a/tests/api-resources/browsers/browsers.test.ts +++ b/tests/api-resources/browsers/browsers.test.ts @@ -34,6 +34,7 @@ describe('resource browsers', () => { proxy_id: 'proxy_id', stealth: true, timeout_seconds: 10, + viewport: { height: 800, width: 1280, refresh_rate: 60 }, }, { path: '/_stainless_unknown_path' }, ), @@ -94,8 +95,8 @@ describe('resource browsers', () => { }); // Prism tests are disabled - test.skip('uploadExtensions: only required params', async () => { - const responsePromise = client.browsers.uploadExtensions('id', { + test.skip('loadExtensions: only required params', async () => { + const responsePromise = client.browsers.loadExtensions('id', { extensions: [{ name: 'name', zip_file: await toFile(Buffer.from('# my file contents'), 'README.md') }], }); const rawResponse = await responsePromise.asResponse(); @@ -108,8 +109,8 @@ describe('resource browsers', () => { }); // Prism tests are disabled - test.skip('uploadExtensions: required and optional params', async () => { - const response = await client.browsers.uploadExtensions('id', { + test.skip('loadExtensions: required and optional params', async () => { + const response = await client.browsers.loadExtensions('id', { extensions: [{ name: 'name', zip_file: await toFile(Buffer.from('# my file contents'), 'README.md') }], }); }); From f0575a66685b255fffcf2d6bfcfb504b35743663 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 13 Oct 2025 15:47:16 +0000 Subject: [PATCH 189/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 727e2bea..7b5cb645 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.14.0" + ".": "0.14.1" } diff --git a/package.json b/package.json index eebd87bc..9d66def0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.14.0", + "version": "0.14.1", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index e2b0672c..85966e21 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.14.0'; // x-release-please-version +export const VERSION = '0.14.1'; // x-release-please-version From a8a247e31677e5f95fc1bb18b0eddb0983b0a4e6 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 16 Oct 2025 17:12:24 +0000 Subject: [PATCH 190/551] feat: Kiosk mode --- .stats.yml | 4 ++-- src/resources/browsers/browsers.ts | 21 +++++++++++++++++++ tests/api-resources/browsers/browsers.test.ts | 1 + 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 99609550..6bb4af83 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 57 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-1cd328ccf61f0e888d6df27b091c30b38c392ab9ca8ce7fd0ead8f10aaf71ffa.yml -openapi_spec_hash: af761c48d1955f11822f3b95f9c46750 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-6c765f1c4ce1c4dd4ceb371f56bf047aa79af36031ba43cbd68fa16a5fdb9bb3.yml +openapi_spec_hash: e9086f69281360f4e0895c9274a59531 config_hash: deadfc4d2b0a947673bcf559b5db6e1b diff --git a/src/resources/browsers/browsers.ts b/src/resources/browsers/browsers.ts index 29716502..97d0d77c 100644 --- a/src/resources/browsers/browsers.ts +++ b/src/resources/browsers/browsers.ts @@ -241,6 +241,11 @@ export interface BrowserCreateResponse { */ browser_live_view_url?: string; + /** + * Whether the browser session is running in kiosk mode. + */ + kiosk_mode?: boolean; + /** * Optional persistence configuration for the browser session. */ @@ -336,6 +341,11 @@ export interface BrowserRetrieveResponse { */ browser_live_view_url?: string; + /** + * Whether the browser session is running in kiosk mode. + */ + kiosk_mode?: boolean; + /** * Optional persistence configuration for the browser session. */ @@ -434,6 +444,11 @@ export namespace BrowserListResponse { */ browser_live_view_url?: string; + /** + * Whether the browser session is running in kiosk mode. + */ + kiosk_mode?: boolean; + /** * Optional persistence configuration for the browser session. */ @@ -510,6 +525,12 @@ export interface BrowserCreateParams { */ invocation_id?: string; + /** + * If true, launches the browser in kiosk mode to hide address bar and tabs in live + * view. + */ + kiosk_mode?: boolean; + /** * Optional persistence configuration for the browser session. */ diff --git a/tests/api-resources/browsers/browsers.test.ts b/tests/api-resources/browsers/browsers.test.ts index 9c96f46e..14ec8f84 100644 --- a/tests/api-resources/browsers/browsers.test.ts +++ b/tests/api-resources/browsers/browsers.test.ts @@ -29,6 +29,7 @@ describe('resource browsers', () => { extensions: [{ id: 'id', name: 'name' }], headless: false, invocation_id: 'rr33xuugxj9h0bkf1rdt2bet', + kiosk_mode: true, persistence: { id: 'my-awesome-browser-for-user-1234' }, profile: { id: 'id', name: 'name', save_changes: true }, proxy_id: 'proxy_id', From 88466bc332fd79f38b97f32b184a15d9ae4bd8b9 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 16 Oct 2025 17:29:16 +0000 Subject: [PATCH 191/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 7b5cb645..b19a3f40 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.14.1" + ".": "0.14.2" } diff --git a/package.json b/package.json index 9d66def0..2d371a8c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.14.1", + "version": "0.14.2", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 85966e21..0af0c850 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.14.1'; // x-release-please-version +export const VERSION = '0.14.2'; // x-release-please-version From 90cf7938f21a774a43282f0accea09f71aab5305 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 16 Oct 2025 20:31:22 +0000 Subject: [PATCH 192/551] feat: Phani/deploy with GitHub url --- .stats.yml | 6 +- README.md | 22 +--- api.md | 6 +- src/client.ts | 8 +- src/resources/deployments.ts | 74 +++++++++++-- src/resources/extensions.ts | 138 ++++++++++++------------ src/resources/index.ts | 4 +- tests/api-resources/deployments.test.ts | 21 +--- tests/api-resources/extensions.test.ts | 36 +++---- 9 files changed, 175 insertions(+), 140 deletions(-) diff --git a/.stats.yml b/.stats.yml index 6bb4af83..2bd40ccf 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 57 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-6c765f1c4ce1c4dd4ceb371f56bf047aa79af36031ba43cbd68fa16a5fdb9bb3.yml -openapi_spec_hash: e9086f69281360f4e0895c9274a59531 -config_hash: deadfc4d2b0a947673bcf559b5db6e1b +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-6eaa6f5654abc94549962d7db1e8c7936af1f815bb3abe2f8249959394da1278.yml +openapi_spec_hash: 31ece7cd801e74228b80a8112a762e56 +config_hash: 3fc2057ce765bc5f27785a694ed0f553 diff --git a/README.md b/README.md index fa69c0cb..0018d91e 100644 --- a/README.md +++ b/README.md @@ -67,29 +67,17 @@ import Kernel, { toFile } from '@onkernel/sdk'; const client = new Kernel(); // If you have access to Node `fs` we recommend using `fs.createReadStream()`: -await client.deployments.create({ - entrypoint_rel_path: 'src/app.py', - file: fs.createReadStream('/path/to/file'), -}); +await client.deployments.create({ file: fs.createReadStream('/path/to/file') }); // Or if you have the web `File` API you can pass a `File` instance: -await client.deployments.create({ entrypoint_rel_path: 'src/app.py', file: new File(['my bytes'], 'file') }); +await client.deployments.create({ file: new File(['my bytes'], 'file') }); // You can also pass a `fetch` `Response`: -await client.deployments.create({ - entrypoint_rel_path: 'src/app.py', - file: await fetch('https://somesite/file'), -}); +await client.deployments.create({ file: await fetch('https://somesite/file') }); // Finally, if none of the above are convenient, you can use our `toFile` helper: -await client.deployments.create({ - entrypoint_rel_path: 'src/app.py', - file: await toFile(Buffer.from('my bytes'), 'file'), -}); -await client.deployments.create({ - entrypoint_rel_path: 'src/app.py', - file: await toFile(new Uint8Array([0, 1, 2]), 'file'), -}); +await client.deployments.create({ file: await toFile(Buffer.from('my bytes'), 'file') }); +await client.deployments.create({ file: await toFile(new Uint8Array([0, 1, 2]), 'file') }); ``` ## Handling errors diff --git a/api.md b/api.md index 92e5d8d5..b442f34b 100644 --- a/api.md +++ b/api.md @@ -183,13 +183,13 @@ Methods: Types: +- ExtensionCreateResponse - ExtensionListResponse -- ExtensionUploadResponse Methods: +- client.extensions.create({ ...params }) -> ExtensionCreateResponse +- client.extensions.retrieve(idOrName) -> Response - client.extensions.list() -> ExtensionListResponse - client.extensions.delete(idOrName) -> void -- client.extensions.download(idOrName) -> Response - client.extensions.downloadFromChromeStore({ ...params }) -> Response -- client.extensions.upload({ ...params }) -> ExtensionUploadResponse diff --git a/src/client.ts b/src/client.ts index 510d650b..96ad7cae 100644 --- a/src/client.ts +++ b/src/client.ts @@ -32,10 +32,10 @@ import { Deployments, } from './resources/deployments'; import { + ExtensionCreateParams, + ExtensionCreateResponse, ExtensionDownloadFromChromeStoreParams, ExtensionListResponse, - ExtensionUploadParams, - ExtensionUploadResponse, Extensions, } from './resources/extensions'; import { @@ -895,10 +895,10 @@ export declare namespace Kernel { export { Extensions as Extensions, + type ExtensionCreateResponse as ExtensionCreateResponse, type ExtensionListResponse as ExtensionListResponse, - type ExtensionUploadResponse as ExtensionUploadResponse, + type ExtensionCreateParams as ExtensionCreateParams, type ExtensionDownloadFromChromeStoreParams as ExtensionDownloadFromChromeStoreParams, - type ExtensionUploadParams as ExtensionUploadParams, }; export type AppAction = API.AppAction; diff --git a/src/resources/deployments.ts b/src/resources/deployments.ts index b9dfe5a0..c297548e 100644 --- a/src/resources/deployments.ts +++ b/src/resources/deployments.ts @@ -19,7 +19,10 @@ export class Deployments extends APIResource { * ```ts * const deployment = await client.deployments.create({ * entrypoint_rel_path: 'src/app.py', + * env_vars: { FOO: 'bar' }, * file: fs.createReadStream('path/to/file'), + * region: 'aws.us-east-1a', + * version: '1.0.0', * }); * ``` */ @@ -349,12 +352,7 @@ export interface DeploymentCreateParams { /** * Relative path to the entrypoint of the application */ - entrypoint_rel_path: string; - - /** - * ZIP file containing the application source directory - */ - file: Uploadable; + entrypoint_rel_path?: string; /** * Map of environment variables to set for the deployed application. Each key-value @@ -362,6 +360,11 @@ export interface DeploymentCreateParams { */ env_vars?: { [key: string]: string }; + /** + * ZIP file containing the application source directory + */ + file?: Uploadable; + /** * Allow overwriting an existing app version */ @@ -372,12 +375,71 @@ export interface DeploymentCreateParams { */ region?: 'aws.us-east-1a'; + /** + * Source from which to fetch application code. + */ + source?: DeploymentCreateParams.Source; + /** * Version of the application. Can be any string. */ version?: string; } +export namespace DeploymentCreateParams { + /** + * Source from which to fetch application code. + */ + export interface Source { + /** + * Relative path to the application entrypoint within the selected path. + */ + entrypoint: string; + + /** + * Git ref (branch, tag, or commit SHA) to fetch. + */ + ref: string; + + /** + * Source type identifier. + */ + type: 'github'; + + /** + * Base repository URL (without blob/tree suffixes). + */ + url: string; + + /** + * Authentication for private repositories. + */ + auth?: Source.Auth; + + /** + * Path within the repo to deploy (omit to use repo root). + */ + path?: string; + } + + export namespace Source { + /** + * Authentication for private repositories. + */ + export interface Auth { + /** + * GitHub PAT or installation access token + */ + token: string; + + /** + * Auth method + */ + method: 'github_token'; + } + } +} + export interface DeploymentListParams extends OffsetPaginationParams { /** * Filter results by application name. diff --git a/src/resources/extensions.ts b/src/resources/extensions.ts index 5697a075..82f29ba1 100644 --- a/src/resources/extensions.ts +++ b/src/resources/extensions.ts @@ -10,50 +10,65 @@ import { path } from '../internal/utils/path'; export class Extensions extends APIResource { /** - * List extensions owned by the caller's organization. + * Upload a zip file containing an unpacked browser extension. Optionally provide a + * unique name for later reference. * * @example * ```ts - * const extensions = await client.extensions.list(); + * const extension = await client.extensions.create({ + * file: fs.createReadStream('path/to/file'), + * }); * ``` */ - list(options?: RequestOptions): APIPromise { - return this._client.get('/extensions', options); + create(body: ExtensionCreateParams, options?: RequestOptions): APIPromise { + return this._client.post('/extensions', multipartFormRequestOptions({ body, ...options }, this._client)); } /** - * Delete an extension by its ID or by its name. + * Download the extension as a ZIP archive by ID or name. * * @example * ```ts - * await client.extensions.delete('id_or_name'); + * const extension = await client.extensions.retrieve( + * 'id_or_name', + * ); + * + * const content = await extension.blob(); + * console.log(content); * ``` */ - delete(idOrName: string, options?: RequestOptions): APIPromise { - return this._client.delete(path`/extensions/${idOrName}`, { + retrieve(idOrName: string, options?: RequestOptions): APIPromise { + return this._client.get(path`/extensions/${idOrName}`, { ...options, - headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), + headers: buildHeaders([{ Accept: 'application/octet-stream' }, options?.headers]), + __binaryResponse: true, }); } /** - * Download the extension as a ZIP archive by ID or name. + * List extensions owned by the caller's organization. * * @example * ```ts - * const response = await client.extensions.download( - * 'id_or_name', - * ); + * const extensions = await client.extensions.list(); + * ``` + */ + list(options?: RequestOptions): APIPromise { + return this._client.get('/extensions', options); + } + + /** + * Delete an extension by its ID or by its name. * - * const content = await response.blob(); - * console.log(content); + * @example + * ```ts + * await client.extensions.delete('id_or_name'); * ``` */ - download(idOrName: string, options?: RequestOptions): APIPromise { - return this._client.get(path`/extensions/${idOrName}`, { + delete(idOrName: string, options?: RequestOptions): APIPromise { + return this._client.delete(path`/extensions/${idOrName}`, { ...options, - headers: buildHeaders([{ Accept: 'application/octet-stream' }, options?.headers]), - __binaryResponse: true, + headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), }); } @@ -83,21 +98,37 @@ export class Extensions extends APIResource { __binaryResponse: true, }); } +} +/** + * A browser extension uploaded to Kernel. + */ +export interface ExtensionCreateResponse { /** - * Upload a zip file containing an unpacked browser extension. Optionally provide a - * unique name for later reference. - * - * @example - * ```ts - * const response = await client.extensions.upload({ - * file: fs.createReadStream('path/to/file'), - * }); - * ``` + * Unique identifier for the extension */ - upload(body: ExtensionUploadParams, options?: RequestOptions): APIPromise { - return this._client.post('/extensions', multipartFormRequestOptions({ body, ...options }, this._client)); - } + id: string; + + /** + * Timestamp when the extension was created + */ + created_at: string; + + /** + * Size of the extension archive in bytes + */ + size_bytes: number; + + /** + * Timestamp when the extension was last used + */ + last_used_at?: string | null; + + /** + * Optional, easier-to-reference name for the extension. Must be unique within the + * organization. + */ + name?: string | null; } export type ExtensionListResponse = Array; @@ -135,35 +166,16 @@ export namespace ExtensionListResponse { } } -/** - * A browser extension uploaded to Kernel. - */ -export interface ExtensionUploadResponse { - /** - * Unique identifier for the extension - */ - id: string; - +export interface ExtensionCreateParams { /** - * Timestamp when the extension was created - */ - created_at: string; - - /** - * Size of the extension archive in bytes - */ - size_bytes: number; - - /** - * Timestamp when the extension was last used + * ZIP file containing the browser extension. */ - last_used_at?: string | null; + file: Uploadable; /** - * Optional, easier-to-reference name for the extension. Must be unique within the - * organization. + * Optional unique name within the organization to reference this extension. */ - name?: string | null; + name?: string; } export interface ExtensionDownloadFromChromeStoreParams { @@ -178,23 +190,11 @@ export interface ExtensionDownloadFromChromeStoreParams { os?: 'win' | 'mac' | 'linux'; } -export interface ExtensionUploadParams { - /** - * ZIP file containing the browser extension. - */ - file: Uploadable; - - /** - * Optional unique name within the organization to reference this extension. - */ - name?: string; -} - export declare namespace Extensions { export { + type ExtensionCreateResponse as ExtensionCreateResponse, type ExtensionListResponse as ExtensionListResponse, - type ExtensionUploadResponse as ExtensionUploadResponse, + type ExtensionCreateParams as ExtensionCreateParams, type ExtensionDownloadFromChromeStoreParams as ExtensionDownloadFromChromeStoreParams, - type ExtensionUploadParams as ExtensionUploadParams, }; } diff --git a/src/resources/index.ts b/src/resources/index.ts index 83e43128..62dfb1ae 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -27,10 +27,10 @@ export { } from './deployments'; export { Extensions, + type ExtensionCreateResponse, type ExtensionListResponse, - type ExtensionUploadResponse, + type ExtensionCreateParams, type ExtensionDownloadFromChromeStoreParams, - type ExtensionUploadParams, } from './extensions'; export { Invocations, diff --git a/tests/api-resources/deployments.test.ts b/tests/api-resources/deployments.test.ts index 80f430f2..12d3bb7b 100644 --- a/tests/api-resources/deployments.test.ts +++ b/tests/api-resources/deployments.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Kernel, { toFile } from '@onkernel/sdk'; +import Kernel from '@onkernel/sdk'; const client = new Kernel({ apiKey: 'My API Key', @@ -9,11 +9,8 @@ const client = new Kernel({ describe('resource deployments', () => { // Prism tests are disabled - test.skip('create: only required params', async () => { - const responsePromise = client.deployments.create({ - entrypoint_rel_path: 'src/app.py', - file: await toFile(Buffer.from('# my file contents'), 'README.md'), - }); + test.skip('create', async () => { + const responsePromise = client.deployments.create({}); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -23,18 +20,6 @@ describe('resource deployments', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled - test.skip('create: required and optional params', async () => { - const response = await client.deployments.create({ - entrypoint_rel_path: 'src/app.py', - file: await toFile(Buffer.from('# my file contents'), 'README.md'), - env_vars: { foo: 'string' }, - force: false, - region: 'aws.us-east-1a', - version: '1.0.0', - }); - }); - // Prism tests are disabled test.skip('retrieve', async () => { const responsePromise = client.deployments.retrieve('id'); diff --git a/tests/api-resources/extensions.test.ts b/tests/api-resources/extensions.test.ts index 515415fe..f401acfb 100644 --- a/tests/api-resources/extensions.test.ts +++ b/tests/api-resources/extensions.test.ts @@ -9,8 +9,10 @@ const client = new Kernel({ describe('resource extensions', () => { // Prism tests are disabled - test.skip('list', async () => { - const responsePromise = client.extensions.list(); + test.skip('create: only required params', async () => { + const responsePromise = client.extensions.create({ + file: await toFile(Buffer.from('# my file contents'), 'README.md'), + }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -21,8 +23,16 @@ describe('resource extensions', () => { }); // Prism tests are disabled - test.skip('delete', async () => { - const responsePromise = client.extensions.delete('id_or_name'); + test.skip('create: required and optional params', async () => { + const response = await client.extensions.create({ + file: await toFile(Buffer.from('# my file contents'), 'README.md'), + name: 'name', + }); + }); + + // Prism tests are disabled + test.skip('list', async () => { + const responsePromise = client.extensions.list(); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -32,15 +42,9 @@ describe('resource extensions', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - test('downloadFromChromeStore: required and optional params', async () => { - const response = await client.extensions.downloadFromChromeStore({ url: 'url', os: 'win' }); - }); - // Prism tests are disabled - test.skip('upload: only required params', async () => { - const responsePromise = client.extensions.upload({ - file: await toFile(Buffer.from('# my file contents'), 'README.md'), - }); + test.skip('delete', async () => { + const responsePromise = client.extensions.delete('id_or_name'); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -50,11 +54,7 @@ describe('resource extensions', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled - test.skip('upload: required and optional params', async () => { - const response = await client.extensions.upload({ - file: await toFile(Buffer.from('# my file contents'), 'README.md'), - name: 'name', - }); + test('downloadFromChromeStore: required and optional params', async () => { + const response = await client.extensions.downloadFromChromeStore({ url: 'url', os: 'win' }); }); }); From 657bea9d9c54b111221b340ad07481b7ab05b894 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 17 Oct 2025 18:33:34 +0000 Subject: [PATCH 193/551] feat: click mouse, move mouse, screenshot --- .stats.yml | 8 +- api.md | 18 +- src/client.ts | 8 +- src/resources/browsers/browsers.ts | 24 ++ src/resources/browsers/computer.ts | 328 ++++++++++++++++++ src/resources/browsers/index.ts | 10 + src/resources/extensions.ts | 138 ++++---- src/resources/index.ts | 4 +- tests/api-resources/browsers/computer.test.ts | 155 +++++++++ tests/api-resources/extensions.test.ts | 36 +- 10 files changed, 629 insertions(+), 100 deletions(-) create mode 100644 src/resources/browsers/computer.ts create mode 100644 tests/api-resources/browsers/computer.test.ts diff --git a/.stats.yml b/.stats.yml index 2bd40ccf..b4dc6064 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 57 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-6eaa6f5654abc94549962d7db1e8c7936af1f815bb3abe2f8249959394da1278.yml -openapi_spec_hash: 31ece7cd801e74228b80a8112a762e56 -config_hash: 3fc2057ce765bc5f27785a694ed0f553 +configured_endpoints: 64 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-e21f0324774a1762bc2bba0da3a8a6b0d0e74720d7a1c83dec813f9e027fcf58.yml +openapi_spec_hash: f1b636abfd6cb8e7c2ba7ffb8e53b9ba +config_hash: 09a2df23048cb16689c9a390d9e5bc47 diff --git a/api.md b/api.md index b442f34b..cd455523 100644 --- a/api.md +++ b/api.md @@ -150,6 +150,18 @@ Methods: - client.browsers.logs.stream(id, { ...params }) -> LogEvent +## Computer + +Methods: + +- client.browsers.computer.captureScreenshot(id, { ...params }) -> Response +- client.browsers.computer.clickMouse(id, { ...params }) -> void +- client.browsers.computer.dragMouse(id, { ...params }) -> void +- client.browsers.computer.moveMouse(id, { ...params }) -> void +- client.browsers.computer.pressKey(id, { ...params }) -> void +- client.browsers.computer.scroll(id, { ...params }) -> void +- client.browsers.computer.typeText(id, { ...params }) -> void + # Profiles Types: @@ -183,13 +195,13 @@ Methods: Types: -- ExtensionCreateResponse - ExtensionListResponse +- ExtensionUploadResponse Methods: -- client.extensions.create({ ...params }) -> ExtensionCreateResponse -- client.extensions.retrieve(idOrName) -> Response - client.extensions.list() -> ExtensionListResponse - client.extensions.delete(idOrName) -> void +- client.extensions.download(idOrName) -> Response - client.extensions.downloadFromChromeStore({ ...params }) -> Response +- client.extensions.upload({ ...params }) -> ExtensionUploadResponse diff --git a/src/client.ts b/src/client.ts index 96ad7cae..510d650b 100644 --- a/src/client.ts +++ b/src/client.ts @@ -32,10 +32,10 @@ import { Deployments, } from './resources/deployments'; import { - ExtensionCreateParams, - ExtensionCreateResponse, ExtensionDownloadFromChromeStoreParams, ExtensionListResponse, + ExtensionUploadParams, + ExtensionUploadResponse, Extensions, } from './resources/extensions'; import { @@ -895,10 +895,10 @@ export declare namespace Kernel { export { Extensions as Extensions, - type ExtensionCreateResponse as ExtensionCreateResponse, type ExtensionListResponse as ExtensionListResponse, - type ExtensionCreateParams as ExtensionCreateParams, + type ExtensionUploadResponse as ExtensionUploadResponse, type ExtensionDownloadFromChromeStoreParams as ExtensionDownloadFromChromeStoreParams, + type ExtensionUploadParams as ExtensionUploadParams, }; export type AppAction = API.AppAction; diff --git a/src/resources/browsers/browsers.ts b/src/resources/browsers/browsers.ts index 97d0d77c..df843b1a 100644 --- a/src/resources/browsers/browsers.ts +++ b/src/resources/browsers/browsers.ts @@ -2,6 +2,17 @@ import { APIResource } from '../../core/resource'; import * as BrowsersAPI from './browsers'; +import * as ComputerAPI from './computer'; +import { + Computer, + ComputerCaptureScreenshotParams, + ComputerClickMouseParams, + ComputerDragMouseParams, + ComputerMoveMouseParams, + ComputerPressKeyParams, + ComputerScrollParams, + ComputerTypeTextParams, +} from './computer'; import * as LogsAPI from './logs'; import { LogStreamParams, Logs } from './logs'; import * as ProcessAPI from './process'; @@ -59,6 +70,7 @@ export class Browsers extends APIResource { fs: FsAPI.Fs = new FsAPI.Fs(this._client); process: ProcessAPI.Process = new ProcessAPI.Process(this._client); logs: LogsAPI.Logs = new LogsAPI.Logs(this._client); + computer: ComputerAPI.Computer = new ComputerAPI.Computer(this._client); /** * Create a new browser session from within an action. @@ -682,6 +694,7 @@ Browsers.Replays = Replays; Browsers.Fs = Fs; Browsers.Process = Process; Browsers.Logs = Logs; +Browsers.Computer = Computer; export declare namespace Browsers { export { @@ -739,4 +752,15 @@ export declare namespace Browsers { }; export { Logs as Logs, type LogStreamParams as LogStreamParams }; + + export { + Computer as Computer, + type ComputerCaptureScreenshotParams as ComputerCaptureScreenshotParams, + type ComputerClickMouseParams as ComputerClickMouseParams, + type ComputerDragMouseParams as ComputerDragMouseParams, + type ComputerMoveMouseParams as ComputerMoveMouseParams, + type ComputerPressKeyParams as ComputerPressKeyParams, + type ComputerScrollParams as ComputerScrollParams, + type ComputerTypeTextParams as ComputerTypeTextParams, + }; } diff --git a/src/resources/browsers/computer.ts b/src/resources/browsers/computer.ts new file mode 100644 index 00000000..49c2954a --- /dev/null +++ b/src/resources/browsers/computer.ts @@ -0,0 +1,328 @@ +// 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 Computer extends APIResource { + /** + * Capture a screenshot of the browser instance + * + * @example + * ```ts + * const response = + * await client.browsers.computer.captureScreenshot('id'); + * + * const content = await response.blob(); + * console.log(content); + * ``` + */ + captureScreenshot( + id: string, + body: ComputerCaptureScreenshotParams | null | undefined = {}, + options?: RequestOptions, + ): APIPromise { + return this._client.post(path`/browsers/${id}/computer/screenshot`, { + body, + ...options, + headers: buildHeaders([{ Accept: 'image/png' }, options?.headers]), + __binaryResponse: true, + }); + } + + /** + * Simulate a mouse click action on the browser instance + * + * @example + * ```ts + * await client.browsers.computer.clickMouse('id', { + * x: 0, + * y: 0, + * }); + * ``` + */ + clickMouse(id: string, body: ComputerClickMouseParams, options?: RequestOptions): APIPromise { + return this._client.post(path`/browsers/${id}/computer/click_mouse`, { + body, + ...options, + headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), + }); + } + + /** + * Drag the mouse along a path + * + * @example + * ```ts + * await client.browsers.computer.dragMouse('id', { + * path: [ + * [0, 0], + * [0, 0], + * ], + * }); + * ``` + */ + dragMouse(id: string, body: ComputerDragMouseParams, options?: RequestOptions): APIPromise { + return this._client.post(path`/browsers/${id}/computer/drag_mouse`, { + body, + ...options, + headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), + }); + } + + /** + * Move the mouse cursor to the specified coordinates on the browser instance + * + * @example + * ```ts + * await client.browsers.computer.moveMouse('id', { + * x: 0, + * y: 0, + * }); + * ``` + */ + moveMouse(id: string, body: ComputerMoveMouseParams, options?: RequestOptions): APIPromise { + return this._client.post(path`/browsers/${id}/computer/move_mouse`, { + body, + ...options, + headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), + }); + } + + /** + * Press one or more keys on the host computer + * + * @example + * ```ts + * await client.browsers.computer.pressKey('id', { + * keys: ['string'], + * }); + * ``` + */ + pressKey(id: string, body: ComputerPressKeyParams, options?: RequestOptions): APIPromise { + return this._client.post(path`/browsers/${id}/computer/press_key`, { + body, + ...options, + headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), + }); + } + + /** + * Scroll the mouse wheel at a position on the host computer + * + * @example + * ```ts + * await client.browsers.computer.scroll('id', { x: 0, y: 0 }); + * ``` + */ + scroll(id: string, body: ComputerScrollParams, options?: RequestOptions): APIPromise { + return this._client.post(path`/browsers/${id}/computer/scroll`, { + body, + ...options, + headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), + }); + } + + /** + * Type text on the browser instance + * + * @example + * ```ts + * await client.browsers.computer.typeText('id', { + * text: 'text', + * }); + * ``` + */ + typeText(id: string, body: ComputerTypeTextParams, options?: RequestOptions): APIPromise { + return this._client.post(path`/browsers/${id}/computer/type`, { + body, + ...options, + headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), + }); + } +} + +export interface ComputerCaptureScreenshotParams { + region?: ComputerCaptureScreenshotParams.Region; +} + +export namespace ComputerCaptureScreenshotParams { + export interface Region { + /** + * Height of the region in pixels + */ + height: number; + + /** + * Width of the region in pixels + */ + width: number; + + /** + * X coordinate of the region's top-left corner + */ + x: number; + + /** + * Y coordinate of the region's top-left corner + */ + y: number; + } +} + +export interface ComputerClickMouseParams { + /** + * X coordinate of the click position + */ + x: number; + + /** + * Y coordinate of the click position + */ + y: number; + + /** + * Mouse button to interact with + */ + button?: 'left' | 'right' | 'middle' | 'back' | 'forward'; + + /** + * Type of click action + */ + click_type?: 'down' | 'up' | 'click'; + + /** + * Modifier keys to hold during the click + */ + hold_keys?: Array; + + /** + * Number of times to repeat the click + */ + num_clicks?: number; +} + +export interface ComputerDragMouseParams { + /** + * Ordered list of [x, y] coordinate pairs to move through while dragging. Must + * contain at least 2 points. + */ + path: Array>; + + /** + * Mouse button to drag with + */ + button?: 'left' | 'middle' | 'right'; + + /** + * Delay in milliseconds between button down and starting to move along the path. + */ + delay?: number; + + /** + * Modifier keys to hold during the drag + */ + hold_keys?: Array; + + /** + * Delay in milliseconds between relative steps while dragging (not the initial + * delay). + */ + step_delay_ms?: number; + + /** + * Number of relative move steps per segment in the path. Minimum 1. + */ + steps_per_segment?: number; +} + +export interface ComputerMoveMouseParams { + /** + * X coordinate to move the cursor to + */ + x: number; + + /** + * Y coordinate to move the cursor to + */ + y: number; + + /** + * Modifier keys to hold during the move + */ + hold_keys?: Array; +} + +export interface ComputerPressKeyParams { + /** + * List of key symbols to press. Each item should be a key symbol supported by + * xdotool (see X11 keysym definitions). Examples include "Return", "Shift", + * "Ctrl", "Alt", "F5". Items in this list could also be combinations, e.g. + * "Ctrl+t" or "Ctrl+Shift+Tab". + */ + keys: Array; + + /** + * Duration to hold the keys down in milliseconds. If omitted or 0, keys are + * tapped. + */ + duration?: number; + + /** + * Optional modifier keys to hold during the key press sequence. + */ + hold_keys?: Array; +} + +export interface ComputerScrollParams { + /** + * X coordinate at which to perform the scroll + */ + x: number; + + /** + * Y coordinate at which to perform the scroll + */ + y: number; + + /** + * Horizontal scroll amount. Positive scrolls right, negative scrolls left. + */ + delta_x?: number; + + /** + * Vertical scroll amount. Positive scrolls down, negative scrolls up. + */ + delta_y?: number; + + /** + * Modifier keys to hold during the scroll + */ + hold_keys?: Array; +} + +export interface ComputerTypeTextParams { + /** + * Text to type on the browser instance + */ + text: string; + + /** + * Delay in milliseconds between keystrokes + */ + delay?: number; +} + +export declare namespace Computer { + export { + type ComputerCaptureScreenshotParams as ComputerCaptureScreenshotParams, + type ComputerClickMouseParams as ComputerClickMouseParams, + type ComputerDragMouseParams as ComputerDragMouseParams, + type ComputerMoveMouseParams as ComputerMoveMouseParams, + type ComputerPressKeyParams as ComputerPressKeyParams, + type ComputerScrollParams as ComputerScrollParams, + type ComputerTypeTextParams as ComputerTypeTextParams, + }; +} diff --git a/src/resources/browsers/index.ts b/src/resources/browsers/index.ts index 53bb8a9f..243f4853 100644 --- a/src/resources/browsers/index.ts +++ b/src/resources/browsers/index.ts @@ -11,6 +11,16 @@ export { type BrowserDeleteParams, type BrowserLoadExtensionsParams, } from './browsers'; +export { + Computer, + type ComputerCaptureScreenshotParams, + type ComputerClickMouseParams, + type ComputerDragMouseParams, + type ComputerMoveMouseParams, + type ComputerPressKeyParams, + type ComputerScrollParams, + type ComputerTypeTextParams, +} from './computer'; export { Fs, type FFileInfoResponse, diff --git a/src/resources/extensions.ts b/src/resources/extensions.ts index 82f29ba1..5697a075 100644 --- a/src/resources/extensions.ts +++ b/src/resources/extensions.ts @@ -10,65 +10,50 @@ import { path } from '../internal/utils/path'; export class Extensions extends APIResource { /** - * Upload a zip file containing an unpacked browser extension. Optionally provide a - * unique name for later reference. + * List extensions owned by the caller's organization. * * @example * ```ts - * const extension = await client.extensions.create({ - * file: fs.createReadStream('path/to/file'), - * }); + * const extensions = await client.extensions.list(); * ``` */ - create(body: ExtensionCreateParams, options?: RequestOptions): APIPromise { - return this._client.post('/extensions', multipartFormRequestOptions({ body, ...options }, this._client)); + list(options?: RequestOptions): APIPromise { + return this._client.get('/extensions', options); } /** - * Download the extension as a ZIP archive by ID or name. + * Delete an extension by its ID or by its name. * * @example * ```ts - * const extension = await client.extensions.retrieve( - * 'id_or_name', - * ); - * - * const content = await extension.blob(); - * console.log(content); + * await client.extensions.delete('id_or_name'); * ``` */ - retrieve(idOrName: string, options?: RequestOptions): APIPromise { - return this._client.get(path`/extensions/${idOrName}`, { + delete(idOrName: string, options?: RequestOptions): APIPromise { + return this._client.delete(path`/extensions/${idOrName}`, { ...options, - headers: buildHeaders([{ Accept: 'application/octet-stream' }, options?.headers]), - __binaryResponse: true, + headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), }); } /** - * List extensions owned by the caller's organization. + * Download the extension as a ZIP archive by ID or name. * * @example * ```ts - * const extensions = await client.extensions.list(); - * ``` - */ - list(options?: RequestOptions): APIPromise { - return this._client.get('/extensions', options); - } - - /** - * Delete an extension by its ID or by its name. + * const response = await client.extensions.download( + * 'id_or_name', + * ); * - * @example - * ```ts - * await client.extensions.delete('id_or_name'); + * const content = await response.blob(); + * console.log(content); * ``` */ - delete(idOrName: string, options?: RequestOptions): APIPromise { - return this._client.delete(path`/extensions/${idOrName}`, { + download(idOrName: string, options?: RequestOptions): APIPromise { + return this._client.get(path`/extensions/${idOrName}`, { ...options, - headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), + headers: buildHeaders([{ Accept: 'application/octet-stream' }, options?.headers]), + __binaryResponse: true, }); } @@ -98,37 +83,21 @@ export class Extensions extends APIResource { __binaryResponse: true, }); } -} -/** - * A browser extension uploaded to Kernel. - */ -export interface ExtensionCreateResponse { /** - * Unique identifier for the extension - */ - id: string; - - /** - * Timestamp when the extension was created - */ - created_at: string; - - /** - * Size of the extension archive in bytes - */ - size_bytes: number; - - /** - * Timestamp when the extension was last used - */ - last_used_at?: string | null; - - /** - * Optional, easier-to-reference name for the extension. Must be unique within the - * organization. + * Upload a zip file containing an unpacked browser extension. Optionally provide a + * unique name for later reference. + * + * @example + * ```ts + * const response = await client.extensions.upload({ + * file: fs.createReadStream('path/to/file'), + * }); + * ``` */ - name?: string | null; + upload(body: ExtensionUploadParams, options?: RequestOptions): APIPromise { + return this._client.post('/extensions', multipartFormRequestOptions({ body, ...options }, this._client)); + } } export type ExtensionListResponse = Array; @@ -166,16 +135,35 @@ export namespace ExtensionListResponse { } } -export interface ExtensionCreateParams { +/** + * A browser extension uploaded to Kernel. + */ +export interface ExtensionUploadResponse { /** - * ZIP file containing the browser extension. + * Unique identifier for the extension */ - file: Uploadable; + id: string; /** - * Optional unique name within the organization to reference this extension. + * Timestamp when the extension was created */ - name?: string; + created_at: string; + + /** + * Size of the extension archive in bytes + */ + size_bytes: number; + + /** + * Timestamp when the extension was last used + */ + last_used_at?: string | null; + + /** + * Optional, easier-to-reference name for the extension. Must be unique within the + * organization. + */ + name?: string | null; } export interface ExtensionDownloadFromChromeStoreParams { @@ -190,11 +178,23 @@ export interface ExtensionDownloadFromChromeStoreParams { os?: 'win' | 'mac' | 'linux'; } +export interface ExtensionUploadParams { + /** + * ZIP file containing the browser extension. + */ + file: Uploadable; + + /** + * Optional unique name within the organization to reference this extension. + */ + name?: string; +} + export declare namespace Extensions { export { - type ExtensionCreateResponse as ExtensionCreateResponse, type ExtensionListResponse as ExtensionListResponse, - type ExtensionCreateParams as ExtensionCreateParams, + type ExtensionUploadResponse as ExtensionUploadResponse, type ExtensionDownloadFromChromeStoreParams as ExtensionDownloadFromChromeStoreParams, + type ExtensionUploadParams as ExtensionUploadParams, }; } diff --git a/src/resources/index.ts b/src/resources/index.ts index 62dfb1ae..83e43128 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -27,10 +27,10 @@ export { } from './deployments'; export { Extensions, - type ExtensionCreateResponse, type ExtensionListResponse, - type ExtensionCreateParams, + type ExtensionUploadResponse, type ExtensionDownloadFromChromeStoreParams, + type ExtensionUploadParams, } from './extensions'; export { Invocations, diff --git a/tests/api-resources/browsers/computer.test.ts b/tests/api-resources/browsers/computer.test.ts new file mode 100644 index 00000000..2c2d7def --- /dev/null +++ b/tests/api-resources/browsers/computer.test.ts @@ -0,0 +1,155 @@ +// 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 computer', () => { + test('captureScreenshot: 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.computer.captureScreenshot( + 'id', + { region: { height: 0, width: 0, x: 0, y: 0 } }, + { path: '/_stainless_unknown_path' }, + ), + ).rejects.toThrow(Kernel.NotFoundError); + }); + + // Prism tests are disabled + test.skip('clickMouse: only required params', async () => { + const responsePromise = client.browsers.computer.clickMouse('id', { x: 0, y: 0 }); + 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); + }); + + // Prism tests are disabled + test.skip('clickMouse: required and optional params', async () => { + const response = await client.browsers.computer.clickMouse('id', { + x: 0, + y: 0, + button: 'left', + click_type: 'down', + hold_keys: ['string'], + num_clicks: 0, + }); + }); + + // Prism tests are disabled + test.skip('dragMouse: only required params', async () => { + const responsePromise = client.browsers.computer.dragMouse('id', { + path: [ + [0, 0], + [0, 0], + ], + }); + 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); + }); + + // Prism tests are disabled + test.skip('dragMouse: required and optional params', async () => { + const response = await client.browsers.computer.dragMouse('id', { + path: [ + [0, 0], + [0, 0], + ], + button: 'left', + delay: 0, + hold_keys: ['string'], + step_delay_ms: 0, + steps_per_segment: 1, + }); + }); + + // Prism tests are disabled + test.skip('moveMouse: only required params', async () => { + const responsePromise = client.browsers.computer.moveMouse('id', { x: 0, y: 0 }); + 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); + }); + + // Prism tests are disabled + test.skip('moveMouse: required and optional params', async () => { + const response = await client.browsers.computer.moveMouse('id', { x: 0, y: 0, hold_keys: ['string'] }); + }); + + // Prism tests are disabled + test.skip('pressKey: only required params', async () => { + const responsePromise = client.browsers.computer.pressKey('id', { keys: ['string'] }); + 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); + }); + + // Prism tests are disabled + test.skip('pressKey: required and optional params', async () => { + const response = await client.browsers.computer.pressKey('id', { + keys: ['string'], + duration: 0, + hold_keys: ['string'], + }); + }); + + // Prism tests are disabled + test.skip('scroll: only required params', async () => { + const responsePromise = client.browsers.computer.scroll('id', { x: 0, y: 0 }); + 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); + }); + + // Prism tests are disabled + test.skip('scroll: required and optional params', async () => { + const response = await client.browsers.computer.scroll('id', { + x: 0, + y: 0, + delta_x: 0, + delta_y: 0, + hold_keys: ['string'], + }); + }); + + // Prism tests are disabled + test.skip('typeText: only required params', async () => { + const responsePromise = client.browsers.computer.typeText('id', { text: 'text' }); + 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); + }); + + // Prism tests are disabled + test.skip('typeText: required and optional params', async () => { + const response = await client.browsers.computer.typeText('id', { text: 'text', delay: 0 }); + }); +}); diff --git a/tests/api-resources/extensions.test.ts b/tests/api-resources/extensions.test.ts index f401acfb..515415fe 100644 --- a/tests/api-resources/extensions.test.ts +++ b/tests/api-resources/extensions.test.ts @@ -9,10 +9,8 @@ const client = new Kernel({ describe('resource extensions', () => { // Prism tests are disabled - test.skip('create: only required params', async () => { - const responsePromise = client.extensions.create({ - file: await toFile(Buffer.from('# my file contents'), 'README.md'), - }); + test.skip('list', async () => { + const responsePromise = client.extensions.list(); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -23,16 +21,8 @@ describe('resource extensions', () => { }); // Prism tests are disabled - test.skip('create: required and optional params', async () => { - const response = await client.extensions.create({ - file: await toFile(Buffer.from('# my file contents'), 'README.md'), - name: 'name', - }); - }); - - // Prism tests are disabled - test.skip('list', async () => { - const responsePromise = client.extensions.list(); + test.skip('delete', async () => { + const responsePromise = client.extensions.delete('id_or_name'); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -42,9 +32,15 @@ describe('resource extensions', () => { expect(dataAndResponse.response).toBe(rawResponse); }); + test('downloadFromChromeStore: required and optional params', async () => { + const response = await client.extensions.downloadFromChromeStore({ url: 'url', os: 'win' }); + }); + // Prism tests are disabled - test.skip('delete', async () => { - const responsePromise = client.extensions.delete('id_or_name'); + test.skip('upload: only required params', async () => { + const responsePromise = client.extensions.upload({ + file: await toFile(Buffer.from('# my file contents'), 'README.md'), + }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -54,7 +50,11 @@ describe('resource extensions', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - test('downloadFromChromeStore: required and optional params', async () => { - const response = await client.extensions.downloadFromChromeStore({ url: 'url', os: 'win' }); + // Prism tests are disabled + test.skip('upload: required and optional params', async () => { + const response = await client.extensions.upload({ + file: await toFile(Buffer.from('# my file contents'), 'README.md'), + name: 'name', + }); }); }); From b45eb9cafa0f7689159c235bbcb16f4b8af31269 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 17 Oct 2025 18:50:55 +0000 Subject: [PATCH 194/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index b19a3f40..f87262aa 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.14.2" + ".": "0.15.0" } diff --git a/package.json b/package.json index 2d371a8c..dfa3c73a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.14.2", + "version": "0.15.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 0af0c850..b67001ee 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.14.2'; // x-release-please-version +export const VERSION = '0.15.0'; // x-release-please-version From 1f92ca521ac4fc779abb6c2597bd6c5d0158d3f7 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 21 Oct 2025 02:19:15 +0000 Subject: [PATCH 195/551] fix(client): incorrect offset pagination check --- src/core/pagination.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/core/pagination.ts b/src/core/pagination.ts index c3266cdc..9a507f0e 100644 --- a/src/core/pagination.ts +++ b/src/core/pagination.ts @@ -148,11 +148,7 @@ export class OffsetPagination extends AbstractPage { } nextPageRequestOptions(): PageRequestOptions | null { - const offset = this.next_offset; - if (!offset) { - return null; - } - + const offset = this.next_offset ?? 0; const length = this.getPaginatedItems().length; const currentCount = offset + length; From bbb9d230340dd37ed955b4d60939551c6a59f356 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 27 Oct 2025 18:39:38 +0000 Subject: [PATCH 196/551] feat: ad hoc playwright code exec AP| --- .stats.yml | 8 +- api.md | 10 +++ src/resources/browsers/browsers.ts | 10 +++ src/resources/browsers/index.ts | 1 + src/resources/browsers/playwright.ts | 83 +++++++++++++++++++ .../api-resources/browsers/playwright.test.ts | 27 ++++++ 6 files changed, 135 insertions(+), 4 deletions(-) create mode 100644 src/resources/browsers/playwright.ts create mode 100644 tests/api-resources/browsers/playwright.test.ts diff --git a/.stats.yml b/.stats.yml index b4dc6064..8cd6a7c5 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 64 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-e21f0324774a1762bc2bba0da3a8a6b0d0e74720d7a1c83dec813f9e027fcf58.yml -openapi_spec_hash: f1b636abfd6cb8e7c2ba7ffb8e53b9ba -config_hash: 09a2df23048cb16689c9a390d9e5bc47 +configured_endpoints: 65 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-ecf484375ede1edd7754779ad8beeebd4ba9118152fe6cd65772dc7245a19dee.yml +openapi_spec_hash: b1f3f05005f75cbf5b82299459e2aa9b +config_hash: 3ded7a0ed77b1bfd68eabc6763521fe8 diff --git a/api.md b/api.md index cd455523..3899a03a 100644 --- a/api.md +++ b/api.md @@ -162,6 +162,16 @@ Methods: - client.browsers.computer.scroll(id, { ...params }) -> void - client.browsers.computer.typeText(id, { ...params }) -> void +## Playwright + +Types: + +- PlaywrightExecuteResponse + +Methods: + +- client.browsers.playwright.execute(id, { ...params }) -> PlaywrightExecuteResponse + # Profiles Types: diff --git a/src/resources/browsers/browsers.ts b/src/resources/browsers/browsers.ts index df843b1a..874e73a4 100644 --- a/src/resources/browsers/browsers.ts +++ b/src/resources/browsers/browsers.ts @@ -15,6 +15,8 @@ import { } from './computer'; import * as LogsAPI from './logs'; import { LogStreamParams, Logs } from './logs'; +import * as PlaywrightAPI from './playwright'; +import { Playwright, PlaywrightExecuteParams, PlaywrightExecuteResponse } from './playwright'; import * as ProcessAPI from './process'; import { Process, @@ -71,6 +73,7 @@ export class Browsers extends APIResource { process: ProcessAPI.Process = new ProcessAPI.Process(this._client); logs: LogsAPI.Logs = new LogsAPI.Logs(this._client); computer: ComputerAPI.Computer = new ComputerAPI.Computer(this._client); + playwright: PlaywrightAPI.Playwright = new PlaywrightAPI.Playwright(this._client); /** * Create a new browser session from within an action. @@ -695,6 +698,7 @@ Browsers.Fs = Fs; Browsers.Process = Process; Browsers.Logs = Logs; Browsers.Computer = Computer; +Browsers.Playwright = Playwright; export declare namespace Browsers { export { @@ -763,4 +767,10 @@ export declare namespace Browsers { type ComputerScrollParams as ComputerScrollParams, type ComputerTypeTextParams as ComputerTypeTextParams, }; + + export { + Playwright as Playwright, + type PlaywrightExecuteResponse as PlaywrightExecuteResponse, + type PlaywrightExecuteParams as PlaywrightExecuteParams, + }; } diff --git a/src/resources/browsers/index.ts b/src/resources/browsers/index.ts index 243f4853..4bba3981 100644 --- a/src/resources/browsers/index.ts +++ b/src/resources/browsers/index.ts @@ -39,6 +39,7 @@ export { type FWriteFileParams, } from './fs/index'; export { Logs, type LogStreamParams } from './logs'; +export { Playwright, type PlaywrightExecuteResponse, type PlaywrightExecuteParams } from './playwright'; export { Process, type ProcessExecResponse, diff --git a/src/resources/browsers/playwright.ts b/src/resources/browsers/playwright.ts new file mode 100644 index 00000000..bd99c520 --- /dev/null +++ b/src/resources/browsers/playwright.ts @@ -0,0 +1,83 @@ +// 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 { RequestOptions } from '../../internal/request-options'; +import { path } from '../../internal/utils/path'; + +export class Playwright extends APIResource { + /** + * Execute arbitrary Playwright code in a fresh execution context against the + * browser. The code runs in the same VM as the browser, minimizing latency and + * maximizing throughput. It has access to 'page', 'context', and 'browser' + * variables. It can `return` a value, and this value is returned in the response. + * + * @example + * ```ts + * const response = await client.browsers.playwright.execute( + * 'id', + * { code: 'code' }, + * ); + * ``` + */ + execute( + id: string, + body: PlaywrightExecuteParams, + options?: RequestOptions, + ): APIPromise { + return this._client.post(path`/browsers/${id}/playwright/execute`, { body, ...options }); + } +} + +/** + * Result of Playwright code execution + */ +export interface PlaywrightExecuteResponse { + /** + * Whether the code executed successfully + */ + success: boolean; + + /** + * Error message if execution failed + */ + error?: string; + + /** + * The value returned by the code (if any) + */ + result?: unknown; + + /** + * Standard error from the execution + */ + stderr?: string; + + /** + * Standard output from the execution + */ + stdout?: string; +} + +export interface PlaywrightExecuteParams { + /** + * TypeScript/JavaScript code to execute. The code has access to 'page', 'context', + * and 'browser' variables. It runs within a function, so you can use a return + * statement at the end to return a value. This value is returned as the `result` + * property in the response. Example: "await page.goto('https://example.com'); + * return await page.title();" + */ + code: string; + + /** + * Maximum execution time in seconds. Default is 60. + */ + timeout_sec?: number; +} + +export declare namespace Playwright { + export { + type PlaywrightExecuteResponse as PlaywrightExecuteResponse, + type PlaywrightExecuteParams as PlaywrightExecuteParams, + }; +} diff --git a/tests/api-resources/browsers/playwright.test.ts b/tests/api-resources/browsers/playwright.test.ts new file mode 100644 index 00000000..5c45947d --- /dev/null +++ b/tests/api-resources/browsers/playwright.test.ts @@ -0,0 +1,27 @@ +// 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 playwright', () => { + // Prism tests are disabled + test.skip('execute: only required params', async () => { + const responsePromise = client.browsers.playwright.execute('id', { code: 'code' }); + 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); + }); + + // Prism tests are disabled + test.skip('execute: required and optional params', async () => { + const response = await client.browsers.playwright.execute('id', { code: 'code', timeout_sec: 1 }); + }); +}); From 44f1f76a6a7fed4a6f45a40a62dd250f245dbb31 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 27 Oct 2025 18:41:33 +0000 Subject: [PATCH 197/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index f87262aa..bc7e4aae 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.15.0" + ".": "0.16.0" } diff --git a/package.json b/package.json index dfa3c73a..386fb018 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.15.0", + "version": "0.16.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index b67001ee..be03af20 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.15.0'; // x-release-please-version +export const VERSION = '0.16.0'; // x-release-please-version From 1a36725873c6c6941f377b6f1dbbbc6034f16a1f Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 27 Oct 2025 19:40:50 +0000 Subject: [PATCH 198/551] feat: Use ping instead of bright data for ISP proxy --- .stats.yml | 4 ++-- src/resources/proxies.ts | 32 ++++++++++++++++---------------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/.stats.yml b/.stats.yml index 8cd6a7c5..8cf9ee75 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 65 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-ecf484375ede1edd7754779ad8beeebd4ba9118152fe6cd65772dc7245a19dee.yml -openapi_spec_hash: b1f3f05005f75cbf5b82299459e2aa9b +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-e914e2d08b888c77051acb09176d5e88052f130e0d22e85d946a675d2c3d39ab.yml +openapi_spec_hash: 611d0ed1b4519331470b5d14e5f6784a config_hash: 3ded7a0ed77b1bfd68eabc6763521fe8 diff --git a/src/resources/proxies.ts b/src/resources/proxies.ts index e6841d70..7c409f5e 100644 --- a/src/resources/proxies.ts +++ b/src/resources/proxies.ts @@ -88,9 +88,9 @@ export namespace ProxyCreateResponse { */ export interface DatacenterProxyConfig { /** - * ISO 3166 country code. + * ISO 3166 country code. Defaults to US if not provided. */ - country: string; + country?: string; } /** @@ -98,9 +98,9 @@ export namespace ProxyCreateResponse { */ export interface IspProxyConfig { /** - * ISO 3166 country code. + * ISO 3166 country code. Defaults to US if not provided. */ - country: string; + country?: string; } /** @@ -308,9 +308,9 @@ export namespace ProxyRetrieveResponse { */ export interface DatacenterProxyConfig { /** - * ISO 3166 country code. + * ISO 3166 country code. Defaults to US if not provided. */ - country: string; + country?: string; } /** @@ -318,9 +318,9 @@ export namespace ProxyRetrieveResponse { */ export interface IspProxyConfig { /** - * ISO 3166 country code. + * ISO 3166 country code. Defaults to US if not provided. */ - country: string; + country?: string; } /** @@ -531,9 +531,9 @@ export namespace ProxyListResponse { */ export interface DatacenterProxyConfig { /** - * ISO 3166 country code. + * ISO 3166 country code. Defaults to US if not provided. */ - country: string; + country?: string; } /** @@ -541,9 +541,9 @@ export namespace ProxyListResponse { */ export interface IspProxyConfig { /** - * ISO 3166 country code. + * ISO 3166 country code. Defaults to US if not provided. */ - country: string; + country?: string; } /** @@ -737,9 +737,9 @@ export namespace ProxyCreateParams { */ export interface DatacenterProxyConfig { /** - * ISO 3166 country code. + * ISO 3166 country code. Defaults to US if not provided. */ - country: string; + country?: string; } /** @@ -747,9 +747,9 @@ export namespace ProxyCreateParams { */ export interface IspProxyConfig { /** - * ISO 3166 country code. + * ISO 3166 country code. Defaults to US if not provided. */ - country: string; + country?: string; } /** From 47321def7d8c6bb5c4c8dc30bf3624e45dba83c1 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 27 Oct 2025 19:47:34 +0000 Subject: [PATCH 199/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index bc7e4aae..7b51ca08 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.16.0" + ".": "0.17.0" } diff --git a/package.json b/package.json index 386fb018..e8752f36 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.16.0", + "version": "0.17.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index be03af20..0251da7d 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.16.0'; // x-release-please-version +export const VERSION = '0.17.0'; // x-release-please-version From a7203fbc32d77b87827a5828690ee96fb7e5bd09 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 30 Oct 2025 21:01:42 +0000 Subject: [PATCH 200/551] feat: apps: add offset pagination + headers --- .stats.yml | 6 +-- api.md | 2 +- src/client.ts | 9 +++- src/resources/apps.ts | 81 +++++++++++++++++--------------- src/resources/index.ts | 7 ++- tests/api-resources/apps.test.ts | 5 +- 6 files changed, 64 insertions(+), 46 deletions(-) diff --git a/.stats.yml b/.stats.yml index 8cf9ee75..9e4dbe62 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 65 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-e914e2d08b888c77051acb09176d5e88052f130e0d22e85d946a675d2c3d39ab.yml -openapi_spec_hash: 611d0ed1b4519331470b5d14e5f6784a -config_hash: 3ded7a0ed77b1bfd68eabc6763521fe8 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-015c11efc34c81d4d82a937c017f5eb789ea3ca21a05b70e2ed31c069b839293.yml +openapi_spec_hash: 3dcab2044da305f376cecf4eca38caee +config_hash: 0fbdda3a736cc2748ca33371871e61b3 diff --git a/api.md b/api.md index 3899a03a..15db545c 100644 --- a/api.md +++ b/api.md @@ -34,7 +34,7 @@ Types: Methods: -- client.apps.list({ ...params }) -> AppListResponse +- client.apps.list({ ...params }) -> AppListResponsesOffsetPagination # Invocations diff --git a/src/client.ts b/src/client.ts index 510d650b..eaef9225 100644 --- a/src/client.ts +++ b/src/client.ts @@ -18,7 +18,7 @@ import { AbstractPage, type OffsetPaginationParams, OffsetPaginationResponse } f import * as Uploads from './core/uploads'; import * as API from './resources/index'; import { APIPromise } from './core/api-promise'; -import { AppListParams, AppListResponse, Apps } from './resources/apps'; +import { AppListParams, AppListResponse, AppListResponsesOffsetPagination, Apps } from './resources/apps'; import { DeploymentCreateParams, DeploymentCreateResponse, @@ -850,7 +850,12 @@ export declare namespace Kernel { type DeploymentFollowParams as DeploymentFollowParams, }; - export { Apps as Apps, type AppListResponse as AppListResponse, type AppListParams as AppListParams }; + export { + Apps as Apps, + type AppListResponse as AppListResponse, + type AppListResponsesOffsetPagination as AppListResponsesOffsetPagination, + type AppListParams as AppListParams, + }; export { Invocations as Invocations, diff --git a/src/resources/apps.ts b/src/resources/apps.ts index b1b71452..c523e2b6 100644 --- a/src/resources/apps.ts +++ b/src/resources/apps.ts @@ -2,63 +2,64 @@ import { APIResource } from '../core/resource'; import * as Shared from './shared'; -import { APIPromise } from '../core/api-promise'; +import { OffsetPagination, type OffsetPaginationParams, PagePromise } from '../core/pagination'; import { RequestOptions } from '../internal/request-options'; export class Apps extends APIResource { /** * List applications. Optionally filter by app name and/or version label. */ - list(query: AppListParams | null | undefined = {}, options?: RequestOptions): APIPromise { - return this._client.get('/apps', { query, ...options }); + list( + query: AppListParams | null | undefined = {}, + options?: RequestOptions, + ): PagePromise { + return this._client.getAPIList('/apps', OffsetPagination, { query, ...options }); } } -export type AppListResponse = Array; +export type AppListResponsesOffsetPagination = OffsetPagination; -export namespace AppListResponse { +/** + * Summary of an application version. + */ +export interface AppListResponse { /** - * Summary of an application version. + * Unique identifier for the app version */ - export interface AppListResponseItem { - /** - * Unique identifier for the app version - */ - id: string; + id: string; - /** - * List of actions available on the app - */ - actions: Array; + /** + * List of actions available on the app + */ + actions: Array; - /** - * Name of the application - */ - app_name: string; + /** + * Name of the application + */ + app_name: string; - /** - * Deployment ID - */ - deployment: string; + /** + * Deployment ID + */ + deployment: string; - /** - * Environment variables configured for this app version - */ - env_vars: { [key: string]: string }; + /** + * Environment variables configured for this app version + */ + env_vars: { [key: string]: string }; - /** - * Deployment region code - */ - region: 'aws.us-east-1a'; + /** + * Deployment region code + */ + region: 'aws.us-east-1a'; - /** - * Version label for the application - */ - version: string; - } + /** + * Version label for the application + */ + version: string; } -export interface AppListParams { +export interface AppListParams extends OffsetPaginationParams { /** * Filter results by application name. */ @@ -71,5 +72,9 @@ export interface AppListParams { } export declare namespace Apps { - export { type AppListResponse as AppListResponse, type AppListParams as AppListParams }; + export { + type AppListResponse as AppListResponse, + type AppListResponsesOffsetPagination as AppListResponsesOffsetPagination, + type AppListParams as AppListParams, + }; } diff --git a/src/resources/index.ts b/src/resources/index.ts index 83e43128..d7e326c3 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -1,7 +1,12 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. export * from './shared'; -export { Apps, type AppListResponse, type AppListParams } from './apps'; +export { + Apps, + type AppListResponse, + type AppListParams, + type AppListResponsesOffsetPagination, +} from './apps'; export { Browsers, type BrowserPersistence, diff --git a/tests/api-resources/apps.test.ts b/tests/api-resources/apps.test.ts index 36a0654b..85debc71 100644 --- a/tests/api-resources/apps.test.ts +++ b/tests/api-resources/apps.test.ts @@ -24,7 +24,10 @@ describe('resource apps', () => { test.skip('list: 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.apps.list({ app_name: 'app_name', version: 'version' }, { path: '/_stainless_unknown_path' }), + client.apps.list( + { app_name: 'app_name', limit: 1, offset: 0, version: 'version' }, + { path: '/_stainless_unknown_path' }, + ), ).rejects.toThrow(Kernel.NotFoundError); }); }); From abba5dfb00ef9b5d9a7ad813cbe6d717cc0234b6 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 30 Oct 2025 21:18:12 +0000 Subject: [PATCH 201/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 7b51ca08..5e39b941 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.17.0" + ".": "0.18.0" } diff --git a/package.json b/package.json index e8752f36..af60924a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.17.0", + "version": "0.18.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 0251da7d..74131f9d 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.17.0'; // x-release-please-version +export const VERSION = '0.18.0'; // x-release-please-version From 94d880636af68d67a4c75b880568719088d52eca Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 7 Nov 2025 21:17:55 +0000 Subject: [PATCH 202/551] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 9e4dbe62..0080fd62 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 65 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-015c11efc34c81d4d82a937c017f5eb789ea3ca21a05b70e2ed31c069b839293.yml -openapi_spec_hash: 3dcab2044da305f376cecf4eca38caee +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-8c7e0b9069a18bc9437269618cde251ba15568771f2b4811d57f0d5f0fd5692d.yml +openapi_spec_hash: aa2544d0bf0e7e875939aaa8e2e114d3 config_hash: 0fbdda3a736cc2748ca33371871e61b3 From e2748c855cb5c84905f9b7c54e1165db9c02a3ea Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 12 Nov 2025 16:43:27 +0000 Subject: [PATCH 203/551] feat: feat hide cursor v2 --- .stats.yml | 8 ++-- api.md | 5 +++ src/resources/browsers/browsers.ts | 4 ++ src/resources/browsers/computer.ts | 38 +++++++++++++++++++ src/resources/browsers/index.ts | 2 + tests/api-resources/browsers/computer.test.ts | 17 +++++++++ 6 files changed, 70 insertions(+), 4 deletions(-) diff --git a/.stats.yml b/.stats.yml index 0080fd62..125a84b7 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 65 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-8c7e0b9069a18bc9437269618cde251ba15568771f2b4811d57f0d5f0fd5692d.yml -openapi_spec_hash: aa2544d0bf0e7e875939aaa8e2e114d3 -config_hash: 0fbdda3a736cc2748ca33371871e61b3 +configured_endpoints: 66 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-86854c41729a6b26f71e26c906f665f69939f23e2d7adcc43380aee64cf6d056.yml +openapi_spec_hash: 270a40c8af29e83cbda77d3700fd456a +config_hash: 9421eb86b7f3f4b274f123279da3858e diff --git a/api.md b/api.md index 15db545c..216b25f9 100644 --- a/api.md +++ b/api.md @@ -152,6 +152,10 @@ Methods: ## Computer +Types: + +- ComputerSetCursorVisibilityResponse + Methods: - client.browsers.computer.captureScreenshot(id, { ...params }) -> Response @@ -160,6 +164,7 @@ Methods: - client.browsers.computer.moveMouse(id, { ...params }) -> void - client.browsers.computer.pressKey(id, { ...params }) -> void - client.browsers.computer.scroll(id, { ...params }) -> void +- client.browsers.computer.setCursorVisibility(id, { ...params }) -> ComputerSetCursorVisibilityResponse - client.browsers.computer.typeText(id, { ...params }) -> void ## Playwright diff --git a/src/resources/browsers/browsers.ts b/src/resources/browsers/browsers.ts index 874e73a4..e05d2195 100644 --- a/src/resources/browsers/browsers.ts +++ b/src/resources/browsers/browsers.ts @@ -11,6 +11,8 @@ import { ComputerMoveMouseParams, ComputerPressKeyParams, ComputerScrollParams, + ComputerSetCursorVisibilityParams, + ComputerSetCursorVisibilityResponse, ComputerTypeTextParams, } from './computer'; import * as LogsAPI from './logs'; @@ -759,12 +761,14 @@ export declare namespace Browsers { export { Computer as Computer, + type ComputerSetCursorVisibilityResponse as ComputerSetCursorVisibilityResponse, type ComputerCaptureScreenshotParams as ComputerCaptureScreenshotParams, type ComputerClickMouseParams as ComputerClickMouseParams, type ComputerDragMouseParams as ComputerDragMouseParams, type ComputerMoveMouseParams as ComputerMoveMouseParams, type ComputerPressKeyParams as ComputerPressKeyParams, type ComputerScrollParams as ComputerScrollParams, + type ComputerSetCursorVisibilityParams as ComputerSetCursorVisibilityParams, type ComputerTypeTextParams as ComputerTypeTextParams, }; diff --git a/src/resources/browsers/computer.ts b/src/resources/browsers/computer.ts index 49c2954a..575cfadb 100644 --- a/src/resources/browsers/computer.ts +++ b/src/resources/browsers/computer.ts @@ -125,6 +125,25 @@ export class Computer extends APIResource { }); } + /** + * Set cursor visibility + * + * @example + * ```ts + * const response = + * await client.browsers.computer.setCursorVisibility('id', { + * hidden: true, + * }); + * ``` + */ + setCursorVisibility( + id: string, + body: ComputerSetCursorVisibilityParams, + options?: RequestOptions, + ): APIPromise { + return this._client.post(path`/browsers/${id}/computer/cursor`, { body, ...options }); + } + /** * Type text on the browser instance * @@ -144,6 +163,16 @@ export class Computer extends APIResource { } } +/** + * Generic OK response. + */ +export interface ComputerSetCursorVisibilityResponse { + /** + * Indicates success. + */ + ok: boolean; +} + export interface ComputerCaptureScreenshotParams { region?: ComputerCaptureScreenshotParams.Region; } @@ -303,6 +332,13 @@ export interface ComputerScrollParams { hold_keys?: Array; } +export interface ComputerSetCursorVisibilityParams { + /** + * Whether the cursor should be hidden or visible + */ + hidden: boolean; +} + export interface ComputerTypeTextParams { /** * Text to type on the browser instance @@ -317,12 +353,14 @@ export interface ComputerTypeTextParams { export declare namespace Computer { export { + type ComputerSetCursorVisibilityResponse as ComputerSetCursorVisibilityResponse, type ComputerCaptureScreenshotParams as ComputerCaptureScreenshotParams, type ComputerClickMouseParams as ComputerClickMouseParams, type ComputerDragMouseParams as ComputerDragMouseParams, type ComputerMoveMouseParams as ComputerMoveMouseParams, type ComputerPressKeyParams as ComputerPressKeyParams, type ComputerScrollParams as ComputerScrollParams, + type ComputerSetCursorVisibilityParams as ComputerSetCursorVisibilityParams, type ComputerTypeTextParams as ComputerTypeTextParams, }; } diff --git a/src/resources/browsers/index.ts b/src/resources/browsers/index.ts index 4bba3981..c4dcd773 100644 --- a/src/resources/browsers/index.ts +++ b/src/resources/browsers/index.ts @@ -13,12 +13,14 @@ export { } from './browsers'; export { Computer, + type ComputerSetCursorVisibilityResponse, type ComputerCaptureScreenshotParams, type ComputerClickMouseParams, type ComputerDragMouseParams, type ComputerMoveMouseParams, type ComputerPressKeyParams, type ComputerScrollParams, + type ComputerSetCursorVisibilityParams, type ComputerTypeTextParams, } from './computer'; export { diff --git a/tests/api-resources/browsers/computer.test.ts b/tests/api-resources/browsers/computer.test.ts index 2c2d7def..eb938fd2 100644 --- a/tests/api-resources/browsers/computer.test.ts +++ b/tests/api-resources/browsers/computer.test.ts @@ -136,6 +136,23 @@ describe('resource computer', () => { }); }); + // Prism tests are disabled + test.skip('setCursorVisibility: only required params', async () => { + const responsePromise = client.browsers.computer.setCursorVisibility('id', { hidden: true }); + 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); + }); + + // Prism tests are disabled + test.skip('setCursorVisibility: required and optional params', async () => { + const response = await client.browsers.computer.setCursorVisibility('id', { hidden: true }); + }); + // Prism tests are disabled test.skip('typeText: only required params', async () => { const responsePromise = client.browsers.computer.typeText('id', { text: 'text' }); From fd9e4c904ce3d818d03ef8dacdc5f9713722b7ee Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 12 Nov 2025 18:03:20 +0000 Subject: [PATCH 204/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 5e39b941..19ee807a 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.18.0" + ".": "0.19.0" } diff --git a/package.json b/package.json index af60924a..7f5f0043 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.18.0", + "version": "0.19.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 74131f9d..02c8084e 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.18.0'; // x-release-please-version +export const VERSION = '0.19.0'; // x-release-please-version From d872e75bd82ce934369a1c6fd3cfead5c2eb47f0 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 13 Nov 2025 16:09:12 +0000 Subject: [PATCH 205/551] feat: works locally --- .stats.yml | 4 ++-- src/resources/browsers/browsers.ts | 32 +++++++++++++++--------------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/.stats.yml b/.stats.yml index 125a84b7..b12b0715 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 66 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-86854c41729a6b26f71e26c906f665f69939f23e2d7adcc43380aee64cf6d056.yml -openapi_spec_hash: 270a40c8af29e83cbda77d3700fd456a +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-7897c6c3f33d12ebf6cb8b3694945169617631a52af8f5b393b77b1995ed0d72.yml +openapi_spec_hash: 1104c3ba0915f1708d7576345cafa9d0 config_hash: 9421eb86b7f3f4b274f123279da3858e diff --git a/src/resources/browsers/browsers.ts b/src/resources/browsers/browsers.ts index e05d2195..de85bd13 100644 --- a/src/resources/browsers/browsers.ts +++ b/src/resources/browsers/browsers.ts @@ -283,8 +283,8 @@ export interface BrowserCreateResponse { * image defaults apply (commonly 1024x768@60). Only specific viewport * configurations are supported. The server will reject unsupported combinations. * Supported resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25, - * 1440x900@25, 1024x768@60 If refresh_rate is not provided, it will be - * automatically determined from the width and height if they match a supported + * 1440x900@25, 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will + * be automatically determined from the width and height if they match a supported * configuration exactly. Note: Higher resolutions may affect the responsiveness of * live view browser */ @@ -297,8 +297,8 @@ export namespace BrowserCreateResponse { * image defaults apply (commonly 1024x768@60). Only specific viewport * configurations are supported. The server will reject unsupported combinations. * Supported resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25, - * 1440x900@25, 1024x768@60 If refresh_rate is not provided, it will be - * automatically determined from the width and height if they match a supported + * 1440x900@25, 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will + * be automatically determined from the width and height if they match a supported * configuration exactly. Note: Higher resolutions may affect the responsiveness of * live view browser */ @@ -383,8 +383,8 @@ export interface BrowserRetrieveResponse { * image defaults apply (commonly 1024x768@60). Only specific viewport * configurations are supported. The server will reject unsupported combinations. * Supported resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25, - * 1440x900@25, 1024x768@60 If refresh_rate is not provided, it will be - * automatically determined from the width and height if they match a supported + * 1440x900@25, 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will + * be automatically determined from the width and height if they match a supported * configuration exactly. Note: Higher resolutions may affect the responsiveness of * live view browser */ @@ -397,8 +397,8 @@ export namespace BrowserRetrieveResponse { * image defaults apply (commonly 1024x768@60). Only specific viewport * configurations are supported. The server will reject unsupported combinations. * Supported resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25, - * 1440x900@25, 1024x768@60 If refresh_rate is not provided, it will be - * automatically determined from the width and height if they match a supported + * 1440x900@25, 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will + * be automatically determined from the width and height if they match a supported * configuration exactly. Note: Higher resolutions may affect the responsiveness of * live view browser */ @@ -486,8 +486,8 @@ export namespace BrowserListResponse { * image defaults apply (commonly 1024x768@60). Only specific viewport * configurations are supported. The server will reject unsupported combinations. * Supported resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25, - * 1440x900@25, 1024x768@60 If refresh_rate is not provided, it will be - * automatically determined from the width and height if they match a supported + * 1440x900@25, 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will + * be automatically determined from the width and height if they match a supported * configuration exactly. Note: Higher resolutions may affect the responsiveness of * live view browser */ @@ -500,8 +500,8 @@ export namespace BrowserListResponse { * image defaults apply (commonly 1024x768@60). Only specific viewport * configurations are supported. The server will reject unsupported combinations. * Supported resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25, - * 1440x900@25, 1024x768@60 If refresh_rate is not provided, it will be - * automatically determined from the width and height if they match a supported + * 1440x900@25, 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will + * be automatically determined from the width and height if they match a supported * configuration exactly. Note: Higher resolutions may affect the responsiveness of * live view browser */ @@ -587,8 +587,8 @@ export interface BrowserCreateParams { * image defaults apply (commonly 1024x768@60). Only specific viewport * configurations are supported. The server will reject unsupported combinations. * Supported resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25, - * 1440x900@25, 1024x768@60 If refresh_rate is not provided, it will be - * automatically determined from the width and height if they match a supported + * 1440x900@25, 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will + * be automatically determined from the width and height if they match a supported * configuration exactly. Note: Higher resolutions may affect the responsiveness of * live view browser */ @@ -642,8 +642,8 @@ export namespace BrowserCreateParams { * image defaults apply (commonly 1024x768@60). Only specific viewport * configurations are supported. The server will reject unsupported combinations. * Supported resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25, - * 1440x900@25, 1024x768@60 If refresh_rate is not provided, it will be - * automatically determined from the width and height if they match a supported + * 1440x900@25, 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will + * be automatically determined from the width and height if they match a supported * configuration exactly. Note: Higher resolutions may affect the responsiveness of * live view browser */ From 192b6df27140f49a5409f0dcbce64aaec7eeb809 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 13 Nov 2025 16:40:12 +0000 Subject: [PATCH 206/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 19ee807a..4a403c7d 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.19.0" + ".": "0.19.1" } diff --git a/package.json b/package.json index 7f5f0043..0765ad39 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.19.0", + "version": "0.19.1", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 02c8084e..f3ae0bb2 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.19.0'; // x-release-please-version +export const VERSION = '0.19.1'; // x-release-please-version From d1aabe21c7be5f90c93a20bcfe3907b74b7b2b11 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 17 Nov 2025 14:21:32 +0000 Subject: [PATCH 207/551] feat: Feat increase max timeout to 72h --- .stats.yml | 4 ++-- src/resources/browsers/browsers.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.stats.yml b/.stats.yml index b12b0715..53123c95 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 66 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-7897c6c3f33d12ebf6cb8b3694945169617631a52af8f5b393b77b1995ed0d72.yml -openapi_spec_hash: 1104c3ba0915f1708d7576345cafa9d0 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-d611cf8b0301a07123eab0e92498bea5ad69c5292b28aca1016c362cca0a0564.yml +openapi_spec_hash: 6d30f4ad9d61a7da8a75d543cf3d3d75 config_hash: 9421eb86b7f3f4b274f123279da3858e diff --git a/src/resources/browsers/browsers.ts b/src/resources/browsers/browsers.ts index de85bd13..e3fb6c45 100644 --- a/src/resources/browsers/browsers.ts +++ b/src/resources/browsers/browsers.ts @@ -576,7 +576,7 @@ export interface BrowserCreateParams { * The number of seconds of inactivity before the browser session is terminated. * Only applicable to non-persistent browsers. Activity includes CDP connections * and live view connections. Defaults to 60 seconds. Minimum allowed is 10 - * seconds. Maximum allowed is 86400 (24 hours). We check for inactivity every 5 + * seconds. Maximum allowed is 259200 (72 hours). We check for inactivity every 5 * seconds, so the actual timeout behavior you will see is +/- 5 seconds around the * specified value. */ From 64ed9d4177b0bd3e9c3fa9ccf448d64aa4e97833 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 17 Nov 2025 14:42:43 +0000 Subject: [PATCH 208/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 4a403c7d..b2c706c7 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.19.1" + ".": "0.19.2" } diff --git a/package.json b/package.json index 0765ad39..b5880c81 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.19.1", + "version": "0.19.2", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index f3ae0bb2..2f39e967 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.19.1'; // x-release-please-version +export const VERSION = '0.19.2'; // x-release-please-version From 20a1f4f074d6f00804c51103c3f23acfaaf2e52e Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 19 Nov 2025 19:37:19 +0000 Subject: [PATCH 209/551] feat: allow get browser to paginate soft deleted browsers --- .stats.yml | 4 +- api.md | 2 +- src/client.ts | 4 + src/resources/browsers/browsers.ts | 204 ++++++++++-------- src/resources/browsers/index.ts | 2 + src/resources/index.ts | 2 + tests/api-resources/browsers/browsers.test.ts | 11 + 7 files changed, 139 insertions(+), 90 deletions(-) diff --git a/.stats.yml b/.stats.yml index 53123c95..11b820d4 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 66 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-d611cf8b0301a07123eab0e92498bea5ad69c5292b28aca1016c362cca0a0564.yml -openapi_spec_hash: 6d30f4ad9d61a7da8a75d543cf3d3d75 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-2af1b468584cb44aa9babbbfb82bff4055614fbb5c815084a6b7dacc1cf1a822.yml +openapi_spec_hash: 891affa2849341ea01d62011125f7edc config_hash: 9421eb86b7f3f4b274f123279da3858e diff --git a/api.md b/api.md index 216b25f9..982d8410 100644 --- a/api.md +++ b/api.md @@ -70,7 +70,7 @@ Methods: - client.browsers.create({ ...params }) -> BrowserCreateResponse - client.browsers.retrieve(id) -> BrowserRetrieveResponse -- client.browsers.list() -> BrowserListResponse +- client.browsers.list({ ...params }) -> BrowserListResponsesOffsetPagination - client.browsers.delete({ ...params }) -> void - client.browsers.deleteByID(id) -> void - client.browsers.loadExtensions(id, { ...params }) -> void diff --git a/src/client.ts b/src/client.ts index eaef9225..e0b23cbe 100644 --- a/src/client.ts +++ b/src/client.ts @@ -64,7 +64,9 @@ import { BrowserCreateParams, BrowserCreateResponse, BrowserDeleteParams, + BrowserListParams, BrowserListResponse, + BrowserListResponsesOffsetPagination, BrowserLoadExtensionsParams, BrowserPersistence, BrowserRetrieveResponse, @@ -879,7 +881,9 @@ export declare namespace Kernel { type BrowserCreateResponse as BrowserCreateResponse, type BrowserRetrieveResponse as BrowserRetrieveResponse, type BrowserListResponse as BrowserListResponse, + type BrowserListResponsesOffsetPagination as BrowserListResponsesOffsetPagination, type BrowserCreateParams as BrowserCreateParams, + type BrowserListParams as BrowserListParams, type BrowserDeleteParams as BrowserDeleteParams, type BrowserLoadExtensionsParams as BrowserLoadExtensionsParams, }; diff --git a/src/resources/browsers/browsers.ts b/src/resources/browsers/browsers.ts index e3fb6c45..1c0f9bca 100644 --- a/src/resources/browsers/browsers.ts +++ b/src/resources/browsers/browsers.ts @@ -1,7 +1,6 @@ // 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 ComputerAPI from './computer'; import { Computer, @@ -63,6 +62,7 @@ import { Fs, } from './fs/fs'; import { APIPromise } from '../../core/api-promise'; +import { OffsetPagination, type OffsetPaginationParams, PagePromise } from '../../core/pagination'; import { type Uploadable } from '../../core/uploads'; import { buildHeaders } from '../../internal/headers'; import { RequestOptions } from '../../internal/request-options'; @@ -107,15 +107,22 @@ export class Browsers extends APIResource { } /** - * List active browser sessions + * List all browser sessions with pagination support. Use include_deleted=true to + * include soft-deleted sessions in the results. * * @example * ```ts - * const browsers = await client.browsers.list(); + * // Automatically fetches more pages as needed. + * for await (const browserListResponse of client.browsers.list()) { + * // ... + * } * ``` */ - list(options?: RequestOptions): APIPromise { - return this._client.get('/browsers', options); + list( + query: BrowserListParams | null | undefined = {}, + options?: RequestOptions, + ): PagePromise { + return this._client.getAPIList('/browsers', OffsetPagination, { query, ...options }); } /** @@ -181,6 +188,8 @@ export class Browsers extends APIResource { } } +export type BrowserListResponsesOffsetPagination = OffsetPagination; + /** * Optional persistence configuration for the browser session. */ @@ -258,6 +267,11 @@ export interface BrowserCreateResponse { */ browser_live_view_url?: string; + /** + * When the browser session was soft-deleted. Only present for deleted sessions. + */ + deleted_at?: string; + /** * Whether the browser session is running in kiosk mode. */ @@ -358,6 +372,11 @@ export interface BrowserRetrieveResponse { */ browser_live_view_url?: string; + /** + * When the browser session was soft-deleted. Only present for deleted sessions. + */ + deleted_at?: string; + /** * Whether the browser session is running in kiosk mode. */ @@ -421,107 +440,108 @@ export namespace BrowserRetrieveResponse { } } -export type BrowserListResponse = Array; +export interface BrowserListResponse { + /** + * Websocket URL for Chrome DevTools Protocol connections to the browser session + */ + cdp_ws_url: string; -export namespace BrowserListResponse { - export interface BrowserListResponseItem { - /** - * Websocket URL for Chrome DevTools Protocol connections to the browser session - */ - cdp_ws_url: string; + /** + * When the browser session was created. + */ + created_at: string; - /** - * When the browser session was created. - */ - created_at: string; + /** + * Whether the browser session is running in headless mode. + */ + headless: boolean; - /** - * Whether the browser session is running in headless mode. - */ - headless: boolean; + /** + * Unique identifier for the browser session + */ + session_id: string; - /** - * Unique identifier for the browser session - */ - session_id: string; + /** + * Whether the browser session is running in stealth mode. + */ + stealth: boolean; - /** - * Whether the browser session is running in stealth mode. - */ - stealth: boolean; + /** + * The number of seconds of inactivity before the browser session is terminated. + */ + timeout_seconds: number; - /** - * The number of seconds of inactivity before the browser session is terminated. - */ - timeout_seconds: number; + /** + * Remote URL for live viewing the browser session. Only available for non-headless + * browsers. + */ + browser_live_view_url?: string; - /** - * Remote URL for live viewing the browser session. Only available for non-headless - * browsers. - */ - browser_live_view_url?: string; + /** + * When the browser session was soft-deleted. Only present for deleted sessions. + */ + deleted_at?: string; - /** - * Whether the browser session is running in kiosk mode. - */ - kiosk_mode?: boolean; + /** + * Whether the browser session is running in kiosk mode. + */ + kiosk_mode?: boolean; - /** - * Optional persistence configuration for the browser session. - */ - persistence?: BrowsersAPI.BrowserPersistence; + /** + * Optional persistence configuration for the browser session. + */ + persistence?: BrowserPersistence; - /** - * Browser profile metadata. - */ - profile?: BrowsersAPI.Profile; + /** + * Browser profile metadata. + */ + profile?: Profile; + + /** + * ID of the proxy associated with this browser session, if any. + */ + proxy_id?: string; + + /** + * Initial browser window size in pixels with optional refresh rate. If omitted, + * image defaults apply (commonly 1024x768@60). Only specific viewport + * configurations are supported. The server will reject unsupported combinations. + * Supported resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25, + * 1440x900@25, 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will + * be automatically determined from the width and height if they match a supported + * configuration exactly. Note: Higher resolutions may affect the responsiveness of + * live view browser + */ + viewport?: BrowserListResponse.Viewport; +} +export namespace BrowserListResponse { + /** + * Initial browser window size in pixels with optional refresh rate. If omitted, + * image defaults apply (commonly 1024x768@60). Only specific viewport + * configurations are supported. The server will reject unsupported combinations. + * Supported resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25, + * 1440x900@25, 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will + * be automatically determined from the width and height if they match a supported + * configuration exactly. Note: Higher resolutions may affect the responsiveness of + * live view browser + */ + export interface Viewport { /** - * ID of the proxy associated with this browser session, if any. + * Browser window height in pixels. */ - proxy_id?: string; + height: number; /** - * Initial browser window size in pixels with optional refresh rate. If omitted, - * image defaults apply (commonly 1024x768@60). Only specific viewport - * configurations are supported. The server will reject unsupported combinations. - * Supported resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25, - * 1440x900@25, 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will - * be automatically determined from the width and height if they match a supported - * configuration exactly. Note: Higher resolutions may affect the responsiveness of - * live view browser + * Browser window width in pixels. */ - viewport?: BrowserListResponseItem.Viewport; - } + width: number; - export namespace BrowserListResponseItem { /** - * Initial browser window size in pixels with optional refresh rate. If omitted, - * image defaults apply (commonly 1024x768@60). Only specific viewport - * configurations are supported. The server will reject unsupported combinations. - * Supported resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25, - * 1440x900@25, 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will - * be automatically determined from the width and height if they match a supported - * configuration exactly. Note: Higher resolutions may affect the responsiveness of - * live view browser + * Display refresh rate in Hz. If omitted, automatically determined from width and + * height. */ - export interface Viewport { - /** - * Browser window height in pixels. - */ - height: number; - - /** - * Browser window width in pixels. - */ - width: number; - - /** - * Display refresh rate in Hz. If omitted, automatically determined from width and - * height. - */ - refresh_rate?: number; - } + refresh_rate?: number; } } @@ -666,6 +686,14 @@ export namespace BrowserCreateParams { } } +export interface BrowserListParams extends OffsetPaginationParams { + /** + * When true, includes soft-deleted browser sessions in the results alongside + * active sessions. + */ + include_deleted?: boolean; +} + export interface BrowserDeleteParams { /** * Persistent browser identifier @@ -709,7 +737,9 @@ export declare namespace Browsers { type BrowserCreateResponse as BrowserCreateResponse, type BrowserRetrieveResponse as BrowserRetrieveResponse, type BrowserListResponse as BrowserListResponse, + type BrowserListResponsesOffsetPagination as BrowserListResponsesOffsetPagination, type BrowserCreateParams as BrowserCreateParams, + type BrowserListParams as BrowserListParams, type BrowserDeleteParams as BrowserDeleteParams, type BrowserLoadExtensionsParams as BrowserLoadExtensionsParams, }; diff --git a/src/resources/browsers/index.ts b/src/resources/browsers/index.ts index c4dcd773..569517ab 100644 --- a/src/resources/browsers/index.ts +++ b/src/resources/browsers/index.ts @@ -8,8 +8,10 @@ export { type BrowserRetrieveResponse, type BrowserListResponse, type BrowserCreateParams, + type BrowserListParams, type BrowserDeleteParams, type BrowserLoadExtensionsParams, + type BrowserListResponsesOffsetPagination, } from './browsers'; export { Computer, diff --git a/src/resources/index.ts b/src/resources/index.ts index d7e326c3..69c693d1 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -15,8 +15,10 @@ export { type BrowserRetrieveResponse, type BrowserListResponse, type BrowserCreateParams, + type BrowserListParams, type BrowserDeleteParams, type BrowserLoadExtensionsParams, + type BrowserListResponsesOffsetPagination, } from './browsers/browsers'; export { Deployments, diff --git a/tests/api-resources/browsers/browsers.test.ts b/tests/api-resources/browsers/browsers.test.ts index 14ec8f84..c44ac77a 100644 --- a/tests/api-resources/browsers/browsers.test.ts +++ b/tests/api-resources/browsers/browsers.test.ts @@ -66,6 +66,17 @@ describe('resource browsers', () => { expect(dataAndResponse.response).toBe(rawResponse); }); + // Prism tests are disabled + test.skip('list: 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.list( + { include_deleted: true, limit: 1, offset: 0 }, + { path: '/_stainless_unknown_path' }, + ), + ).rejects.toThrow(Kernel.NotFoundError); + }); + // Prism tests are disabled test.skip('delete: only required params', async () => { const responsePromise = client.browsers.delete({ persistent_id: 'persistent_id' }); From 90deeb27b9d0fbd90963c6528dda45d69ceb3959 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 19 Nov 2025 19:50:38 +0000 Subject: [PATCH 210/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index b2c706c7..71e95baf 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.19.2" + ".": "0.20.0" } diff --git a/package.json b/package.json index b5880c81..6fa7c739 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.19.2", + "version": "0.20.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 2f39e967..b4e51da6 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.19.2'; // x-release-please-version +export const VERSION = '0.20.0'; // x-release-please-version From c68ae44b5313d1524338b9bc1f0ccb526010954f Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 24 Nov 2025 18:52:47 +0000 Subject: [PATCH 211/551] feat: Mason/agent auth api --- .stats.yml | 8 +- api.md | 29 +++ src/client.ts | 5 + src/resources/agents.ts | 3 + src/resources/agents/agents.ts | 31 +++ src/resources/agents/auth.ts | 3 + src/resources/agents/auth/auth.ts | 245 +++++++++++++++++++ src/resources/agents/auth/index.ts | 18 ++ src/resources/agents/auth/runs.ts | 125 ++++++++++ src/resources/agents/index.ts | 12 + src/resources/index.ts | 1 + tests/api-resources/agents/auth/auth.test.ts | 35 +++ tests/api-resources/agents/auth/runs.test.ts | 80 ++++++ 13 files changed, 591 insertions(+), 4 deletions(-) create mode 100644 src/resources/agents.ts create mode 100644 src/resources/agents/agents.ts create mode 100644 src/resources/agents/auth.ts create mode 100644 src/resources/agents/auth/auth.ts create mode 100644 src/resources/agents/auth/index.ts create mode 100644 src/resources/agents/auth/runs.ts create mode 100644 src/resources/agents/index.ts create mode 100644 tests/api-resources/agents/auth/auth.test.ts create mode 100644 tests/api-resources/agents/auth/runs.test.ts diff --git a/.stats.yml b/.stats.yml index 11b820d4..bdbede3e 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 66 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-2af1b468584cb44aa9babbbfb82bff4055614fbb5c815084a6b7dacc1cf1a822.yml -openapi_spec_hash: 891affa2849341ea01d62011125f7edc -config_hash: 9421eb86b7f3f4b274f123279da3858e +configured_endpoints: 71 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-bb3f37e55117a56e7a4208bd646d3a68adeb651ced8531e13fbfc1fc9dcb05a4.yml +openapi_spec_hash: 7303ce8ce3130e16a6a5c2bb49e43e9b +config_hash: be146470fb2d4583b6533859f0fa48f5 diff --git a/api.md b/api.md index 982d8410..b16b4351 100644 --- a/api.md +++ b/api.md @@ -220,3 +220,32 @@ Methods: - client.extensions.download(idOrName) -> Response - client.extensions.downloadFromChromeStore({ ...params }) -> Response - client.extensions.upload({ ...params }) -> ExtensionUploadResponse + +# Agents + +## Auth + +Types: + +- AgentAuthDiscoverResponse +- AgentAuthRunResponse +- AgentAuthStartResponse +- AgentAuthSubmitResponse +- DiscoveredField + +Methods: + +- client.agents.auth.start({ ...params }) -> AgentAuthStartResponse + +### Runs + +Types: + +- RunExchangeResponse + +Methods: + +- client.agents.auth.runs.retrieve(runID) -> AgentAuthRunResponse +- client.agents.auth.runs.discover(runID) -> AgentAuthDiscoverResponse +- client.agents.auth.runs.exchange(runID, { ...params }) -> RunExchangeResponse +- client.agents.auth.runs.submit(runID, { ...params }) -> AgentAuthSubmitResponse diff --git a/src/client.ts b/src/client.ts index e0b23cbe..7bdbd166 100644 --- a/src/client.ts +++ b/src/client.ts @@ -60,6 +60,7 @@ import { ProxyListResponse, ProxyRetrieveResponse, } from './resources/proxies'; +import { Agents } from './resources/agents/agents'; import { BrowserCreateParams, BrowserCreateResponse, @@ -820,6 +821,7 @@ export class Kernel { profiles: API.Profiles = new API.Profiles(this); proxies: API.Proxies = new API.Proxies(this); extensions: API.Extensions = new API.Extensions(this); + agents: API.Agents = new API.Agents(this); } Kernel.Deployments = Deployments; @@ -829,6 +831,7 @@ Kernel.Browsers = Browsers; Kernel.Profiles = Profiles; Kernel.Proxies = Proxies; Kernel.Extensions = Extensions; +Kernel.Agents = Agents; export declare namespace Kernel { export type RequestOptions = Opts.RequestOptions; @@ -910,6 +913,8 @@ export declare namespace Kernel { type ExtensionUploadParams as ExtensionUploadParams, }; + export { Agents as Agents }; + export type AppAction = API.AppAction; export type ErrorDetail = API.ErrorDetail; export type ErrorEvent = API.ErrorEvent; diff --git a/src/resources/agents.ts b/src/resources/agents.ts new file mode 100644 index 00000000..0c43db07 --- /dev/null +++ b/src/resources/agents.ts @@ -0,0 +1,3 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export * from './agents/index'; diff --git a/src/resources/agents/agents.ts b/src/resources/agents/agents.ts new file mode 100644 index 00000000..67fd75b2 --- /dev/null +++ b/src/resources/agents/agents.ts @@ -0,0 +1,31 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../core/resource'; +import * as AuthAPI from './auth/auth'; +import { + AgentAuthDiscoverResponse, + AgentAuthRunResponse, + AgentAuthStartResponse, + AgentAuthSubmitResponse, + Auth, + AuthStartParams, + DiscoveredField, +} from './auth/auth'; + +export class Agents extends APIResource { + auth: AuthAPI.Auth = new AuthAPI.Auth(this._client); +} + +Agents.Auth = Auth; + +export declare namespace Agents { + export { + Auth as Auth, + type AgentAuthDiscoverResponse as AgentAuthDiscoverResponse, + type AgentAuthRunResponse as AgentAuthRunResponse, + type AgentAuthStartResponse as AgentAuthStartResponse, + type AgentAuthSubmitResponse as AgentAuthSubmitResponse, + type DiscoveredField as DiscoveredField, + type AuthStartParams as AuthStartParams, + }; +} diff --git a/src/resources/agents/auth.ts b/src/resources/agents/auth.ts new file mode 100644 index 00000000..b64faa13 --- /dev/null +++ b/src/resources/agents/auth.ts @@ -0,0 +1,3 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export * from './auth/index'; diff --git a/src/resources/agents/auth/auth.ts b/src/resources/agents/auth/auth.ts new file mode 100644 index 00000000..a97ee3be --- /dev/null +++ b/src/resources/agents/auth/auth.ts @@ -0,0 +1,245 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../../core/resource'; +import * as RunsAPI from './runs'; +import { RunDiscoverParams, RunExchangeParams, RunExchangeResponse, RunSubmitParams, Runs } from './runs'; +import { APIPromise } from '../../../core/api-promise'; +import { RequestOptions } from '../../../internal/request-options'; + +export class Auth extends APIResource { + runs: RunsAPI.Runs = new RunsAPI.Runs(this._client); + + /** + * Creates a browser session and returns a handoff code for the hosted flow. Uses + * standard API key or JWT authentication (not the JWT returned by the exchange + * endpoint). + * + * @example + * ```ts + * const agentAuthStartResponse = + * await client.agents.auth.start({ + * profile_name: 'auth-abc123', + * target_domain: 'doordash.com', + * }); + * ``` + */ + start(body: AuthStartParams, options?: RequestOptions): APIPromise { + return this._client.post('/agents/auth/start', { body, ...options }); + } +} + +/** + * Response from discover endpoint matching AuthBlueprint schema + */ +export interface AgentAuthDiscoverResponse { + /** + * Whether discovery succeeded + */ + success: boolean; + + /** + * Error message if discovery failed + */ + error_message?: string; + + /** + * Discovered form fields (present when success is true) + */ + fields?: Array; + + /** + * Whether user is already logged in + */ + logged_in?: boolean; + + /** + * URL of the discovered login page + */ + login_url?: string; + + /** + * Title of the login page + */ + page_title?: string; +} + +/** + * Response from get run endpoint + */ +export interface AgentAuthRunResponse { + /** + * App name (org name at time of run creation) + */ + app_name: string; + + /** + * When the handoff code expires + */ + expires_at: string; + + /** + * Run status + */ + status: 'ACTIVE' | 'ENDED' | 'EXPIRED' | 'CANCELED'; + + /** + * Target domain for authentication + */ + target_domain: string; +} + +/** + * Response from starting an agent authentication run + */ +export interface AgentAuthStartResponse { + /** + * When the handoff code expires + */ + expires_at: string; + + /** + * One-time code for handoff + */ + handoff_code: string; + + /** + * URL to redirect user to + */ + hosted_url: string; + + /** + * Unique identifier for the run + */ + run_id: string; +} + +/** + * Response from submit endpoint matching SubmitResult schema + */ +export interface AgentAuthSubmitResponse { + /** + * Whether submission succeeded + */ + success: boolean; + + /** + * Additional fields needed (e.g., OTP) - present when needs_additional_auth is + * true + */ + additional_fields?: Array; + + /** + * App name (only present when logged_in is true) + */ + app_name?: string; + + /** + * Error message if submission failed + */ + error_message?: string; + + /** + * Whether user is now logged in + */ + logged_in?: boolean; + + /** + * Whether additional authentication fields are needed + */ + needs_additional_auth?: boolean; + + /** + * Target domain (only present when logged_in is true) + */ + target_domain?: string; +} + +/** + * A discovered form field + */ +export interface DiscoveredField { + /** + * Field label + */ + label: string; + + /** + * Field name + */ + name: string; + + /** + * CSS selector for the field + */ + selector: string; + + /** + * Field type + */ + type: 'text' | 'email' | 'password' | 'tel' | 'number' | 'url' | 'code' | 'checkbox'; + + /** + * Field placeholder + */ + placeholder?: string; + + /** + * Whether field is required + */ + required?: boolean; +} + +export interface AuthStartParams { + /** + * Name of the profile to use for this flow + */ + profile_name: string; + + /** + * Target domain for authentication + */ + target_domain: string; + + /** + * Optional logo URL for the application + */ + app_logo_url?: string; + + /** + * Optional proxy configuration + */ + proxy?: AuthStartParams.Proxy; +} + +export namespace AuthStartParams { + /** + * Optional proxy configuration + */ + export interface Proxy { + /** + * ID of the proxy to use + */ + proxy_id?: string; + } +} + +Auth.Runs = Runs; + +export declare namespace Auth { + export { + type AgentAuthDiscoverResponse as AgentAuthDiscoverResponse, + type AgentAuthRunResponse as AgentAuthRunResponse, + type AgentAuthStartResponse as AgentAuthStartResponse, + type AgentAuthSubmitResponse as AgentAuthSubmitResponse, + type DiscoveredField as DiscoveredField, + type AuthStartParams as AuthStartParams, + }; + + export { + Runs as Runs, + type RunExchangeResponse as RunExchangeResponse, + type RunDiscoverParams as RunDiscoverParams, + type RunExchangeParams as RunExchangeParams, + type RunSubmitParams as RunSubmitParams, + }; +} diff --git a/src/resources/agents/auth/index.ts b/src/resources/agents/auth/index.ts new file mode 100644 index 00000000..904c0ce0 --- /dev/null +++ b/src/resources/agents/auth/index.ts @@ -0,0 +1,18 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export { + Auth, + type AgentAuthDiscoverResponse, + type AgentAuthRunResponse, + type AgentAuthStartResponse, + type AgentAuthSubmitResponse, + type DiscoveredField, + type AuthStartParams, +} from './auth'; +export { + Runs, + type RunExchangeResponse, + type RunDiscoverParams, + type RunExchangeParams, + type RunSubmitParams, +} from './runs'; diff --git a/src/resources/agents/auth/runs.ts b/src/resources/agents/auth/runs.ts new file mode 100644 index 00000000..7b9e2e46 --- /dev/null +++ b/src/resources/agents/auth/runs.ts @@ -0,0 +1,125 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../../core/resource'; +import * as AuthAPI from './auth'; +import { APIPromise } from '../../../core/api-promise'; +import { RequestOptions } from '../../../internal/request-options'; +import { path } from '../../../internal/utils/path'; + +export class Runs extends APIResource { + /** + * Returns run details including app_name and target_domain. Uses the JWT returned + * by the exchange endpoint, or standard API key or JWT authentication. + * + * @example + * ```ts + * const agentAuthRunResponse = + * await client.agents.auth.runs.retrieve('run_id'); + * ``` + */ + retrieve(runID: string, options?: RequestOptions): APIPromise { + return this._client.get(path`/agents/auth/runs/${runID}`, options); + } + + /** + * Inspects the target site to detect logged-in state or discover required fields. + * Returns 200 with success: true when fields are found, or 4xx/5xx for failures. + * Requires the JWT returned by the exchange endpoint. + * + * @example + * ```ts + * const agentAuthDiscoverResponse = + * await client.agents.auth.runs.discover('run_id'); + * ``` + */ + discover( + runID: string, + body?: RunDiscoverParams | null | undefined, + options?: RequestOptions, + ): APIPromise { + return this._client.post(path`/agents/auth/runs/${runID}/discover`, { body, ...options }); + } + + /** + * Validates the handoff code and returns a JWT token for subsequent requests. No + * authentication required (the handoff code serves as the credential). + * + * @example + * ```ts + * const response = await client.agents.auth.runs.exchange( + * 'run_id', + * { code: 'otp_abc123xyz' }, + * ); + * ``` + */ + exchange( + runID: string, + body: RunExchangeParams, + options?: RequestOptions, + ): APIPromise { + return this._client.post(path`/agents/auth/runs/${runID}/exchange`, { body, ...options }); + } + + /** + * Submits field values for the discovered login form and may return additional + * auth fields or success. Requires the JWT returned by the exchange endpoint. + * + * @example + * ```ts + * const agentAuthSubmitResponse = + * await client.agents.auth.runs.submit('run_id', { + * field_values: { + * email: 'user@example.com', + * password: '********', + * }, + * }); + * ``` + */ + submit( + runID: string, + body: RunSubmitParams, + options?: RequestOptions, + ): APIPromise { + return this._client.post(path`/agents/auth/runs/${runID}/submit`, { body, ...options }); + } +} + +/** + * Response from exchange endpoint + */ +export interface RunExchangeResponse { + /** + * JWT token with run_id claim (30 minute TTL) + */ + jwt: string; + + /** + * Run ID + */ + run_id: string; +} + +export interface RunDiscoverParams {} + +export interface RunExchangeParams { + /** + * Handoff code from start endpoint + */ + code: string; +} + +export interface RunSubmitParams { + /** + * Values for the discovered login fields + */ + field_values: { [key: string]: string }; +} + +export declare namespace Runs { + export { + type RunExchangeResponse as RunExchangeResponse, + type RunDiscoverParams as RunDiscoverParams, + type RunExchangeParams as RunExchangeParams, + type RunSubmitParams as RunSubmitParams, + }; +} diff --git a/src/resources/agents/index.ts b/src/resources/agents/index.ts new file mode 100644 index 00000000..c5647b79 --- /dev/null +++ b/src/resources/agents/index.ts @@ -0,0 +1,12 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export { Agents } from './agents'; +export { + Auth, + type AgentAuthDiscoverResponse, + type AgentAuthRunResponse, + type AgentAuthStartResponse, + type AgentAuthSubmitResponse, + type DiscoveredField, + type AuthStartParams, +} from './auth/index'; diff --git a/src/resources/index.ts b/src/resources/index.ts index 69c693d1..3e3fce48 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -1,6 +1,7 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. export * from './shared'; +export { Agents } from './agents/agents'; export { Apps, type AppListResponse, diff --git a/tests/api-resources/agents/auth/auth.test.ts b/tests/api-resources/agents/auth/auth.test.ts new file mode 100644 index 00000000..8d0224cf --- /dev/null +++ b/tests/api-resources/agents/auth/auth.test.ts @@ -0,0 +1,35 @@ +// 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 auth', () => { + // Prism tests are disabled + test.skip('start: only required params', async () => { + const responsePromise = client.agents.auth.start({ + profile_name: 'auth-abc123', + target_domain: 'doordash.com', + }); + 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); + }); + + // Prism tests are disabled + test.skip('start: required and optional params', async () => { + const response = await client.agents.auth.start({ + profile_name: 'auth-abc123', + target_domain: 'doordash.com', + app_logo_url: 'https://example.com/logo.png', + proxy: { proxy_id: 'proxy_id' }, + }); + }); +}); diff --git a/tests/api-resources/agents/auth/runs.test.ts b/tests/api-resources/agents/auth/runs.test.ts new file mode 100644 index 00000000..c3e8b4bd --- /dev/null +++ b/tests/api-resources/agents/auth/runs.test.ts @@ -0,0 +1,80 @@ +// 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 runs', () => { + // Prism tests are disabled + test.skip('retrieve', async () => { + const responsePromise = client.agents.auth.runs.retrieve('run_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); + }); + + // Prism tests are disabled + test.skip('discover', async () => { + const responsePromise = client.agents.auth.runs.discover('run_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); + }); + + // Prism tests are disabled + test.skip('discover: 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.agents.auth.runs.discover('run_id', {}, { path: '/_stainless_unknown_path' }), + ).rejects.toThrow(Kernel.NotFoundError); + }); + + // Prism tests are disabled + test.skip('exchange: only required params', async () => { + const responsePromise = client.agents.auth.runs.exchange('run_id', { code: 'otp_abc123xyz' }); + 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); + }); + + // Prism tests are disabled + test.skip('exchange: required and optional params', async () => { + const response = await client.agents.auth.runs.exchange('run_id', { code: 'otp_abc123xyz' }); + }); + + // Prism tests are disabled + test.skip('submit: only required params', async () => { + const responsePromise = client.agents.auth.runs.submit('run_id', { + field_values: { email: 'user@example.com', password: '********' }, + }); + 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); + }); + + // Prism tests are disabled + test.skip('submit: required and optional params', async () => { + const response = await client.agents.auth.runs.submit('run_id', { + field_values: { email: 'user@example.com', password: '********' }, + }); + }); +}); From 128b1e1ffe946ddb8045d8580996a195dcb96e7e Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 25 Nov 2025 18:13:27 +0000 Subject: [PATCH 212/551] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index bdbede3e..fa4f9006 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 71 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-bb3f37e55117a56e7a4208bd646d3a68adeb651ced8531e13fbfc1fc9dcb05a4.yml -openapi_spec_hash: 7303ce8ce3130e16a6a5c2bb49e43e9b +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-ae9ed0d949aa701dd3873e49080fe923404a8869ffcb69b7c912a3f244d0236d.yml +openapi_spec_hash: 654d6e13a8bfe2103b373c668f43b33d config_hash: be146470fb2d4583b6533859f0fa48f5 From 4e968c0462dc572ce3acbb742d4047b239d82021 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 26 Nov 2025 00:27:30 +0000 Subject: [PATCH 213/551] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index fa4f9006..541095fa 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 71 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-ae9ed0d949aa701dd3873e49080fe923404a8869ffcb69b7c912a3f244d0236d.yml -openapi_spec_hash: 654d6e13a8bfe2103b373c668f43b33d +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-2a63841293bec1bb651c5a24a95b2e9b5c07851dec1164de1aa2f87dafc51046.yml +openapi_spec_hash: d0bb3ca22c10b79758d503f717dd8e2f config_hash: be146470fb2d4583b6533859f0fa48f5 From db360954c7e281cd7c60e5ed053ca56fab6f6a4a Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 2 Dec 2025 01:22:14 +0000 Subject: [PATCH 214/551] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 541095fa..a6b35ee5 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 71 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-2a63841293bec1bb651c5a24a95b2e9b5c07851dec1164de1aa2f87dafc51046.yml -openapi_spec_hash: d0bb3ca22c10b79758d503f717dd8e2f +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-92b20a9e4650f645d3bb23b64f4ae72287bb41d3922ff1371426a91879186362.yml +openapi_spec_hash: a3c5f41d36734c980bc5313ee60b97cf config_hash: be146470fb2d4583b6533859f0fa48f5 From 45be3b09f5418222111ccb9543ce478e6c181202 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 2 Dec 2025 04:13:44 +0000 Subject: [PATCH 215/551] chore(client): fix logger property type --- src/client.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client.ts b/src/client.ts index 7bdbd166..e1689928 100644 --- a/src/client.ts +++ b/src/client.ts @@ -186,7 +186,7 @@ export class Kernel { baseURL: string; maxRetries: number; timeout: number; - logger: Logger | undefined; + logger: Logger; logLevel: LogLevel | undefined; fetchOptions: MergedRequestInit | undefined; From c601115c53cd4b97c5106d771197b35dcd1ba597 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 2 Dec 2025 20:24:35 +0000 Subject: [PATCH 216/551] feat: Browser pools sdk release --- .stats.yml | 8 +- api.md | 41 +- src/client.ts | 39 +- src/resources/agents.ts | 3 - src/resources/agents/agents.ts | 31 - src/resources/agents/auth.ts | 3 - src/resources/agents/auth/auth.ts | 245 -------- src/resources/agents/auth/index.ts | 18 - src/resources/agents/auth/runs.ts | 125 ----- src/resources/agents/index.ts | 12 - src/resources/browser-pools.ts | 560 +++++++++++++++++++ src/resources/browsers/browsers.ts | 174 +----- src/resources/index.ts | 16 +- src/resources/shared.ts | 69 +++ tests/api-resources/agents/auth/auth.test.ts | 35 -- tests/api-resources/agents/auth/runs.test.ts | 80 --- tests/api-resources/browser-pools.test.ts | 159 ++++++ 17 files changed, 868 insertions(+), 750 deletions(-) delete mode 100644 src/resources/agents.ts delete mode 100644 src/resources/agents/agents.ts delete mode 100644 src/resources/agents/auth.ts delete mode 100644 src/resources/agents/auth/auth.ts delete mode 100644 src/resources/agents/auth/index.ts delete mode 100644 src/resources/agents/auth/runs.ts delete mode 100644 src/resources/agents/index.ts create mode 100644 src/resources/browser-pools.ts delete mode 100644 tests/api-resources/agents/auth/auth.test.ts delete mode 100644 tests/api-resources/agents/auth/runs.test.ts create mode 100644 tests/api-resources/browser-pools.test.ts diff --git a/.stats.yml b/.stats.yml index a6b35ee5..c32f96db 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 71 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-92b20a9e4650f645d3bb23b64f4ae72287bb41d3922ff1371426a91879186362.yml -openapi_spec_hash: a3c5f41d36734c980bc5313ee60b97cf -config_hash: be146470fb2d4583b6533859f0fa48f5 +configured_endpoints: 74 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-340c8f009b71922347d4c238c8715cd752c8965abfa12cbb1ffabe35edc338a8.yml +openapi_spec_hash: efc13ab03ef89cc07333db8ab5345f31 +config_hash: a4124701ae0a474e580d7416adbcfb00 diff --git a/api.md b/api.md index b16b4351..c3c1b6e2 100644 --- a/api.md +++ b/api.md @@ -3,6 +3,9 @@ Types: - AppAction +- BrowserExtension +- BrowserProfile +- BrowserViewport - ErrorDetail - ErrorEvent - ErrorModel @@ -221,31 +224,25 @@ Methods: - client.extensions.downloadFromChromeStore({ ...params }) -> Response - client.extensions.upload({ ...params }) -> ExtensionUploadResponse -# Agents - -## Auth - -Types: - -- AgentAuthDiscoverResponse -- AgentAuthRunResponse -- AgentAuthStartResponse -- AgentAuthSubmitResponse -- DiscoveredField - -Methods: - -- client.agents.auth.start({ ...params }) -> AgentAuthStartResponse - -### Runs +# BrowserPools Types: -- RunExchangeResponse +- BrowserPool +- BrowserPoolAcquireRequest +- BrowserPoolReleaseRequest +- BrowserPoolRequest +- BrowserPoolUpdateRequest +- BrowserPoolListResponse +- BrowserPoolAcquireResponse Methods: -- client.agents.auth.runs.retrieve(runID) -> AgentAuthRunResponse -- client.agents.auth.runs.discover(runID) -> AgentAuthDiscoverResponse -- client.agents.auth.runs.exchange(runID, { ...params }) -> RunExchangeResponse -- client.agents.auth.runs.submit(runID, { ...params }) -> AgentAuthSubmitResponse +- client.browserPools.create({ ...params }) -> BrowserPool +- client.browserPools.retrieve(idOrName) -> BrowserPool +- client.browserPools.update(idOrName, { ...params }) -> BrowserPool +- client.browserPools.list() -> BrowserPoolListResponse +- client.browserPools.delete(idOrName, { ...params }) -> void +- client.browserPools.acquire(idOrName, { ...params }) -> BrowserPoolAcquireResponse +- client.browserPools.flush(idOrName) -> void +- client.browserPools.release(idOrName, { ...params }) -> void diff --git a/src/client.ts b/src/client.ts index e1689928..bf7fb3b3 100644 --- a/src/client.ts +++ b/src/client.ts @@ -19,6 +19,21 @@ import * as Uploads from './core/uploads'; import * as API from './resources/index'; import { APIPromise } from './core/api-promise'; import { AppListParams, AppListResponse, AppListResponsesOffsetPagination, Apps } from './resources/apps'; +import { + BrowserPool, + BrowserPoolAcquireParams, + BrowserPoolAcquireRequest, + BrowserPoolAcquireResponse, + BrowserPoolCreateParams, + BrowserPoolDeleteParams, + BrowserPoolListResponse, + BrowserPoolReleaseParams, + BrowserPoolReleaseRequest, + BrowserPoolRequest, + BrowserPoolUpdateParams, + BrowserPoolUpdateRequest, + BrowserPools, +} from './resources/browser-pools'; import { DeploymentCreateParams, DeploymentCreateResponse, @@ -60,7 +75,6 @@ import { ProxyListResponse, ProxyRetrieveResponse, } from './resources/proxies'; -import { Agents } from './resources/agents/agents'; import { BrowserCreateParams, BrowserCreateResponse, @@ -821,7 +835,7 @@ export class Kernel { profiles: API.Profiles = new API.Profiles(this); proxies: API.Proxies = new API.Proxies(this); extensions: API.Extensions = new API.Extensions(this); - agents: API.Agents = new API.Agents(this); + browserPools: API.BrowserPools = new API.BrowserPools(this); } Kernel.Deployments = Deployments; @@ -831,7 +845,7 @@ Kernel.Browsers = Browsers; Kernel.Profiles = Profiles; Kernel.Proxies = Proxies; Kernel.Extensions = Extensions; -Kernel.Agents = Agents; +Kernel.BrowserPools = BrowserPools; export declare namespace Kernel { export type RequestOptions = Opts.RequestOptions; @@ -913,9 +927,26 @@ export declare namespace Kernel { type ExtensionUploadParams as ExtensionUploadParams, }; - export { Agents as Agents }; + export { + BrowserPools as BrowserPools, + type BrowserPool as BrowserPool, + type BrowserPoolAcquireRequest as BrowserPoolAcquireRequest, + type BrowserPoolReleaseRequest as BrowserPoolReleaseRequest, + type BrowserPoolRequest as BrowserPoolRequest, + type BrowserPoolUpdateRequest as BrowserPoolUpdateRequest, + type BrowserPoolListResponse as BrowserPoolListResponse, + type BrowserPoolAcquireResponse as BrowserPoolAcquireResponse, + type BrowserPoolCreateParams as BrowserPoolCreateParams, + type BrowserPoolUpdateParams as BrowserPoolUpdateParams, + type BrowserPoolDeleteParams as BrowserPoolDeleteParams, + type BrowserPoolAcquireParams as BrowserPoolAcquireParams, + type BrowserPoolReleaseParams as BrowserPoolReleaseParams, + }; export type AppAction = API.AppAction; + export type BrowserExtension = API.BrowserExtension; + export type BrowserProfile = API.BrowserProfile; + export type BrowserViewport = API.BrowserViewport; export type ErrorDetail = API.ErrorDetail; export type ErrorEvent = API.ErrorEvent; export type ErrorModel = API.ErrorModel; diff --git a/src/resources/agents.ts b/src/resources/agents.ts deleted file mode 100644 index 0c43db07..00000000 --- a/src/resources/agents.ts +++ /dev/null @@ -1,3 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -export * from './agents/index'; diff --git a/src/resources/agents/agents.ts b/src/resources/agents/agents.ts deleted file mode 100644 index 67fd75b2..00000000 --- a/src/resources/agents/agents.ts +++ /dev/null @@ -1,31 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { APIResource } from '../../core/resource'; -import * as AuthAPI from './auth/auth'; -import { - AgentAuthDiscoverResponse, - AgentAuthRunResponse, - AgentAuthStartResponse, - AgentAuthSubmitResponse, - Auth, - AuthStartParams, - DiscoveredField, -} from './auth/auth'; - -export class Agents extends APIResource { - auth: AuthAPI.Auth = new AuthAPI.Auth(this._client); -} - -Agents.Auth = Auth; - -export declare namespace Agents { - export { - Auth as Auth, - type AgentAuthDiscoverResponse as AgentAuthDiscoverResponse, - type AgentAuthRunResponse as AgentAuthRunResponse, - type AgentAuthStartResponse as AgentAuthStartResponse, - type AgentAuthSubmitResponse as AgentAuthSubmitResponse, - type DiscoveredField as DiscoveredField, - type AuthStartParams as AuthStartParams, - }; -} diff --git a/src/resources/agents/auth.ts b/src/resources/agents/auth.ts deleted file mode 100644 index b64faa13..00000000 --- a/src/resources/agents/auth.ts +++ /dev/null @@ -1,3 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -export * from './auth/index'; diff --git a/src/resources/agents/auth/auth.ts b/src/resources/agents/auth/auth.ts deleted file mode 100644 index a97ee3be..00000000 --- a/src/resources/agents/auth/auth.ts +++ /dev/null @@ -1,245 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { APIResource } from '../../../core/resource'; -import * as RunsAPI from './runs'; -import { RunDiscoverParams, RunExchangeParams, RunExchangeResponse, RunSubmitParams, Runs } from './runs'; -import { APIPromise } from '../../../core/api-promise'; -import { RequestOptions } from '../../../internal/request-options'; - -export class Auth extends APIResource { - runs: RunsAPI.Runs = new RunsAPI.Runs(this._client); - - /** - * Creates a browser session and returns a handoff code for the hosted flow. Uses - * standard API key or JWT authentication (not the JWT returned by the exchange - * endpoint). - * - * @example - * ```ts - * const agentAuthStartResponse = - * await client.agents.auth.start({ - * profile_name: 'auth-abc123', - * target_domain: 'doordash.com', - * }); - * ``` - */ - start(body: AuthStartParams, options?: RequestOptions): APIPromise { - return this._client.post('/agents/auth/start', { body, ...options }); - } -} - -/** - * Response from discover endpoint matching AuthBlueprint schema - */ -export interface AgentAuthDiscoverResponse { - /** - * Whether discovery succeeded - */ - success: boolean; - - /** - * Error message if discovery failed - */ - error_message?: string; - - /** - * Discovered form fields (present when success is true) - */ - fields?: Array; - - /** - * Whether user is already logged in - */ - logged_in?: boolean; - - /** - * URL of the discovered login page - */ - login_url?: string; - - /** - * Title of the login page - */ - page_title?: string; -} - -/** - * Response from get run endpoint - */ -export interface AgentAuthRunResponse { - /** - * App name (org name at time of run creation) - */ - app_name: string; - - /** - * When the handoff code expires - */ - expires_at: string; - - /** - * Run status - */ - status: 'ACTIVE' | 'ENDED' | 'EXPIRED' | 'CANCELED'; - - /** - * Target domain for authentication - */ - target_domain: string; -} - -/** - * Response from starting an agent authentication run - */ -export interface AgentAuthStartResponse { - /** - * When the handoff code expires - */ - expires_at: string; - - /** - * One-time code for handoff - */ - handoff_code: string; - - /** - * URL to redirect user to - */ - hosted_url: string; - - /** - * Unique identifier for the run - */ - run_id: string; -} - -/** - * Response from submit endpoint matching SubmitResult schema - */ -export interface AgentAuthSubmitResponse { - /** - * Whether submission succeeded - */ - success: boolean; - - /** - * Additional fields needed (e.g., OTP) - present when needs_additional_auth is - * true - */ - additional_fields?: Array; - - /** - * App name (only present when logged_in is true) - */ - app_name?: string; - - /** - * Error message if submission failed - */ - error_message?: string; - - /** - * Whether user is now logged in - */ - logged_in?: boolean; - - /** - * Whether additional authentication fields are needed - */ - needs_additional_auth?: boolean; - - /** - * Target domain (only present when logged_in is true) - */ - target_domain?: string; -} - -/** - * A discovered form field - */ -export interface DiscoveredField { - /** - * Field label - */ - label: string; - - /** - * Field name - */ - name: string; - - /** - * CSS selector for the field - */ - selector: string; - - /** - * Field type - */ - type: 'text' | 'email' | 'password' | 'tel' | 'number' | 'url' | 'code' | 'checkbox'; - - /** - * Field placeholder - */ - placeholder?: string; - - /** - * Whether field is required - */ - required?: boolean; -} - -export interface AuthStartParams { - /** - * Name of the profile to use for this flow - */ - profile_name: string; - - /** - * Target domain for authentication - */ - target_domain: string; - - /** - * Optional logo URL for the application - */ - app_logo_url?: string; - - /** - * Optional proxy configuration - */ - proxy?: AuthStartParams.Proxy; -} - -export namespace AuthStartParams { - /** - * Optional proxy configuration - */ - export interface Proxy { - /** - * ID of the proxy to use - */ - proxy_id?: string; - } -} - -Auth.Runs = Runs; - -export declare namespace Auth { - export { - type AgentAuthDiscoverResponse as AgentAuthDiscoverResponse, - type AgentAuthRunResponse as AgentAuthRunResponse, - type AgentAuthStartResponse as AgentAuthStartResponse, - type AgentAuthSubmitResponse as AgentAuthSubmitResponse, - type DiscoveredField as DiscoveredField, - type AuthStartParams as AuthStartParams, - }; - - export { - Runs as Runs, - type RunExchangeResponse as RunExchangeResponse, - type RunDiscoverParams as RunDiscoverParams, - type RunExchangeParams as RunExchangeParams, - type RunSubmitParams as RunSubmitParams, - }; -} diff --git a/src/resources/agents/auth/index.ts b/src/resources/agents/auth/index.ts deleted file mode 100644 index 904c0ce0..00000000 --- a/src/resources/agents/auth/index.ts +++ /dev/null @@ -1,18 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -export { - Auth, - type AgentAuthDiscoverResponse, - type AgentAuthRunResponse, - type AgentAuthStartResponse, - type AgentAuthSubmitResponse, - type DiscoveredField, - type AuthStartParams, -} from './auth'; -export { - Runs, - type RunExchangeResponse, - type RunDiscoverParams, - type RunExchangeParams, - type RunSubmitParams, -} from './runs'; diff --git a/src/resources/agents/auth/runs.ts b/src/resources/agents/auth/runs.ts deleted file mode 100644 index 7b9e2e46..00000000 --- a/src/resources/agents/auth/runs.ts +++ /dev/null @@ -1,125 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { APIResource } from '../../../core/resource'; -import * as AuthAPI from './auth'; -import { APIPromise } from '../../../core/api-promise'; -import { RequestOptions } from '../../../internal/request-options'; -import { path } from '../../../internal/utils/path'; - -export class Runs extends APIResource { - /** - * Returns run details including app_name and target_domain. Uses the JWT returned - * by the exchange endpoint, or standard API key or JWT authentication. - * - * @example - * ```ts - * const agentAuthRunResponse = - * await client.agents.auth.runs.retrieve('run_id'); - * ``` - */ - retrieve(runID: string, options?: RequestOptions): APIPromise { - return this._client.get(path`/agents/auth/runs/${runID}`, options); - } - - /** - * Inspects the target site to detect logged-in state or discover required fields. - * Returns 200 with success: true when fields are found, or 4xx/5xx for failures. - * Requires the JWT returned by the exchange endpoint. - * - * @example - * ```ts - * const agentAuthDiscoverResponse = - * await client.agents.auth.runs.discover('run_id'); - * ``` - */ - discover( - runID: string, - body?: RunDiscoverParams | null | undefined, - options?: RequestOptions, - ): APIPromise { - return this._client.post(path`/agents/auth/runs/${runID}/discover`, { body, ...options }); - } - - /** - * Validates the handoff code and returns a JWT token for subsequent requests. No - * authentication required (the handoff code serves as the credential). - * - * @example - * ```ts - * const response = await client.agents.auth.runs.exchange( - * 'run_id', - * { code: 'otp_abc123xyz' }, - * ); - * ``` - */ - exchange( - runID: string, - body: RunExchangeParams, - options?: RequestOptions, - ): APIPromise { - return this._client.post(path`/agents/auth/runs/${runID}/exchange`, { body, ...options }); - } - - /** - * Submits field values for the discovered login form and may return additional - * auth fields or success. Requires the JWT returned by the exchange endpoint. - * - * @example - * ```ts - * const agentAuthSubmitResponse = - * await client.agents.auth.runs.submit('run_id', { - * field_values: { - * email: 'user@example.com', - * password: '********', - * }, - * }); - * ``` - */ - submit( - runID: string, - body: RunSubmitParams, - options?: RequestOptions, - ): APIPromise { - return this._client.post(path`/agents/auth/runs/${runID}/submit`, { body, ...options }); - } -} - -/** - * Response from exchange endpoint - */ -export interface RunExchangeResponse { - /** - * JWT token with run_id claim (30 minute TTL) - */ - jwt: string; - - /** - * Run ID - */ - run_id: string; -} - -export interface RunDiscoverParams {} - -export interface RunExchangeParams { - /** - * Handoff code from start endpoint - */ - code: string; -} - -export interface RunSubmitParams { - /** - * Values for the discovered login fields - */ - field_values: { [key: string]: string }; -} - -export declare namespace Runs { - export { - type RunExchangeResponse as RunExchangeResponse, - type RunDiscoverParams as RunDiscoverParams, - type RunExchangeParams as RunExchangeParams, - type RunSubmitParams as RunSubmitParams, - }; -} diff --git a/src/resources/agents/index.ts b/src/resources/agents/index.ts deleted file mode 100644 index c5647b79..00000000 --- a/src/resources/agents/index.ts +++ /dev/null @@ -1,12 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -export { Agents } from './agents'; -export { - Auth, - type AgentAuthDiscoverResponse, - type AgentAuthRunResponse, - type AgentAuthStartResponse, - type AgentAuthSubmitResponse, - type DiscoveredField, - type AuthStartParams, -} from './auth/index'; diff --git a/src/resources/browser-pools.ts b/src/resources/browser-pools.ts new file mode 100644 index 00000000..be28ad06 --- /dev/null +++ b/src/resources/browser-pools.ts @@ -0,0 +1,560 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../core/resource'; +import * as Shared from './shared'; +import * as BrowsersAPI from './browsers/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 BrowserPools extends APIResource { + /** + * Create a new browser pool with the specified configuration and size. + * + * @example + * ```ts + * const browserPool = await client.browserPools.create({ + * size: 10, + * }); + * ``` + */ + create(body: BrowserPoolCreateParams, options?: RequestOptions): APIPromise { + return this._client.post('/browser_pools', { body, ...options }); + } + + /** + * Retrieve details for a single browser pool by its ID or name. + * + * @example + * ```ts + * const browserPool = await client.browserPools.retrieve( + * 'id_or_name', + * ); + * ``` + */ + retrieve(idOrName: string, options?: RequestOptions): APIPromise { + return this._client.get(path`/browser_pools/${idOrName}`, options); + } + + /** + * Updates the configuration used to create browsers in the pool. + * + * @example + * ```ts + * const browserPool = await client.browserPools.update( + * 'id_or_name', + * { size: 10 }, + * ); + * ``` + */ + update(idOrName: string, body: BrowserPoolUpdateParams, options?: RequestOptions): APIPromise { + return this._client.patch(path`/browser_pools/${idOrName}`, { body, ...options }); + } + + /** + * List browser pools owned by the caller's organization. + * + * @example + * ```ts + * const browserPools = await client.browserPools.list(); + * ``` + */ + list(options?: RequestOptions): APIPromise { + return this._client.get('/browser_pools', options); + } + + /** + * Delete a browser pool and all browsers in it. By default, deletion is blocked if + * browsers are currently leased. Use force=true to terminate leased browsers. + * + * @example + * ```ts + * await client.browserPools.delete('id_or_name'); + * ``` + */ + delete( + idOrName: string, + body: BrowserPoolDeleteParams | null | undefined = {}, + options?: RequestOptions, + ): APIPromise { + return this._client.delete(path`/browser_pools/${idOrName}`, { + body, + ...options, + headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), + }); + } + + /** + * Long-polling endpoint to acquire a browser from the pool. Returns immediately + * when a browser is available, or returns 204 No Content when the poll times out. + * The client should retry the request to continue waiting for a browser. The + * acquired browser will use the pool's timeout_seconds for its idle timeout. + * + * @example + * ```ts + * const response = await client.browserPools.acquire( + * 'id_or_name', + * ); + * ``` + */ + acquire( + idOrName: string, + body: BrowserPoolAcquireParams, + options?: RequestOptions, + ): APIPromise { + return this._client.post(path`/browser_pools/${idOrName}/acquire`, { body, ...options }); + } + + /** + * Destroys all idle browsers in the pool; leased browsers are not affected. + * + * @example + * ```ts + * await client.browserPools.flush('id_or_name'); + * ``` + */ + flush(idOrName: string, options?: RequestOptions): APIPromise { + return this._client.post(path`/browser_pools/${idOrName}/flush`, { + ...options, + headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), + }); + } + + /** + * Release a browser back to the pool, optionally recreating the browser instance. + * + * @example + * ```ts + * await client.browserPools.release('id_or_name', { + * session_id: 'ts8iy3sg25ibheguyni2lg9t', + * }); + * ``` + */ + release(idOrName: string, body: BrowserPoolReleaseParams, options?: RequestOptions): APIPromise { + return this._client.post(path`/browser_pools/${idOrName}/release`, { + body, + ...options, + headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), + }); + } +} + +/** + * A browser pool containing multiple identically configured browsers. + */ +export interface BrowserPool { + /** + * Unique identifier for the browser pool + */ + id: string; + + /** + * Number of browsers currently acquired from the pool + */ + acquired_count: number; + + /** + * Number of browsers currently available in the pool + */ + available_count: number; + + /** + * Configuration used to create all browsers in this pool + */ + browser_pool_config: BrowserPoolRequest; + + /** + * Timestamp when the browser pool was created + */ + created_at: string; + + /** + * Browser pool name, if set + */ + name?: string; +} + +/** + * Request body for acquiring a browser from the pool. + */ +export interface BrowserPoolAcquireRequest { + /** + * Maximum number of seconds to wait for a browser to be available. Defaults to the + * calculated time it would take to fill the pool at the currently configured fill + * rate. + */ + acquire_timeout_seconds?: number; +} + +/** + * Request body for releasing a browser back to the pool. + */ +export interface BrowserPoolReleaseRequest { + /** + * Browser session ID to release back to the pool + */ + session_id: string; + + /** + * Whether to reuse the browser instance or destroy it and create a new one. + * Defaults to true. + */ + reuse?: boolean; +} + +/** + * Parameters for creating a browser pool. All browsers in the pool will be created + * with the same configuration. + */ +export interface BrowserPoolRequest { + /** + * Number of browsers to create in the pool + */ + size: number; + + /** + * List of browser extensions to load into the session. Provide each by id or name. + */ + extensions?: Array; + + /** + * Percentage of the pool to fill per minute. Defaults to 10%. + */ + fill_rate_per_minute?: number; + + /** + * If true, launches the browser using a headless image. Defaults to false. + */ + headless?: boolean; + + /** + * If true, launches the browser in kiosk mode to hide address bar and tabs in live + * view. + */ + kiosk_mode?: boolean; + + /** + * Optional name for the browser pool. Must be unique within the organization. + */ + name?: string; + + /** + * Profile selection for the browser session. Provide either id or name. If + * specified, the matching profile will be loaded into the browser session. + * Profiles must be created beforehand. + */ + profile?: Shared.BrowserProfile; + + /** + * Optional proxy to associate to the browser session. Must reference a proxy + * belonging to the caller's org. + */ + proxy_id?: string; + + /** + * If true, launches the browser in stealth mode to reduce detection by anti-bot + * mechanisms. + */ + stealth?: boolean; + + /** + * Default idle timeout in seconds for browsers acquired from this pool before they + * are destroyed. Defaults to 600 seconds if not specified + */ + timeout_seconds?: number; + + /** + * Initial browser window size in pixels with optional refresh rate. If omitted, + * image defaults apply (commonly 1024x768@60). Only specific viewport + * configurations are supported. The server will reject unsupported combinations. + * Supported resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25, + * 1440x900@25, 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will + * be automatically determined from the width and height if they match a supported + * configuration exactly. Note: Higher resolutions may affect the responsiveness of + * live view browser + */ + viewport?: Shared.BrowserViewport; +} + +/** + * Parameters for updating a browser pool. All browsers in the pool will be created + * with the same configuration. + */ +export interface BrowserPoolUpdateRequest extends BrowserPoolRequest { + /** + * Whether to discard all idle browsers and rebuild the pool immediately. Defaults + * to true. + */ + discard_all_idle?: boolean; +} + +export type BrowserPoolListResponse = Array; + +export interface BrowserPoolAcquireResponse { + /** + * Websocket URL for Chrome DevTools Protocol connections to the browser session + */ + cdp_ws_url: string; + + /** + * When the browser session was created. + */ + created_at: string; + + /** + * Whether the browser session is running in headless mode. + */ + headless: boolean; + + /** + * Unique identifier for the browser session + */ + session_id: string; + + /** + * Whether the browser session is running in stealth mode. + */ + stealth: boolean; + + /** + * The number of seconds of inactivity before the browser session is terminated. + */ + timeout_seconds: number; + + /** + * Remote URL for live viewing the browser session. Only available for non-headless + * browsers. + */ + browser_live_view_url?: string; + + /** + * When the browser session was soft-deleted. Only present for deleted sessions. + */ + deleted_at?: string; + + /** + * Whether the browser session is running in kiosk mode. + */ + kiosk_mode?: boolean; + + /** + * Optional persistence configuration for the browser session. + */ + persistence?: BrowsersAPI.BrowserPersistence; + + /** + * Browser profile metadata. + */ + profile?: BrowsersAPI.Profile; + + /** + * ID of the proxy associated with this browser session, if any. + */ + proxy_id?: string; + + /** + * Initial browser window size in pixels with optional refresh rate. If omitted, + * image defaults apply (commonly 1024x768@60). Only specific viewport + * configurations are supported. The server will reject unsupported combinations. + * Supported resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25, + * 1440x900@25, 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will + * be automatically determined from the width and height if they match a supported + * configuration exactly. Note: Higher resolutions may affect the responsiveness of + * live view browser + */ + viewport?: Shared.BrowserViewport; +} + +export interface BrowserPoolCreateParams { + /** + * Number of browsers to create in the pool + */ + size: number; + + /** + * List of browser extensions to load into the session. Provide each by id or name. + */ + extensions?: Array; + + /** + * Percentage of the pool to fill per minute. Defaults to 10%. + */ + fill_rate_per_minute?: number; + + /** + * If true, launches the browser using a headless image. Defaults to false. + */ + headless?: boolean; + + /** + * If true, launches the browser in kiosk mode to hide address bar and tabs in live + * view. + */ + kiosk_mode?: boolean; + + /** + * Optional name for the browser pool. Must be unique within the organization. + */ + name?: string; + + /** + * Profile selection for the browser session. Provide either id or name. If + * specified, the matching profile will be loaded into the browser session. + * Profiles must be created beforehand. + */ + profile?: Shared.BrowserProfile; + + /** + * Optional proxy to associate to the browser session. Must reference a proxy + * belonging to the caller's org. + */ + proxy_id?: string; + + /** + * If true, launches the browser in stealth mode to reduce detection by anti-bot + * mechanisms. + */ + stealth?: boolean; + + /** + * Default idle timeout in seconds for browsers acquired from this pool before they + * are destroyed. Defaults to 600 seconds if not specified + */ + timeout_seconds?: number; + + /** + * Initial browser window size in pixels with optional refresh rate. If omitted, + * image defaults apply (commonly 1024x768@60). Only specific viewport + * configurations are supported. The server will reject unsupported combinations. + * Supported resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25, + * 1440x900@25, 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will + * be automatically determined from the width and height if they match a supported + * configuration exactly. Note: Higher resolutions may affect the responsiveness of + * live view browser + */ + viewport?: Shared.BrowserViewport; +} + +export interface BrowserPoolUpdateParams { + /** + * Number of browsers to create in the pool + */ + size: number; + + /** + * Whether to discard all idle browsers and rebuild the pool immediately. Defaults + * to true. + */ + discard_all_idle?: boolean; + + /** + * List of browser extensions to load into the session. Provide each by id or name. + */ + extensions?: Array; + + /** + * Percentage of the pool to fill per minute. Defaults to 10%. + */ + fill_rate_per_minute?: number; + + /** + * If true, launches the browser using a headless image. Defaults to false. + */ + headless?: boolean; + + /** + * If true, launches the browser in kiosk mode to hide address bar and tabs in live + * view. + */ + kiosk_mode?: boolean; + + /** + * Optional name for the browser pool. Must be unique within the organization. + */ + name?: string; + + /** + * Profile selection for the browser session. Provide either id or name. If + * specified, the matching profile will be loaded into the browser session. + * Profiles must be created beforehand. + */ + profile?: Shared.BrowserProfile; + + /** + * Optional proxy to associate to the browser session. Must reference a proxy + * belonging to the caller's org. + */ + proxy_id?: string; + + /** + * If true, launches the browser in stealth mode to reduce detection by anti-bot + * mechanisms. + */ + stealth?: boolean; + + /** + * Default idle timeout in seconds for browsers acquired from this pool before they + * are destroyed. Defaults to 600 seconds if not specified + */ + timeout_seconds?: number; + + /** + * Initial browser window size in pixels with optional refresh rate. If omitted, + * image defaults apply (commonly 1024x768@60). Only specific viewport + * configurations are supported. The server will reject unsupported combinations. + * Supported resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25, + * 1440x900@25, 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will + * be automatically determined from the width and height if they match a supported + * configuration exactly. Note: Higher resolutions may affect the responsiveness of + * live view browser + */ + viewport?: Shared.BrowserViewport; +} + +export interface BrowserPoolDeleteParams { + /** + * If true, force delete even if browsers are currently leased. Leased browsers + * will be terminated. + */ + force?: boolean; +} + +export interface BrowserPoolAcquireParams { + /** + * Maximum number of seconds to wait for a browser to be available. Defaults to the + * calculated time it would take to fill the pool at the currently configured fill + * rate. + */ + acquire_timeout_seconds?: number; +} + +export interface BrowserPoolReleaseParams { + /** + * Browser session ID to release back to the pool + */ + session_id: string; + + /** + * Whether to reuse the browser instance or destroy it and create a new one. + * Defaults to true. + */ + reuse?: boolean; +} + +export declare namespace BrowserPools { + export { + type BrowserPool as BrowserPool, + type BrowserPoolAcquireRequest as BrowserPoolAcquireRequest, + type BrowserPoolReleaseRequest as BrowserPoolReleaseRequest, + type BrowserPoolRequest as BrowserPoolRequest, + type BrowserPoolUpdateRequest as BrowserPoolUpdateRequest, + type BrowserPoolListResponse as BrowserPoolListResponse, + type BrowserPoolAcquireResponse as BrowserPoolAcquireResponse, + type BrowserPoolCreateParams as BrowserPoolCreateParams, + type BrowserPoolUpdateParams as BrowserPoolUpdateParams, + type BrowserPoolDeleteParams as BrowserPoolDeleteParams, + type BrowserPoolAcquireParams as BrowserPoolAcquireParams, + type BrowserPoolReleaseParams as BrowserPoolReleaseParams, + }; +} diff --git a/src/resources/browsers/browsers.ts b/src/resources/browsers/browsers.ts index 1c0f9bca..d3f8b3d1 100644 --- a/src/resources/browsers/browsers.ts +++ b/src/resources/browsers/browsers.ts @@ -1,6 +1,7 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. import { APIResource } from '../../core/resource'; +import * as Shared from '../shared'; import * as ComputerAPI from './computer'; import { Computer, @@ -302,37 +303,7 @@ export interface BrowserCreateResponse { * configuration exactly. Note: Higher resolutions may affect the responsiveness of * live view browser */ - viewport?: BrowserCreateResponse.Viewport; -} - -export namespace BrowserCreateResponse { - /** - * Initial browser window size in pixels with optional refresh rate. If omitted, - * image defaults apply (commonly 1024x768@60). Only specific viewport - * configurations are supported. The server will reject unsupported combinations. - * Supported resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25, - * 1440x900@25, 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will - * be automatically determined from the width and height if they match a supported - * configuration exactly. Note: Higher resolutions may affect the responsiveness of - * live view browser - */ - export interface Viewport { - /** - * Browser window height in pixels. - */ - height: number; - - /** - * Browser window width in pixels. - */ - width: number; - - /** - * Display refresh rate in Hz. If omitted, automatically determined from width and - * height. - */ - refresh_rate?: number; - } + viewport?: Shared.BrowserViewport; } export interface BrowserRetrieveResponse { @@ -407,37 +378,7 @@ export interface BrowserRetrieveResponse { * configuration exactly. Note: Higher resolutions may affect the responsiveness of * live view browser */ - viewport?: BrowserRetrieveResponse.Viewport; -} - -export namespace BrowserRetrieveResponse { - /** - * Initial browser window size in pixels with optional refresh rate. If omitted, - * image defaults apply (commonly 1024x768@60). Only specific viewport - * configurations are supported. The server will reject unsupported combinations. - * Supported resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25, - * 1440x900@25, 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will - * be automatically determined from the width and height if they match a supported - * configuration exactly. Note: Higher resolutions may affect the responsiveness of - * live view browser - */ - export interface Viewport { - /** - * Browser window height in pixels. - */ - height: number; - - /** - * Browser window width in pixels. - */ - width: number; - - /** - * Display refresh rate in Hz. If omitted, automatically determined from width and - * height. - */ - refresh_rate?: number; - } + viewport?: Shared.BrowserViewport; } export interface BrowserListResponse { @@ -512,44 +453,14 @@ export interface BrowserListResponse { * configuration exactly. Note: Higher resolutions may affect the responsiveness of * live view browser */ - viewport?: BrowserListResponse.Viewport; -} - -export namespace BrowserListResponse { - /** - * Initial browser window size in pixels with optional refresh rate. If omitted, - * image defaults apply (commonly 1024x768@60). Only specific viewport - * configurations are supported. The server will reject unsupported combinations. - * Supported resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25, - * 1440x900@25, 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will - * be automatically determined from the width and height if they match a supported - * configuration exactly. Note: Higher resolutions may affect the responsiveness of - * live view browser - */ - export interface Viewport { - /** - * Browser window height in pixels. - */ - height: number; - - /** - * Browser window width in pixels. - */ - width: number; - - /** - * Display refresh rate in Hz. If omitted, automatically determined from width and - * height. - */ - refresh_rate?: number; - } + viewport?: Shared.BrowserViewport; } export interface BrowserCreateParams { /** * List of browser extensions to load into the session. Provide each by id or name. */ - extensions?: Array; + extensions?: Array; /** * If true, launches the browser using a headless image (no VNC/GUI). Defaults to @@ -578,7 +489,7 @@ export interface BrowserCreateParams { * specified, the matching profile will be loaded into the browser session. * Profiles must be created beforehand. */ - profile?: BrowserCreateParams.Profile; + profile?: Shared.BrowserProfile; /** * Optional proxy to associate to the browser session. Must reference a proxy @@ -612,78 +523,7 @@ export interface BrowserCreateParams { * configuration exactly. Note: Higher resolutions may affect the responsiveness of * live view browser */ - viewport?: BrowserCreateParams.Viewport; -} - -export namespace BrowserCreateParams { - /** - * Extension selection for the browser session. Provide either id or name of an - * extension uploaded to Kernel. - */ - export interface Extension { - /** - * Extension ID to load for this browser session - */ - id?: string; - - /** - * Extension name to load for this browser session (instead of id). Must be 1-255 - * characters, using letters, numbers, dots, underscores, or hyphens. - */ - name?: string; - } - - /** - * Profile selection for the browser session. Provide either id or name. If - * specified, the matching profile will be loaded into the browser session. - * Profiles must be created beforehand. - */ - export interface Profile { - /** - * Profile ID to load for this browser session - */ - id?: string; - - /** - * Profile name to load for this browser session (instead of id). Must be 1-255 - * characters, using letters, numbers, dots, underscores, or hyphens. - */ - name?: string; - - /** - * If true, save changes made during the session back to the profile when the - * session ends. - */ - save_changes?: boolean; - } - - /** - * Initial browser window size in pixels with optional refresh rate. If omitted, - * image defaults apply (commonly 1024x768@60). Only specific viewport - * configurations are supported. The server will reject unsupported combinations. - * Supported resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25, - * 1440x900@25, 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will - * be automatically determined from the width and height if they match a supported - * configuration exactly. Note: Higher resolutions may affect the responsiveness of - * live view browser - */ - export interface Viewport { - /** - * Browser window height in pixels. - */ - height: number; - - /** - * Browser window width in pixels. - */ - width: number; - - /** - * Display refresh rate in Hz. If omitted, automatically determined from width and - * height. - */ - refresh_rate?: number; - } + viewport?: Shared.BrowserViewport; } export interface BrowserListParams extends OffsetPaginationParams { diff --git a/src/resources/index.ts b/src/resources/index.ts index 3e3fce48..420e5e28 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -1,13 +1,27 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. export * from './shared'; -export { Agents } from './agents/agents'; export { Apps, type AppListResponse, type AppListParams, type AppListResponsesOffsetPagination, } from './apps'; +export { + BrowserPools, + type BrowserPool, + type BrowserPoolAcquireRequest, + type BrowserPoolReleaseRequest, + type BrowserPoolRequest, + type BrowserPoolUpdateRequest, + type BrowserPoolListResponse, + type BrowserPoolAcquireResponse, + type BrowserPoolCreateParams, + type BrowserPoolUpdateParams, + type BrowserPoolDeleteParams, + type BrowserPoolAcquireParams, + type BrowserPoolReleaseParams, +} from './browser-pools'; export { Browsers, type BrowserPersistence, diff --git a/src/resources/shared.ts b/src/resources/shared.ts index c44734e2..13cbc0b9 100644 --- a/src/resources/shared.ts +++ b/src/resources/shared.ts @@ -10,6 +10,75 @@ export interface AppAction { name: string; } +/** + * Extension selection for the browser session. Provide either id or name of an + * extension uploaded to Kernel. + */ +export interface BrowserExtension { + /** + * Extension ID to load for this browser session + */ + id?: string; + + /** + * Extension name to load for this browser session (instead of id). Must be 1-255 + * characters, using letters, numbers, dots, underscores, or hyphens. + */ + name?: string; +} + +/** + * Profile selection for the browser session. Provide either id or name. If + * specified, the matching profile will be loaded into the browser session. + * Profiles must be created beforehand. + */ +export interface BrowserProfile { + /** + * Profile ID to load for this browser session + */ + id?: string; + + /** + * Profile name to load for this browser session (instead of id). Must be 1-255 + * characters, using letters, numbers, dots, underscores, or hyphens. + */ + name?: string; + + /** + * If true, save changes made during the session back to the profile when the + * session ends. + */ + save_changes?: boolean; +} + +/** + * Initial browser window size in pixels with optional refresh rate. If omitted, + * image defaults apply (commonly 1024x768@60). Only specific viewport + * configurations are supported. The server will reject unsupported combinations. + * Supported resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25, + * 1440x900@25, 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will + * be automatically determined from the width and height if they match a supported + * configuration exactly. Note: Higher resolutions may affect the responsiveness of + * live view browser + */ +export interface BrowserViewport { + /** + * Browser window height in pixels. + */ + height: number; + + /** + * Browser window width in pixels. + */ + width: number; + + /** + * Display refresh rate in Hz. If omitted, automatically determined from width and + * height. + */ + refresh_rate?: number; +} + export interface ErrorDetail { /** * Lower-level error code providing more specific detail diff --git a/tests/api-resources/agents/auth/auth.test.ts b/tests/api-resources/agents/auth/auth.test.ts deleted file mode 100644 index 8d0224cf..00000000 --- a/tests/api-resources/agents/auth/auth.test.ts +++ /dev/null @@ -1,35 +0,0 @@ -// 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 auth', () => { - // Prism tests are disabled - test.skip('start: only required params', async () => { - const responsePromise = client.agents.auth.start({ - profile_name: 'auth-abc123', - target_domain: 'doordash.com', - }); - 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); - }); - - // Prism tests are disabled - test.skip('start: required and optional params', async () => { - const response = await client.agents.auth.start({ - profile_name: 'auth-abc123', - target_domain: 'doordash.com', - app_logo_url: 'https://example.com/logo.png', - proxy: { proxy_id: 'proxy_id' }, - }); - }); -}); diff --git a/tests/api-resources/agents/auth/runs.test.ts b/tests/api-resources/agents/auth/runs.test.ts deleted file mode 100644 index c3e8b4bd..00000000 --- a/tests/api-resources/agents/auth/runs.test.ts +++ /dev/null @@ -1,80 +0,0 @@ -// 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 runs', () => { - // Prism tests are disabled - test.skip('retrieve', async () => { - const responsePromise = client.agents.auth.runs.retrieve('run_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); - }); - - // Prism tests are disabled - test.skip('discover', async () => { - const responsePromise = client.agents.auth.runs.discover('run_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); - }); - - // Prism tests are disabled - test.skip('discover: 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.agents.auth.runs.discover('run_id', {}, { path: '/_stainless_unknown_path' }), - ).rejects.toThrow(Kernel.NotFoundError); - }); - - // Prism tests are disabled - test.skip('exchange: only required params', async () => { - const responsePromise = client.agents.auth.runs.exchange('run_id', { code: 'otp_abc123xyz' }); - 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); - }); - - // Prism tests are disabled - test.skip('exchange: required and optional params', async () => { - const response = await client.agents.auth.runs.exchange('run_id', { code: 'otp_abc123xyz' }); - }); - - // Prism tests are disabled - test.skip('submit: only required params', async () => { - const responsePromise = client.agents.auth.runs.submit('run_id', { - field_values: { email: 'user@example.com', password: '********' }, - }); - 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); - }); - - // Prism tests are disabled - test.skip('submit: required and optional params', async () => { - const response = await client.agents.auth.runs.submit('run_id', { - field_values: { email: 'user@example.com', password: '********' }, - }); - }); -}); diff --git a/tests/api-resources/browser-pools.test.ts b/tests/api-resources/browser-pools.test.ts new file mode 100644 index 00000000..2fdc93e3 --- /dev/null +++ b/tests/api-resources/browser-pools.test.ts @@ -0,0 +1,159 @@ +// 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 browserPools', () => { + // Prism tests are disabled + test.skip('create: only required params', async () => { + const responsePromise = client.browserPools.create({ size: 10 }); + 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); + }); + + // Prism tests are disabled + test.skip('create: required and optional params', async () => { + const response = await client.browserPools.create({ + size: 10, + extensions: [{ id: 'id', name: 'name' }], + fill_rate_per_minute: 0, + headless: false, + kiosk_mode: true, + name: 'my-pool', + profile: { id: 'id', name: 'name', save_changes: true }, + proxy_id: 'proxy_id', + stealth: true, + timeout_seconds: 60, + viewport: { height: 800, width: 1280, refresh_rate: 60 }, + }); + }); + + // Prism tests are disabled + test.skip('retrieve', async () => { + const responsePromise = client.browserPools.retrieve('id_or_name'); + 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); + }); + + // Prism tests are disabled + test.skip('update: only required params', async () => { + const responsePromise = client.browserPools.update('id_or_name', { size: 10 }); + 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); + }); + + // Prism tests are disabled + test.skip('update: required and optional params', async () => { + const response = await client.browserPools.update('id_or_name', { + size: 10, + discard_all_idle: false, + extensions: [{ id: 'id', name: 'name' }], + fill_rate_per_minute: 0, + headless: false, + kiosk_mode: true, + name: 'my-pool', + profile: { id: 'id', name: 'name', save_changes: true }, + proxy_id: 'proxy_id', + stealth: true, + timeout_seconds: 60, + viewport: { height: 800, width: 1280, refresh_rate: 60 }, + }); + }); + + // Prism tests are disabled + test.skip('list', async () => { + const responsePromise = client.browserPools.list(); + 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); + }); + + // Prism tests are disabled + test.skip('delete', async () => { + const responsePromise = client.browserPools.delete('id_or_name'); + 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); + }); + + // Prism tests are disabled + test.skip('delete: 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.browserPools.delete('id_or_name', { force: true }, { path: '/_stainless_unknown_path' }), + ).rejects.toThrow(Kernel.NotFoundError); + }); + + // Prism tests are disabled + test.skip('acquire', async () => { + const responsePromise = client.browserPools.acquire('id_or_name', {}); + 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); + }); + + // Prism tests are disabled + test.skip('flush', async () => { + const responsePromise = client.browserPools.flush('id_or_name'); + 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); + }); + + // Prism tests are disabled + test.skip('release: only required params', async () => { + const responsePromise = client.browserPools.release('id_or_name', { + session_id: 'ts8iy3sg25ibheguyni2lg9t', + }); + 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); + }); + + // Prism tests are disabled + test.skip('release: required and optional params', async () => { + const response = await client.browserPools.release('id_or_name', { + session_id: 'ts8iy3sg25ibheguyni2lg9t', + reuse: false, + }); + }); +}); From 6ebd7eb34c2063590d6cedcfae7feeb6ef028b70 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 2 Dec 2025 22:14:15 +0000 Subject: [PATCH 217/551] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index c32f96db..25e77f1e 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 74 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-340c8f009b71922347d4c238c8715cd752c8965abfa12cbb1ffabe35edc338a8.yml -openapi_spec_hash: efc13ab03ef89cc07333db8ab5345f31 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-3db06d1628149b5ea8303f1c72250664dfd7cb4a14ceb6102f1ae6e85c92c038.yml +openapi_spec_hash: e5b3da2da328eb26d2a70e2521744c62 config_hash: a4124701ae0a474e580d7416adbcfb00 From f791440b05bceb622db1ab9964a51578f6b53af5 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 2 Dec 2025 22:16:18 +0000 Subject: [PATCH 218/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 71e95baf..d3535156 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.20.0" + ".": "0.21.0" } diff --git a/package.json b/package.json index 6fa7c739..9ff823b4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.20.0", + "version": "0.21.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index b4e51da6..bc954354 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.20.0'; // x-release-please-version +export const VERSION = '0.21.0'; // x-release-please-version From da12d31a08d9d3f92a89c4b44d6ca8e9e41e9bf0 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 3 Dec 2025 04:04:15 +0000 Subject: [PATCH 219/551] chore(internal): upgrade eslint --- package.json | 2 +- yarn.lock | 150 ++++++++++++++++++++++++++++++--------------------- 2 files changed, 89 insertions(+), 63 deletions(-) diff --git a/package.json b/package.json index 9ff823b4..7ba9dac6 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,7 @@ "@types/node": "^20.17.6", "@typescript-eslint/eslint-plugin": "8.31.1", "@typescript-eslint/parser": "8.31.1", - "eslint": "^9.20.1", + "eslint": "^9.39.1", "eslint-plugin-prettier": "^5.4.1", "eslint-plugin-unused-imports": "^4.1.4", "iconv-lite": "^0.6.3", diff --git a/yarn.lock b/yarn.lock index 8311caf5..5f56a201 100644 --- a/yarn.lock +++ b/yarn.lock @@ -350,45 +350,52 @@ dependencies: "@cspotcode/source-map-consumer" "0.8.0" -"@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0": +"@eslint-community/eslint-utils@^4.4.0": version "4.4.0" resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" integrity sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA== dependencies: eslint-visitor-keys "^3.3.0" +"@eslint-community/eslint-utils@^4.8.0": + version "4.9.0" + resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz#7308df158e064f0dd8b8fdb58aa14fa2a7f913b3" + integrity sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g== + dependencies: + eslint-visitor-keys "^3.4.3" + "@eslint-community/regexpp@^4.10.0", "@eslint-community/regexpp@^4.12.1": version "4.12.1" resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.12.1.tgz#cfc6cffe39df390a3841cde2abccf92eaa7ae0e0" integrity sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ== -"@eslint/config-array@^0.19.0": - version "0.19.2" - resolved "https://registry.yarnpkg.com/@eslint/config-array/-/config-array-0.19.2.tgz#3060b809e111abfc97adb0bb1172778b90cb46aa" - integrity sha512-GNKqxfHG2ySmJOBSHg7LxeUx4xpuCoFjacmlCoYWEbaPXLwvfIjixRI12xCQZeULksQb23uiA8F40w5TojpV7w== +"@eslint/config-array@^0.21.1": + version "0.21.1" + resolved "https://registry.yarnpkg.com/@eslint/config-array/-/config-array-0.21.1.tgz#7d1b0060fea407f8301e932492ba8c18aff29713" + integrity sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA== dependencies: - "@eslint/object-schema" "^2.1.6" + "@eslint/object-schema" "^2.1.7" debug "^4.3.1" minimatch "^3.1.2" -"@eslint/core@^0.10.0": - version "0.10.0" - resolved "https://registry.yarnpkg.com/@eslint/core/-/core-0.10.0.tgz#23727063c21b335f752dbb3a16450f6f9cbc9091" - integrity sha512-gFHJ+xBOo4G3WRlR1e/3G8A6/KZAH6zcE/hkLRCZTi/B9avAG365QhFA8uOGzTMqgTghpn7/fSnscW++dpMSAw== +"@eslint/config-helpers@^0.4.2": + version "0.4.2" + resolved "https://registry.yarnpkg.com/@eslint/config-helpers/-/config-helpers-0.4.2.tgz#1bd006ceeb7e2e55b2b773ab318d300e1a66aeda" + integrity sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw== dependencies: - "@types/json-schema" "^7.0.15" + "@eslint/core" "^0.17.0" -"@eslint/core@^0.11.0": - version "0.11.0" - resolved "https://registry.yarnpkg.com/@eslint/core/-/core-0.11.0.tgz#7a9226e850922e42cbd2ba71361eacbe74352a12" - integrity sha512-DWUB2pksgNEb6Bz2fggIy1wh6fGgZP4Xyy/Mt0QZPiloKKXerbqq9D3SBQTlCRYOrcRPu4vuz+CGjwdfqxnoWA== +"@eslint/core@^0.17.0": + version "0.17.0" + resolved "https://registry.yarnpkg.com/@eslint/core/-/core-0.17.0.tgz#77225820413d9617509da9342190a2019e78761c" + integrity sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ== dependencies: "@types/json-schema" "^7.0.15" -"@eslint/eslintrc@^3.2.0": - version "3.2.0" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-3.2.0.tgz#57470ac4e2e283a6bf76044d63281196e370542c" - integrity sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w== +"@eslint/eslintrc@^3.3.1": + version "3.3.3" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-3.3.3.tgz#26393a0806501b5e2b6a43aa588a4d8df67880ac" + integrity sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ== dependencies: ajv "^6.12.4" debug "^4.3.2" @@ -396,26 +403,26 @@ globals "^14.0.0" ignore "^5.2.0" import-fresh "^3.2.1" - js-yaml "^4.1.0" + js-yaml "^4.1.1" minimatch "^3.1.2" strip-json-comments "^3.1.1" -"@eslint/js@9.20.0": - version "9.20.0" - resolved "https://registry.yarnpkg.com/@eslint/js/-/js-9.20.0.tgz#7421bcbe74889fcd65d1be59f00130c289856eb4" - integrity sha512-iZA07H9io9Wn836aVTytRaNqh00Sad+EamwOVJT12GTLw1VGMFV/4JaME+JjLtr9fiGaoWgYnS54wrfWsSs4oQ== +"@eslint/js@9.39.1": + version "9.39.1" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-9.39.1.tgz#0dd59c3a9f40e3f1882975c321470969243e0164" + integrity sha512-S26Stp4zCy88tH94QbBv3XCuzRQiZ9yXofEILmglYTh/Ug/a9/umqvgFtYBAo3Lp0nsI/5/qH1CCrbdK3AP1Tw== -"@eslint/object-schema@^2.1.6": - version "2.1.6" - resolved "https://registry.yarnpkg.com/@eslint/object-schema/-/object-schema-2.1.6.tgz#58369ab5b5b3ca117880c0f6c0b0f32f6950f24f" - integrity sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA== +"@eslint/object-schema@^2.1.7": + version "2.1.7" + resolved "https://registry.yarnpkg.com/@eslint/object-schema/-/object-schema-2.1.7.tgz#6e2126a1347e86a4dedf8706ec67ff8e107ebbad" + integrity sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA== -"@eslint/plugin-kit@^0.2.5": - version "0.2.5" - resolved "https://registry.yarnpkg.com/@eslint/plugin-kit/-/plugin-kit-0.2.5.tgz#ee07372035539e7847ef834e3f5e7b79f09e3a81" - integrity sha512-lB05FkqEdUg2AA0xEbUz0SnkXT1LcCTa438W4IWTUh4hdOnVbQyOJ81OrDXsJk/LSiJHubgGEFoR5EHq1NsH1A== +"@eslint/plugin-kit@^0.4.1": + version "0.4.1" + resolved "https://registry.yarnpkg.com/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz#9779e3fd9b7ee33571a57435cf4335a1794a6cb2" + integrity sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA== dependencies: - "@eslint/core" "^0.10.0" + "@eslint/core" "^0.17.0" levn "^0.4.1" "@humanfs/core@^0.19.1": @@ -441,10 +448,10 @@ resolved "https://registry.yarnpkg.com/@humanwhocodes/retry/-/retry-0.3.1.tgz#c72a5c76a9fbaf3488e231b13dc52c0da7bab42a" integrity sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA== -"@humanwhocodes/retry@^0.4.1": - version "0.4.1" - resolved "https://registry.yarnpkg.com/@humanwhocodes/retry/-/retry-0.4.1.tgz#9a96ce501bc62df46c4031fbd970e3cc6b10f07b" - integrity sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA== +"@humanwhocodes/retry@^0.4.2": + version "0.4.3" + resolved "https://registry.yarnpkg.com/@humanwhocodes/retry/-/retry-0.4.3.tgz#c2b9d2e374ee62c586d3adbea87199b1d7a7a6ba" + integrity sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ== "@istanbuljs/load-nyc-config@^1.0.0": version "1.1.0" @@ -1057,6 +1064,11 @@ acorn@^8.14.0: resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.14.0.tgz#063e2c70cac5fb4f6467f0b11152e04c682795b0" integrity sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA== +acorn@^8.15.0: + version "8.15.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.15.0.tgz#a360898bc415edaac46c8241f6383975b930b816" + integrity sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg== + acorn@^8.4.1: version "8.7.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.0.tgz#90951fde0f8f09df93549481e5fc141445b791cf" @@ -1560,15 +1572,15 @@ eslint-plugin-unused-imports@^4.1.4: resolved "https://registry.yarnpkg.com/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-4.1.4.tgz#62ddc7446ccbf9aa7b6f1f0b00a980423cda2738" integrity sha512-YptD6IzQjDardkl0POxnnRBhU1OEePMV0nd6siHaRBbd+lyh6NAhFEobiznKU7kTsSsDeSD62Pe7kAM1b7dAZQ== -eslint-scope@^8.2.0: - version "8.2.0" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-8.2.0.tgz#377aa6f1cb5dc7592cfd0b7f892fd0cf352ce442" - integrity sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A== +eslint-scope@^8.4.0: + version "8.4.0" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-8.4.0.tgz#88e646a207fad61436ffa39eb505147200655c82" + integrity sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg== dependencies: esrecurse "^4.3.0" estraverse "^5.2.0" -eslint-visitor-keys@^3.3.0: +eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.3: version "3.4.3" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== @@ -1578,31 +1590,36 @@ eslint-visitor-keys@^4.2.0: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz#687bacb2af884fcdda8a6e7d65c606f46a14cd45" integrity sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw== -eslint@^9.20.1: - version "9.20.1" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-9.20.1.tgz#923924c078f5226832449bac86662dd7e53c91d6" - integrity sha512-m1mM33o6dBUjxl2qb6wv6nGNwCAsns1eKtaQ4l/NPHeTvhiUPbtdfMyktxN4B3fgHIgsYh1VT3V9txblpQHq+g== +eslint-visitor-keys@^4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz#4cfea60fe7dd0ad8e816e1ed026c1d5251b512c1" + integrity sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ== + +eslint@^9.39.1: + version "9.39.1" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-9.39.1.tgz#be8bf7c6de77dcc4252b5a8dcb31c2efff74a6e5" + integrity sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g== dependencies: - "@eslint-community/eslint-utils" "^4.2.0" + "@eslint-community/eslint-utils" "^4.8.0" "@eslint-community/regexpp" "^4.12.1" - "@eslint/config-array" "^0.19.0" - "@eslint/core" "^0.11.0" - "@eslint/eslintrc" "^3.2.0" - "@eslint/js" "9.20.0" - "@eslint/plugin-kit" "^0.2.5" + "@eslint/config-array" "^0.21.1" + "@eslint/config-helpers" "^0.4.2" + "@eslint/core" "^0.17.0" + "@eslint/eslintrc" "^3.3.1" + "@eslint/js" "9.39.1" + "@eslint/plugin-kit" "^0.4.1" "@humanfs/node" "^0.16.6" "@humanwhocodes/module-importer" "^1.0.1" - "@humanwhocodes/retry" "^0.4.1" + "@humanwhocodes/retry" "^0.4.2" "@types/estree" "^1.0.6" - "@types/json-schema" "^7.0.15" ajv "^6.12.4" chalk "^4.0.0" cross-spawn "^7.0.6" debug "^4.3.2" escape-string-regexp "^4.0.0" - eslint-scope "^8.2.0" - eslint-visitor-keys "^4.2.0" - espree "^10.3.0" + eslint-scope "^8.4.0" + eslint-visitor-keys "^4.2.1" + espree "^10.4.0" esquery "^1.5.0" esutils "^2.0.2" fast-deep-equal "^3.1.3" @@ -1618,7 +1635,7 @@ eslint@^9.20.1: natural-compare "^1.4.0" optionator "^0.9.3" -espree@^10.0.1, espree@^10.3.0: +espree@^10.0.1: version "10.3.0" resolved "https://registry.yarnpkg.com/espree/-/espree-10.3.0.tgz#29267cf5b0cb98735b65e64ba07e0ed49d1eed8a" integrity sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg== @@ -1627,6 +1644,15 @@ espree@^10.0.1, espree@^10.3.0: acorn-jsx "^5.3.2" eslint-visitor-keys "^4.2.0" +espree@^10.4.0: + version "10.4.0" + resolved "https://registry.yarnpkg.com/espree/-/espree-10.4.0.tgz#d54f4949d4629005a1fa168d937c3ff1f7e2a837" + integrity sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ== + dependencies: + acorn "^8.15.0" + acorn-jsx "^5.3.2" + eslint-visitor-keys "^4.2.1" + esprima@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" @@ -2440,10 +2466,10 @@ js-yaml@^3.13.1: argparse "^1.0.7" esprima "^4.0.0" -js-yaml@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" - integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== +js-yaml@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.1.tgz#854c292467705b699476e1a2decc0c8a3458806b" + integrity sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA== dependencies: argparse "^2.0.1" From 2817c86cb933c024be2c598d5a7e2d1bff820fcf Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 5 Dec 2025 20:08:31 +0000 Subject: [PATCH 220/551] feat: Add `async_timeout_seconds` to PostInvocations --- .stats.yml | 4 ++-- src/resources/invocations.ts | 6 ++++++ tests/api-resources/invocations.test.ts | 1 + 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 25e77f1e..7792bb0d 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 74 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-3db06d1628149b5ea8303f1c72250664dfd7cb4a14ceb6102f1ae6e85c92c038.yml -openapi_spec_hash: e5b3da2da328eb26d2a70e2521744c62 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-003e9afa15f0765009d2c7d34e8eb62268d818e628e3c84361b21138e30cc423.yml +openapi_spec_hash: c1b8309f60385bf2b02d245363ca47c1 config_hash: a4124701ae0a474e580d7416adbcfb00 diff --git a/src/resources/invocations.ts b/src/resources/invocations.ts index 95d36e3e..5b9106d2 100644 --- a/src/resources/invocations.ts +++ b/src/resources/invocations.ts @@ -416,6 +416,12 @@ export interface InvocationCreateParams { */ async?: boolean; + /** + * Timeout in seconds for async invocations (min 10, max 3600). Only applies when + * async is true. + */ + async_timeout_seconds?: number; + /** * Input data for the action, sent as a JSON string. */ diff --git a/tests/api-resources/invocations.test.ts b/tests/api-resources/invocations.test.ts index bf3ba646..b8c80247 100644 --- a/tests/api-resources/invocations.test.ts +++ b/tests/api-resources/invocations.test.ts @@ -31,6 +31,7 @@ describe('resource invocations', () => { app_name: 'my-app', version: '1.0.0', async: true, + async_timeout_seconds: 600, payload: '{"data":"example input"}', }); }); From ab3c26def9d5cfac381f9c1d3d4d0f3d61bfeb82 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 5 Dec 2025 20:12:17 +0000 Subject: [PATCH 221/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index d3535156..788b0fa7 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.21.0" + ".": "0.22.0" } diff --git a/package.json b/package.json index 7ba9dac6..76cf5a42 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.21.0", + "version": "0.22.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index bc954354..db66d332 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.21.0'; // x-release-please-version +export const VERSION = '0.22.0'; // x-release-please-version From b1a1687f5e1c98707d0334370a5b4d4fd2158b51 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 5 Dec 2025 22:00:26 +0000 Subject: [PATCH 222/551] refactor(browser): remove persistence option UI --- .stats.yml | 6 ++--- README.md | 34 +++++++++++++--------------- src/resources/browser-pools.ts | 3 ++- src/resources/browsers/browsers.ts | 36 +++++++++++++++--------------- 4 files changed, 38 insertions(+), 41 deletions(-) diff --git a/.stats.yml b/.stats.yml index 7792bb0d..a0095f11 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 74 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-003e9afa15f0765009d2c7d34e8eb62268d818e628e3c84361b21138e30cc423.yml -openapi_spec_hash: c1b8309f60385bf2b02d245363ca47c1 -config_hash: a4124701ae0a474e580d7416adbcfb00 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-cbef7e4fef29ad40af5c767aceb762ee68811c2287f255c05d2ee44a9a9247a2.yml +openapi_spec_hash: 467e61e072773ec9f2d49c7dd3de8c2f +config_hash: 6dbe88d2ba9df1ec46cedbfdb7d00000 diff --git a/README.md b/README.md index 0018d91e..3007e652 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ const client = new Kernel({ environment: 'development', // defaults to 'production' }); -const browser = await client.browsers.create({ persistence: { id: 'browser-for-user-1234' } }); +const browser = await client.browsers.create({ stealth: true }); console.log(browser.session_id); ``` @@ -45,7 +45,7 @@ const client = new Kernel({ environment: 'development', // defaults to 'production' }); -const params: Kernel.BrowserCreateParams = { persistence: { id: 'browser-for-user-1234' } }; +const params: Kernel.BrowserCreateParams = { stealth: true }; const browser: Kernel.BrowserCreateResponse = await client.browsers.create(params); ``` @@ -88,17 +88,15 @@ a subclass of `APIError` will be thrown: ```ts -const browser = await client.browsers - .create({ persistence: { id: 'browser-for-user-1234' } }) - .catch(async (err) => { - if (err instanceof Kernel.APIError) { - console.log(err.status); // 400 - console.log(err.name); // BadRequestError - console.log(err.headers); // {server: 'nginx', ...} - } else { - throw err; - } - }); +const browser = await client.browsers.create({ stealth: true }).catch(async (err) => { + if (err instanceof Kernel.APIError) { + console.log(err.status); // 400 + console.log(err.name); // BadRequestError + console.log(err.headers); // {server: 'nginx', ...} + } else { + throw err; + } +}); ``` Error codes are as follows: @@ -130,7 +128,7 @@ const client = new Kernel({ }); // Or, configure per-request: -await client.browsers.create({ persistence: { id: 'browser-for-user-1234' } }, { +await client.browsers.create({ stealth: true }, { maxRetries: 5, }); ``` @@ -147,7 +145,7 @@ const client = new Kernel({ }); // Override per-request: -await client.browsers.create({ persistence: { id: 'browser-for-user-1234' } }, { +await client.browsers.create({ stealth: true }, { timeout: 5 * 1000, }); ``` @@ -201,13 +199,11 @@ Unlike `.asResponse()` this method consumes the body, returning once it is parse ```ts const client = new Kernel(); -const response = await client.browsers.create({ persistence: { id: 'browser-for-user-1234' } }).asResponse(); +const response = await client.browsers.create({ stealth: true }).asResponse(); console.log(response.headers.get('X-My-Header')); console.log(response.statusText); // access the underlying Response object -const { data: browser, response: raw } = await client.browsers - .create({ persistence: { id: 'browser-for-user-1234' } }) - .withResponse(); +const { data: browser, response: raw } = await client.browsers.create({ stealth: true }).withResponse(); console.log(raw.headers.get('X-My-Header')); console.log(browser.session_id); ``` diff --git a/src/resources/browser-pools.ts b/src/resources/browser-pools.ts index be28ad06..d60dbe79 100644 --- a/src/resources/browser-pools.ts +++ b/src/resources/browser-pools.ts @@ -339,7 +339,8 @@ export interface BrowserPoolAcquireResponse { kiosk_mode?: boolean; /** - * Optional persistence configuration for the browser session. + * @deprecated DEPRECATED: Use timeout_seconds (up to 72 hours) and Profiles + * instead. */ persistence?: BrowsersAPI.BrowserPersistence; diff --git a/src/resources/browsers/browsers.ts b/src/resources/browsers/browsers.ts index d3f8b3d1..0fcd3eb4 100644 --- a/src/resources/browsers/browsers.ts +++ b/src/resources/browsers/browsers.ts @@ -127,14 +127,10 @@ export class Browsers extends APIResource { } /** - * Delete a persistent browser session by its persistent_id. + * DEPRECATED: Use DELETE /browsers/{id} instead. Delete a persistent browser + * session by its persistent_id. * - * @example - * ```ts - * await client.browsers.delete({ - * persistent_id: 'persistent_id', - * }); - * ``` + * @deprecated */ delete(params: BrowserDeleteParams, options?: RequestOptions): APIPromise { const { persistent_id } = params; @@ -192,11 +188,12 @@ export class Browsers extends APIResource { export type BrowserListResponsesOffsetPagination = OffsetPagination; /** - * Optional persistence configuration for the browser session. + * @deprecated DEPRECATED: Use timeout_seconds (up to 72 hours) and Profiles + * instead. */ export interface BrowserPersistence { /** - * Unique identifier for the persistent browser session. + * DEPRECATED: Unique identifier for the persistent browser session. */ id: string; } @@ -279,7 +276,8 @@ export interface BrowserCreateResponse { kiosk_mode?: boolean; /** - * Optional persistence configuration for the browser session. + * @deprecated DEPRECATED: Use timeout_seconds (up to 72 hours) and Profiles + * instead. */ persistence?: BrowserPersistence; @@ -354,7 +352,8 @@ export interface BrowserRetrieveResponse { kiosk_mode?: boolean; /** - * Optional persistence configuration for the browser session. + * @deprecated DEPRECATED: Use timeout_seconds (up to 72 hours) and Profiles + * instead. */ persistence?: BrowserPersistence; @@ -429,7 +428,8 @@ export interface BrowserListResponse { kiosk_mode?: boolean; /** - * Optional persistence configuration for the browser session. + * @deprecated DEPRECATED: Use timeout_seconds (up to 72 hours) and Profiles + * instead. */ persistence?: BrowserPersistence; @@ -480,7 +480,8 @@ export interface BrowserCreateParams { kiosk_mode?: boolean; /** - * Optional persistence configuration for the browser session. + * @deprecated DEPRECATED: Use timeout_seconds (up to 72 hours) and Profiles + * instead. */ persistence?: BrowserPersistence; @@ -505,11 +506,10 @@ export interface BrowserCreateParams { /** * The number of seconds of inactivity before the browser session is terminated. - * Only applicable to non-persistent browsers. Activity includes CDP connections - * and live view connections. Defaults to 60 seconds. Minimum allowed is 10 - * seconds. Maximum allowed is 259200 (72 hours). We check for inactivity every 5 - * seconds, so the actual timeout behavior you will see is +/- 5 seconds around the - * specified value. + * Activity includes CDP connections and live view connections. Defaults to 60 + * seconds. Minimum allowed is 10 seconds. Maximum allowed is 259200 (72 hours). We + * check for inactivity every 5 seconds, so the actual timeout behavior you will + * see is +/- 5 seconds around the specified value. */ timeout_seconds?: number; From b0093d78d8c540c5213d1f07abe67f2f05e53a35 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 5 Dec 2025 22:56:11 +0000 Subject: [PATCH 223/551] feat: [wip] Browser pools polish pass --- .stats.yml | 4 +-- src/resources/browser-pools.ts | 44 +++++++++++++++--------------- src/resources/browsers/browsers.ts | 40 +++++++++++++-------------- src/resources/shared.ts | 10 +++---- 4 files changed, 49 insertions(+), 49 deletions(-) diff --git a/.stats.yml b/.stats.yml index a0095f11..44c807a5 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 74 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-cbef7e4fef29ad40af5c767aceb762ee68811c2287f255c05d2ee44a9a9247a2.yml -openapi_spec_hash: 467e61e072773ec9f2d49c7dd3de8c2f +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-3a68acd8c46e121c66be5b4c30bb4e962967840ca0f31070905baa39635fbc2d.yml +openapi_spec_hash: 9453963fbb01de3e0afb462b16cdf115 config_hash: 6dbe88d2ba9df1ec46cedbfdb7d00000 diff --git a/src/resources/browser-pools.ts b/src/resources/browser-pools.ts index d60dbe79..6aa09c2e 100644 --- a/src/resources/browser-pools.ts +++ b/src/resources/browser-pools.ts @@ -266,11 +266,11 @@ export interface BrowserPoolRequest { /** * Initial browser window size in pixels with optional refresh rate. If omitted, - * image defaults apply (commonly 1024x768@60). Only specific viewport - * configurations are supported. The server will reject unsupported combinations. - * Supported resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25, - * 1440x900@25, 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will - * be automatically determined from the width and height if they match a supported + * image defaults apply (1920x1080@25). Only specific viewport configurations are + * supported. The server will reject unsupported combinations. Supported + * resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25, 1440x900@25, + * 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will be + * automatically determined from the width and height if they match a supported * configuration exactly. Note: Higher resolutions may affect the responsiveness of * live view browser */ @@ -284,7 +284,7 @@ export interface BrowserPoolRequest { export interface BrowserPoolUpdateRequest extends BrowserPoolRequest { /** * Whether to discard all idle browsers and rebuild the pool immediately. Defaults - * to true. + * to false. */ discard_all_idle?: boolean; } @@ -356,11 +356,11 @@ export interface BrowserPoolAcquireResponse { /** * Initial browser window size in pixels with optional refresh rate. If omitted, - * image defaults apply (commonly 1024x768@60). Only specific viewport - * configurations are supported. The server will reject unsupported combinations. - * Supported resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25, - * 1440x900@25, 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will - * be automatically determined from the width and height if they match a supported + * image defaults apply (1920x1080@25). Only specific viewport configurations are + * supported. The server will reject unsupported combinations. Supported + * resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25, 1440x900@25, + * 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will be + * automatically determined from the width and height if they match a supported * configuration exactly. Note: Higher resolutions may affect the responsiveness of * live view browser */ @@ -426,11 +426,11 @@ export interface BrowserPoolCreateParams { /** * Initial browser window size in pixels with optional refresh rate. If omitted, - * image defaults apply (commonly 1024x768@60). Only specific viewport - * configurations are supported. The server will reject unsupported combinations. - * Supported resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25, - * 1440x900@25, 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will - * be automatically determined from the width and height if they match a supported + * image defaults apply (1920x1080@25). Only specific viewport configurations are + * supported. The server will reject unsupported combinations. Supported + * resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25, 1440x900@25, + * 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will be + * automatically determined from the width and height if they match a supported * configuration exactly. Note: Higher resolutions may affect the responsiveness of * live view browser */ @@ -445,7 +445,7 @@ export interface BrowserPoolUpdateParams { /** * Whether to discard all idle browsers and rebuild the pool immediately. Defaults - * to true. + * to false. */ discard_all_idle?: boolean; @@ -502,11 +502,11 @@ export interface BrowserPoolUpdateParams { /** * Initial browser window size in pixels with optional refresh rate. If omitted, - * image defaults apply (commonly 1024x768@60). Only specific viewport - * configurations are supported. The server will reject unsupported combinations. - * Supported resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25, - * 1440x900@25, 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will - * be automatically determined from the width and height if they match a supported + * image defaults apply (1920x1080@25). Only specific viewport configurations are + * supported. The server will reject unsupported combinations. Supported + * resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25, 1440x900@25, + * 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will be + * automatically determined from the width and height if they match a supported * configuration exactly. Note: Higher resolutions may affect the responsiveness of * live view browser */ diff --git a/src/resources/browsers/browsers.ts b/src/resources/browsers/browsers.ts index 0fcd3eb4..b42c3832 100644 --- a/src/resources/browsers/browsers.ts +++ b/src/resources/browsers/browsers.ts @@ -293,11 +293,11 @@ export interface BrowserCreateResponse { /** * Initial browser window size in pixels with optional refresh rate. If omitted, - * image defaults apply (commonly 1024x768@60). Only specific viewport - * configurations are supported. The server will reject unsupported combinations. - * Supported resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25, - * 1440x900@25, 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will - * be automatically determined from the width and height if they match a supported + * image defaults apply (1920x1080@25). Only specific viewport configurations are + * supported. The server will reject unsupported combinations. Supported + * resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25, 1440x900@25, + * 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will be + * automatically determined from the width and height if they match a supported * configuration exactly. Note: Higher resolutions may affect the responsiveness of * live view browser */ @@ -369,11 +369,11 @@ export interface BrowserRetrieveResponse { /** * Initial browser window size in pixels with optional refresh rate. If omitted, - * image defaults apply (commonly 1024x768@60). Only specific viewport - * configurations are supported. The server will reject unsupported combinations. - * Supported resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25, - * 1440x900@25, 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will - * be automatically determined from the width and height if they match a supported + * image defaults apply (1920x1080@25). Only specific viewport configurations are + * supported. The server will reject unsupported combinations. Supported + * resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25, 1440x900@25, + * 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will be + * automatically determined from the width and height if they match a supported * configuration exactly. Note: Higher resolutions may affect the responsiveness of * live view browser */ @@ -445,11 +445,11 @@ export interface BrowserListResponse { /** * Initial browser window size in pixels with optional refresh rate. If omitted, - * image defaults apply (commonly 1024x768@60). Only specific viewport - * configurations are supported. The server will reject unsupported combinations. - * Supported resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25, - * 1440x900@25, 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will - * be automatically determined from the width and height if they match a supported + * image defaults apply (1920x1080@25). Only specific viewport configurations are + * supported. The server will reject unsupported combinations. Supported + * resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25, 1440x900@25, + * 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will be + * automatically determined from the width and height if they match a supported * configuration exactly. Note: Higher resolutions may affect the responsiveness of * live view browser */ @@ -515,11 +515,11 @@ export interface BrowserCreateParams { /** * Initial browser window size in pixels with optional refresh rate. If omitted, - * image defaults apply (commonly 1024x768@60). Only specific viewport - * configurations are supported. The server will reject unsupported combinations. - * Supported resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25, - * 1440x900@25, 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will - * be automatically determined from the width and height if they match a supported + * image defaults apply (1920x1080@25). Only specific viewport configurations are + * supported. The server will reject unsupported combinations. Supported + * resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25, 1440x900@25, + * 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will be + * automatically determined from the width and height if they match a supported * configuration exactly. Note: Higher resolutions may affect the responsiveness of * live view browser */ diff --git a/src/resources/shared.ts b/src/resources/shared.ts index 13cbc0b9..3a3112b7 100644 --- a/src/resources/shared.ts +++ b/src/resources/shared.ts @@ -53,11 +53,11 @@ export interface BrowserProfile { /** * Initial browser window size in pixels with optional refresh rate. If omitted, - * image defaults apply (commonly 1024x768@60). Only specific viewport - * configurations are supported. The server will reject unsupported combinations. - * Supported resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25, - * 1440x900@25, 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will - * be automatically determined from the width and height if they match a supported + * image defaults apply (1920x1080@25). Only specific viewport configurations are + * supported. The server will reject unsupported combinations. Supported + * resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25, 1440x900@25, + * 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will be + * automatically determined from the width and height if they match a supported * configuration exactly. Note: Higher resolutions may affect the responsiveness of * live view browser */ From 9f5b808ee59823b574860d9b1483a9ff77acfeec Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 6 Dec 2025 02:01:14 +0000 Subject: [PATCH 224/551] =?UTF-8?q?feat:=20Enhance=20agent=20authenticatio?= =?UTF-8?q?n=20with=20optional=20login=20page=20URL=20and=20auth=20ch?= =?UTF-8?q?=E2=80=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .stats.yml | 8 +- api.md | 31 ++ src/client.ts | 5 + src/resources/agents.ts | 3 + src/resources/agents/agents.ts | 33 ++ src/resources/agents/auth.ts | 3 + src/resources/agents/auth/auth.ts | 303 ++++++++++++++++++ src/resources/agents/auth/index.ts | 19 ++ src/resources/agents/auth/invocations.ts | 139 ++++++++ src/resources/agents/index.ts | 13 + src/resources/index.ts | 1 + tests/api-resources/agents/auth/auth.test.ts | 48 +++ .../agents/auth/invocations.test.ts | 84 +++++ 13 files changed, 686 insertions(+), 4 deletions(-) create mode 100644 src/resources/agents.ts create mode 100644 src/resources/agents/agents.ts create mode 100644 src/resources/agents/auth.ts create mode 100644 src/resources/agents/auth/auth.ts create mode 100644 src/resources/agents/auth/index.ts create mode 100644 src/resources/agents/auth/invocations.ts create mode 100644 src/resources/agents/index.ts create mode 100644 tests/api-resources/agents/auth/auth.test.ts create mode 100644 tests/api-resources/agents/auth/invocations.test.ts diff --git a/.stats.yml b/.stats.yml index 44c807a5..0c474bba 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 74 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-3a68acd8c46e121c66be5b4c30bb4e962967840ca0f31070905baa39635fbc2d.yml -openapi_spec_hash: 9453963fbb01de3e0afb462b16cdf115 -config_hash: 6dbe88d2ba9df1ec46cedbfdb7d00000 +configured_endpoints: 80 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-8a37652fa586b8932466d16285359a89988505f850787f8257d0c4c7053da173.yml +openapi_spec_hash: 042765a113f6d08109e8146b302323ec +config_hash: 113f1e5bc3567628a5d51c70bc00969d diff --git a/api.md b/api.md index c3c1b6e2..6d64516b 100644 --- a/api.md +++ b/api.md @@ -246,3 +246,34 @@ Methods: - client.browserPools.acquire(idOrName, { ...params }) -> BrowserPoolAcquireResponse - client.browserPools.flush(idOrName) -> void - client.browserPools.release(idOrName, { ...params }) -> void + +# Agents + +## Auth + +Types: + +- AgentAuthDiscoverResponse +- AgentAuthInvocationResponse +- AgentAuthStartResponse +- AgentAuthSubmitResponse +- AuthAgent +- DiscoveredField + +Methods: + +- client.agents.auth.retrieve(id) -> AuthAgent +- client.agents.auth.start({ ...params }) -> AgentAuthStartResponse + +### Invocations + +Types: + +- InvocationExchangeResponse + +Methods: + +- client.agents.auth.invocations.retrieve(invocationID) -> AgentAuthInvocationResponse +- client.agents.auth.invocations.discover(invocationID, { ...params }) -> AgentAuthDiscoverResponse +- client.agents.auth.invocations.exchange(invocationID, { ...params }) -> InvocationExchangeResponse +- client.agents.auth.invocations.submit(invocationID, { ...params }) -> AgentAuthSubmitResponse diff --git a/src/client.ts b/src/client.ts index bf7fb3b3..13526536 100644 --- a/src/client.ts +++ b/src/client.ts @@ -75,6 +75,7 @@ import { ProxyListResponse, ProxyRetrieveResponse, } from './resources/proxies'; +import { Agents } from './resources/agents/agents'; import { BrowserCreateParams, BrowserCreateResponse, @@ -836,6 +837,7 @@ export class Kernel { proxies: API.Proxies = new API.Proxies(this); extensions: API.Extensions = new API.Extensions(this); browserPools: API.BrowserPools = new API.BrowserPools(this); + agents: API.Agents = new API.Agents(this); } Kernel.Deployments = Deployments; @@ -846,6 +848,7 @@ Kernel.Profiles = Profiles; Kernel.Proxies = Proxies; Kernel.Extensions = Extensions; Kernel.BrowserPools = BrowserPools; +Kernel.Agents = Agents; export declare namespace Kernel { export type RequestOptions = Opts.RequestOptions; @@ -943,6 +946,8 @@ export declare namespace Kernel { type BrowserPoolReleaseParams as BrowserPoolReleaseParams, }; + export { Agents as Agents }; + export type AppAction = API.AppAction; export type BrowserExtension = API.BrowserExtension; export type BrowserProfile = API.BrowserProfile; diff --git a/src/resources/agents.ts b/src/resources/agents.ts new file mode 100644 index 00000000..0c43db07 --- /dev/null +++ b/src/resources/agents.ts @@ -0,0 +1,3 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export * from './agents/index'; diff --git a/src/resources/agents/agents.ts b/src/resources/agents/agents.ts new file mode 100644 index 00000000..51550282 --- /dev/null +++ b/src/resources/agents/agents.ts @@ -0,0 +1,33 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../core/resource'; +import * as AuthAPI from './auth/auth'; +import { + AgentAuthDiscoverResponse, + AgentAuthInvocationResponse, + AgentAuthStartResponse, + AgentAuthSubmitResponse, + Auth, + AuthAgent, + AuthStartParams, + DiscoveredField, +} from './auth/auth'; + +export class Agents extends APIResource { + auth: AuthAPI.Auth = new AuthAPI.Auth(this._client); +} + +Agents.Auth = Auth; + +export declare namespace Agents { + export { + Auth as Auth, + type AgentAuthDiscoverResponse as AgentAuthDiscoverResponse, + type AgentAuthInvocationResponse as AgentAuthInvocationResponse, + type AgentAuthStartResponse as AgentAuthStartResponse, + type AgentAuthSubmitResponse as AgentAuthSubmitResponse, + type AuthAgent as AuthAgent, + type DiscoveredField as DiscoveredField, + type AuthStartParams as AuthStartParams, + }; +} diff --git a/src/resources/agents/auth.ts b/src/resources/agents/auth.ts new file mode 100644 index 00000000..b64faa13 --- /dev/null +++ b/src/resources/agents/auth.ts @@ -0,0 +1,3 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export * from './auth/index'; diff --git a/src/resources/agents/auth/auth.ts b/src/resources/agents/auth/auth.ts new file mode 100644 index 00000000..65d847eb --- /dev/null +++ b/src/resources/agents/auth/auth.ts @@ -0,0 +1,303 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../../core/resource'; +import * as InvocationsAPI from './invocations'; +import { + InvocationDiscoverParams, + InvocationExchangeParams, + InvocationExchangeResponse, + InvocationSubmitParams, + Invocations, +} from './invocations'; +import { APIPromise } from '../../../core/api-promise'; +import { RequestOptions } from '../../../internal/request-options'; +import { path } from '../../../internal/utils/path'; + +export class Auth extends APIResource { + invocations: InvocationsAPI.Invocations = new InvocationsAPI.Invocations(this._client); + + /** + * Retrieve an auth agent by its ID. Returns the current authentication status of + * the managed profile. + * + * @example + * ```ts + * const authAgent = await client.agents.auth.retrieve('id'); + * ``` + */ + retrieve(id: string, options?: RequestOptions): APIPromise { + return this._client.get(path`/agents/auth/${id}`, options); + } + + /** + * Creates a browser session and returns a handoff code for the hosted flow. Uses + * standard API key or JWT authentication (not the JWT returned by the exchange + * endpoint). + * + * @example + * ```ts + * const agentAuthStartResponse = + * await client.agents.auth.start({ + * profile_name: 'auth-abc123', + * target_domain: 'doordash.com', + * }); + * ``` + */ + start(body: AuthStartParams, options?: RequestOptions): APIPromise { + return this._client.post('/agents/auth/start', { body, ...options }); + } +} + +/** + * Response from discover endpoint matching AuthBlueprint schema + */ +export interface AgentAuthDiscoverResponse { + /** + * Whether discovery succeeded + */ + success: boolean; + + /** + * Error message if discovery failed + */ + error_message?: string; + + /** + * Discovered form fields (present when success is true) + */ + fields?: Array; + + /** + * Whether user is already logged in + */ + logged_in?: boolean; + + /** + * URL of the discovered login page + */ + login_url?: string; + + /** + * Title of the login page + */ + page_title?: string; +} + +/** + * Response from get invocation endpoint + */ +export interface AgentAuthInvocationResponse { + /** + * App name (org name at time of invocation creation) + */ + app_name: string; + + /** + * When the handoff code expires + */ + expires_at: string; + + /** + * Invocation status + */ + status: 'IN_PROGRESS' | 'SUCCESS' | 'EXPIRED' | 'CANCELED'; + + /** + * Target domain for authentication + */ + target_domain: string; +} + +/** + * Response from starting an agent authentication invocation + */ +export interface AgentAuthStartResponse { + /** + * Unique identifier for the auth agent managing this domain/profile + */ + auth_agent_id: string; + + /** + * When the handoff code expires + */ + expires_at: string; + + /** + * One-time code for handoff + */ + handoff_code: string; + + /** + * URL to redirect user to + */ + hosted_url: string; + + /** + * Unique identifier for the invocation + */ + invocation_id: string; +} + +/** + * Response from submit endpoint matching SubmitResult schema + */ +export interface AgentAuthSubmitResponse { + /** + * Whether submission succeeded + */ + success: boolean; + + /** + * Additional fields needed (e.g., OTP) - present when needs_additional_auth is + * true + */ + additional_fields?: Array; + + /** + * App name (only present when logged_in is true) + */ + app_name?: string; + + /** + * Error message if submission failed + */ + error_message?: string; + + /** + * Whether user is now logged in + */ + logged_in?: boolean; + + /** + * Whether additional authentication fields are needed + */ + needs_additional_auth?: boolean; + + /** + * Target domain (only present when logged_in is true) + */ + target_domain?: string; +} + +/** + * An auth agent that manages authentication for a specific domain and profile + * combination + */ +export interface AuthAgent { + /** + * Unique identifier for the auth agent + */ + id: string; + + /** + * Target domain for authentication + */ + domain: string; + + /** + * Name of the profile associated with this auth agent + */ + profile_name: string; + + /** + * Current authentication status of the managed profile + */ + status: 'AUTHENTICATED' | 'NEEDS_AUTH'; +} + +/** + * A discovered form field + */ +export interface DiscoveredField { + /** + * Field label + */ + label: string; + + /** + * Field name + */ + name: string; + + /** + * CSS selector for the field + */ + selector: string; + + /** + * Field type + */ + type: 'text' | 'email' | 'password' | 'tel' | 'number' | 'url' | 'code'; + + /** + * Field placeholder + */ + placeholder?: string; + + /** + * Whether field is required + */ + required?: boolean; +} + +export interface AuthStartParams { + /** + * Name of the profile to use for this flow + */ + profile_name: string; + + /** + * Target domain for authentication + */ + target_domain: string; + + /** + * Optional logo URL for the application + */ + app_logo_url?: string; + + /** + * Optional login page URL. If provided, will be stored on the agent and used to + * skip Phase 1 discovery in future invocations. + */ + login_url?: string; + + /** + * Optional proxy configuration + */ + proxy?: AuthStartParams.Proxy; +} + +export namespace AuthStartParams { + /** + * Optional proxy configuration + */ + export interface Proxy { + /** + * ID of the proxy to use + */ + proxy_id?: string; + } +} + +Auth.Invocations = Invocations; + +export declare namespace Auth { + export { + type AgentAuthDiscoverResponse as AgentAuthDiscoverResponse, + type AgentAuthInvocationResponse as AgentAuthInvocationResponse, + type AgentAuthStartResponse as AgentAuthStartResponse, + type AgentAuthSubmitResponse as AgentAuthSubmitResponse, + type AuthAgent as AuthAgent, + type DiscoveredField as DiscoveredField, + type AuthStartParams as AuthStartParams, + }; + + export { + Invocations as Invocations, + type InvocationExchangeResponse as InvocationExchangeResponse, + type InvocationDiscoverParams as InvocationDiscoverParams, + type InvocationExchangeParams as InvocationExchangeParams, + type InvocationSubmitParams as InvocationSubmitParams, + }; +} diff --git a/src/resources/agents/auth/index.ts b/src/resources/agents/auth/index.ts new file mode 100644 index 00000000..b3646430 --- /dev/null +++ b/src/resources/agents/auth/index.ts @@ -0,0 +1,19 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export { + Auth, + type AgentAuthDiscoverResponse, + type AgentAuthInvocationResponse, + type AgentAuthStartResponse, + type AgentAuthSubmitResponse, + type AuthAgent, + type DiscoveredField, + type AuthStartParams, +} from './auth'; +export { + Invocations, + type InvocationExchangeResponse, + type InvocationDiscoverParams, + type InvocationExchangeParams, + type InvocationSubmitParams, +} from './invocations'; diff --git a/src/resources/agents/auth/invocations.ts b/src/resources/agents/auth/invocations.ts new file mode 100644 index 00000000..4c87d5dc --- /dev/null +++ b/src/resources/agents/auth/invocations.ts @@ -0,0 +1,139 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../../core/resource'; +import * as AuthAPI from './auth'; +import { APIPromise } from '../../../core/api-promise'; +import { RequestOptions } from '../../../internal/request-options'; +import { path } from '../../../internal/utils/path'; + +export class Invocations extends APIResource { + /** + * Returns invocation details including app_name and target_domain. Uses the JWT + * returned by the exchange endpoint, or standard API key or JWT authentication. + * + * @example + * ```ts + * const agentAuthInvocationResponse = + * await client.agents.auth.invocations.retrieve( + * 'invocation_id', + * ); + * ``` + */ + retrieve(invocationID: string, options?: RequestOptions): APIPromise { + return this._client.get(path`/agents/auth/invocations/${invocationID}`, options); + } + + /** + * Inspects the target site to detect logged-in state or discover required fields. + * Returns 200 with success: true when fields are found, or 4xx/5xx for failures. + * Requires the JWT returned by the exchange endpoint. + * + * @example + * ```ts + * const agentAuthDiscoverResponse = + * await client.agents.auth.invocations.discover( + * 'invocation_id', + * ); + * ``` + */ + discover( + invocationID: string, + body: InvocationDiscoverParams | null | undefined = {}, + options?: RequestOptions, + ): APIPromise { + return this._client.post(path`/agents/auth/invocations/${invocationID}/discover`, { body, ...options }); + } + + /** + * Validates the handoff code and returns a JWT token for subsequent requests. No + * authentication required (the handoff code serves as the credential). + * + * @example + * ```ts + * const response = + * await client.agents.auth.invocations.exchange( + * 'invocation_id', + * { code: 'abc123xyz' }, + * ); + * ``` + */ + exchange( + invocationID: string, + body: InvocationExchangeParams, + options?: RequestOptions, + ): APIPromise { + return this._client.post(path`/agents/auth/invocations/${invocationID}/exchange`, { body, ...options }); + } + + /** + * Submits field values for the discovered login form and may return additional + * auth fields or success. Requires the JWT returned by the exchange endpoint. + * + * @example + * ```ts + * const agentAuthSubmitResponse = + * await client.agents.auth.invocations.submit( + * 'invocation_id', + * { + * field_values: { + * email: 'user@example.com', + * password: '********', + * }, + * }, + * ); + * ``` + */ + submit( + invocationID: string, + body: InvocationSubmitParams, + options?: RequestOptions, + ): APIPromise { + return this._client.post(path`/agents/auth/invocations/${invocationID}/submit`, { body, ...options }); + } +} + +/** + * Response from exchange endpoint + */ +export interface InvocationExchangeResponse { + /** + * Invocation ID + */ + invocation_id: string; + + /** + * JWT token with invocation_id claim (30 minute TTL) + */ + jwt: string; +} + +export interface InvocationDiscoverParams { + /** + * Optional login page URL. If provided, will override the stored login URL for + * this discovery invocation and skip Phase 1 discovery. + */ + login_url?: string; +} + +export interface InvocationExchangeParams { + /** + * Handoff code from start endpoint + */ + code: string; +} + +export interface InvocationSubmitParams { + /** + * Values for the discovered login fields + */ + field_values: { [key: string]: string }; +} + +export declare namespace Invocations { + export { + type InvocationExchangeResponse as InvocationExchangeResponse, + type InvocationDiscoverParams as InvocationDiscoverParams, + type InvocationExchangeParams as InvocationExchangeParams, + type InvocationSubmitParams as InvocationSubmitParams, + }; +} diff --git a/src/resources/agents/index.ts b/src/resources/agents/index.ts new file mode 100644 index 00000000..86baf266 --- /dev/null +++ b/src/resources/agents/index.ts @@ -0,0 +1,13 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export { Agents } from './agents'; +export { + Auth, + type AgentAuthDiscoverResponse, + type AgentAuthInvocationResponse, + type AgentAuthStartResponse, + type AgentAuthSubmitResponse, + type AuthAgent, + type DiscoveredField, + type AuthStartParams, +} from './auth/index'; diff --git a/src/resources/index.ts b/src/resources/index.ts index 420e5e28..bab015bb 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -1,6 +1,7 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. export * from './shared'; +export { Agents } from './agents/agents'; export { Apps, type AppListResponse, diff --git a/tests/api-resources/agents/auth/auth.test.ts b/tests/api-resources/agents/auth/auth.test.ts new file mode 100644 index 00000000..d0007db1 --- /dev/null +++ b/tests/api-resources/agents/auth/auth.test.ts @@ -0,0 +1,48 @@ +// 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 auth', () => { + // Prism tests are disabled + test.skip('retrieve', async () => { + const responsePromise = client.agents.auth.retrieve('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); + }); + + // Prism tests are disabled + test.skip('start: only required params', async () => { + const responsePromise = client.agents.auth.start({ + profile_name: 'auth-abc123', + target_domain: 'doordash.com', + }); + 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); + }); + + // Prism tests are disabled + test.skip('start: required and optional params', async () => { + const response = await client.agents.auth.start({ + profile_name: 'auth-abc123', + target_domain: 'doordash.com', + app_logo_url: 'https://example.com/logo.png', + login_url: 'https://doordash.com/account/login', + proxy: { proxy_id: 'proxy_id' }, + }); + }); +}); diff --git a/tests/api-resources/agents/auth/invocations.test.ts b/tests/api-resources/agents/auth/invocations.test.ts new file mode 100644 index 00000000..33a58f93 --- /dev/null +++ b/tests/api-resources/agents/auth/invocations.test.ts @@ -0,0 +1,84 @@ +// 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 invocations', () => { + // Prism tests are disabled + test.skip('retrieve', async () => { + const responsePromise = client.agents.auth.invocations.retrieve('invocation_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); + }); + + // Prism tests are disabled + test.skip('discover', async () => { + const responsePromise = client.agents.auth.invocations.discover('invocation_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); + }); + + // Prism tests are disabled + test.skip('discover: 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.agents.auth.invocations.discover( + 'invocation_id', + { login_url: 'https://doordash.com/account/login' }, + { path: '/_stainless_unknown_path' }, + ), + ).rejects.toThrow(Kernel.NotFoundError); + }); + + // Prism tests are disabled + test.skip('exchange: only required params', async () => { + const responsePromise = client.agents.auth.invocations.exchange('invocation_id', { code: 'abc123xyz' }); + 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); + }); + + // Prism tests are disabled + test.skip('exchange: required and optional params', async () => { + const response = await client.agents.auth.invocations.exchange('invocation_id', { code: 'abc123xyz' }); + }); + + // Prism tests are disabled + test.skip('submit: only required params', async () => { + const responsePromise = client.agents.auth.invocations.submit('invocation_id', { + field_values: { email: 'user@example.com', password: '********' }, + }); + 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); + }); + + // Prism tests are disabled + test.skip('submit: required and optional params', async () => { + const response = await client.agents.auth.invocations.submit('invocation_id', { + field_values: { email: 'user@example.com', password: '********' }, + }); + }); +}); From 219df484c4e89dc91c78e9a05346cd6a5c6b6230 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 6 Dec 2025 03:45:26 +0000 Subject: [PATCH 225/551] fix(mcp): return correct lines on typescript errors --- .devcontainer/Dockerfile | 23 +++++++++++++++++++++++ .eslintrc.js | 10 ++++++++++ jest.setup.ts | 0 src/internal/polyfill/file.node.d.ts | 14 ++++++++++++++ src/internal/polyfill/file.node.mjs | 9 +++++++++ tests/responses.test.ts | 24 ++++++++++++++++++++++++ 6 files changed, 80 insertions(+) create mode 100644 .devcontainer/Dockerfile create mode 100644 .eslintrc.js create mode 100644 jest.setup.ts create mode 100644 src/internal/polyfill/file.node.d.ts create mode 100644 src/internal/polyfill/file.node.mjs create mode 100644 tests/responses.test.ts diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 00000000..8ea34be9 --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,23 @@ +# syntax=docker/dockerfile:1 +FROM debian:bookworm-slim AS stainless + +RUN apt-get update && apt-get install -y \ + nodejs \ + npm \ + yarnpkg \ + && apt-get clean autoclean + +# Ensure UTF-8 encoding +ENV LANG=C.UTF-8 +ENV LC_ALL=C.UTF-8 + +# Yarn +RUN ln -sf /usr/bin/yarnpkg /usr/bin/yarn + +WORKDIR /workspace + +COPY package.json yarn.lock /workspace/ + +RUN yarn install + +COPY . /workspace diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 00000000..60f0e7a3 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,10 @@ +module.exports = { + parser: '@typescript-eslint/parser', + plugins: ['@typescript-eslint', 'unused-imports', 'prettier'], + rules: { + 'no-unused-vars': 'off', + 'prettier/prettier': 'error', + 'unused-imports/no-unused-imports': 'error', + }, + root: true, +}; diff --git a/jest.setup.ts b/jest.setup.ts new file mode 100644 index 00000000..e69de29b diff --git a/src/internal/polyfill/file.node.d.ts b/src/internal/polyfill/file.node.d.ts new file mode 100644 index 00000000..c95276d8 --- /dev/null +++ b/src/internal/polyfill/file.node.d.ts @@ -0,0 +1,14 @@ +/** + * This file polyfills the global `File` object for you if it's not already defined + * when running on Node.js + * + * This is only needed on Node.js v18 & v19. Newer versions already define `File` + * as a global. + */ + +// @ts-ignore +type nodeBuffer = typeof import('node:buffer'); +declare const File: typeof globalThis extends { File: unknown } ? (typeof globalThis)['File'] +: nodeBuffer extends { File: unknown } ? nodeBuffer['File'] +: any; +export {}; diff --git a/src/internal/polyfill/file.node.mjs b/src/internal/polyfill/file.node.mjs new file mode 100644 index 00000000..520dcb84 --- /dev/null +++ b/src/internal/polyfill/file.node.mjs @@ -0,0 +1,9 @@ +/** + * This file polyfills the global `File` object for you if it's not already defined + * when running on Node.js + * + * This is only needed on Node.js v18 & v19. Newer versions already define `File` + * as a global. + */ + +import './file.node.js'; diff --git a/tests/responses.test.ts b/tests/responses.test.ts new file mode 100644 index 00000000..7d08ea09 --- /dev/null +++ b/tests/responses.test.ts @@ -0,0 +1,24 @@ +import { createResponseHeaders } from '@onkernel/sdk/internal/headers'; + +describe('response parsing', () => { + // TODO: test unicode characters + test('headers are case agnostic', async () => { + const headers = createResponseHeaders(new Headers({ 'Content-Type': 'foo', Accept: 'text/plain' })); + expect(headers['content-type']).toEqual('foo'); + expect(headers['Content-type']).toEqual('foo'); + expect(headers['Content-Type']).toEqual('foo'); + expect(headers['accept']).toEqual('text/plain'); + expect(headers['Accept']).toEqual('text/plain'); + expect(headers['Hello-World']).toBeUndefined(); + }); + + test('duplicate headers are concatenated', () => { + const headers = createResponseHeaders( + new Headers([ + ['Content-Type', 'text/xml'], + ['Content-Type', 'application/json'], + ]), + ); + expect(headers['content-type']).toBe('text/xml, application/json'); + }); +}); From 03712f868d519736fccf4fba651e5706cb0f8951 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 6 Dec 2025 03:46:16 +0000 Subject: [PATCH 226/551] chore(internal): codegen related update --- .devcontainer/Dockerfile | 23 ----------------------- .eslintrc.js | 10 ---------- jest.setup.ts | 0 src/internal/polyfill/file.node.d.ts | 14 -------------- src/internal/polyfill/file.node.mjs | 9 --------- tests/responses.test.ts | 24 ------------------------ 6 files changed, 80 deletions(-) delete mode 100644 .devcontainer/Dockerfile delete mode 100644 .eslintrc.js delete mode 100644 jest.setup.ts delete mode 100644 src/internal/polyfill/file.node.d.ts delete mode 100644 src/internal/polyfill/file.node.mjs delete mode 100644 tests/responses.test.ts diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile deleted file mode 100644 index 8ea34be9..00000000 --- a/.devcontainer/Dockerfile +++ /dev/null @@ -1,23 +0,0 @@ -# syntax=docker/dockerfile:1 -FROM debian:bookworm-slim AS stainless - -RUN apt-get update && apt-get install -y \ - nodejs \ - npm \ - yarnpkg \ - && apt-get clean autoclean - -# Ensure UTF-8 encoding -ENV LANG=C.UTF-8 -ENV LC_ALL=C.UTF-8 - -# Yarn -RUN ln -sf /usr/bin/yarnpkg /usr/bin/yarn - -WORKDIR /workspace - -COPY package.json yarn.lock /workspace/ - -RUN yarn install - -COPY . /workspace diff --git a/.eslintrc.js b/.eslintrc.js deleted file mode 100644 index 60f0e7a3..00000000 --- a/.eslintrc.js +++ /dev/null @@ -1,10 +0,0 @@ -module.exports = { - parser: '@typescript-eslint/parser', - plugins: ['@typescript-eslint', 'unused-imports', 'prettier'], - rules: { - 'no-unused-vars': 'off', - 'prettier/prettier': 'error', - 'unused-imports/no-unused-imports': 'error', - }, - root: true, -}; diff --git a/jest.setup.ts b/jest.setup.ts deleted file mode 100644 index e69de29b..00000000 diff --git a/src/internal/polyfill/file.node.d.ts b/src/internal/polyfill/file.node.d.ts deleted file mode 100644 index c95276d8..00000000 --- a/src/internal/polyfill/file.node.d.ts +++ /dev/null @@ -1,14 +0,0 @@ -/** - * This file polyfills the global `File` object for you if it's not already defined - * when running on Node.js - * - * This is only needed on Node.js v18 & v19. Newer versions already define `File` - * as a global. - */ - -// @ts-ignore -type nodeBuffer = typeof import('node:buffer'); -declare const File: typeof globalThis extends { File: unknown } ? (typeof globalThis)['File'] -: nodeBuffer extends { File: unknown } ? nodeBuffer['File'] -: any; -export {}; diff --git a/src/internal/polyfill/file.node.mjs b/src/internal/polyfill/file.node.mjs deleted file mode 100644 index 520dcb84..00000000 --- a/src/internal/polyfill/file.node.mjs +++ /dev/null @@ -1,9 +0,0 @@ -/** - * This file polyfills the global `File` object for you if it's not already defined - * when running on Node.js - * - * This is only needed on Node.js v18 & v19. Newer versions already define `File` - * as a global. - */ - -import './file.node.js'; diff --git a/tests/responses.test.ts b/tests/responses.test.ts deleted file mode 100644 index 7d08ea09..00000000 --- a/tests/responses.test.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { createResponseHeaders } from '@onkernel/sdk/internal/headers'; - -describe('response parsing', () => { - // TODO: test unicode characters - test('headers are case agnostic', async () => { - const headers = createResponseHeaders(new Headers({ 'Content-Type': 'foo', Accept: 'text/plain' })); - expect(headers['content-type']).toEqual('foo'); - expect(headers['Content-type']).toEqual('foo'); - expect(headers['Content-Type']).toEqual('foo'); - expect(headers['accept']).toEqual('text/plain'); - expect(headers['Accept']).toEqual('text/plain'); - expect(headers['Hello-World']).toBeUndefined(); - }); - - test('duplicate headers are concatenated', () => { - const headers = createResponseHeaders( - new Headers([ - ['Content-Type', 'text/xml'], - ['Content-Type', 'application/json'], - ]), - ); - expect(headers['content-type']).toBe('text/xml, application/json'); - }); -}); From 53426ca51d807a4bbb89d77697b9bc3ac317fffb Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 6 Dec 2025 03:47:13 +0000 Subject: [PATCH 227/551] fix(mcp): correct code tool API endpoint --- .devcontainer/Dockerfile | 23 +++++++++++++++++++++++ .eslintrc.js | 10 ++++++++++ jest.setup.ts | 0 src/internal/polyfill/file.node.d.ts | 14 ++++++++++++++ src/internal/polyfill/file.node.mjs | 9 +++++++++ tests/responses.test.ts | 24 ++++++++++++++++++++++++ 6 files changed, 80 insertions(+) create mode 100644 .devcontainer/Dockerfile create mode 100644 .eslintrc.js create mode 100644 jest.setup.ts create mode 100644 src/internal/polyfill/file.node.d.ts create mode 100644 src/internal/polyfill/file.node.mjs create mode 100644 tests/responses.test.ts diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 00000000..8ea34be9 --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,23 @@ +# syntax=docker/dockerfile:1 +FROM debian:bookworm-slim AS stainless + +RUN apt-get update && apt-get install -y \ + nodejs \ + npm \ + yarnpkg \ + && apt-get clean autoclean + +# Ensure UTF-8 encoding +ENV LANG=C.UTF-8 +ENV LC_ALL=C.UTF-8 + +# Yarn +RUN ln -sf /usr/bin/yarnpkg /usr/bin/yarn + +WORKDIR /workspace + +COPY package.json yarn.lock /workspace/ + +RUN yarn install + +COPY . /workspace diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 00000000..60f0e7a3 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,10 @@ +module.exports = { + parser: '@typescript-eslint/parser', + plugins: ['@typescript-eslint', 'unused-imports', 'prettier'], + rules: { + 'no-unused-vars': 'off', + 'prettier/prettier': 'error', + 'unused-imports/no-unused-imports': 'error', + }, + root: true, +}; diff --git a/jest.setup.ts b/jest.setup.ts new file mode 100644 index 00000000..e69de29b diff --git a/src/internal/polyfill/file.node.d.ts b/src/internal/polyfill/file.node.d.ts new file mode 100644 index 00000000..c95276d8 --- /dev/null +++ b/src/internal/polyfill/file.node.d.ts @@ -0,0 +1,14 @@ +/** + * This file polyfills the global `File` object for you if it's not already defined + * when running on Node.js + * + * This is only needed on Node.js v18 & v19. Newer versions already define `File` + * as a global. + */ + +// @ts-ignore +type nodeBuffer = typeof import('node:buffer'); +declare const File: typeof globalThis extends { File: unknown } ? (typeof globalThis)['File'] +: nodeBuffer extends { File: unknown } ? nodeBuffer['File'] +: any; +export {}; diff --git a/src/internal/polyfill/file.node.mjs b/src/internal/polyfill/file.node.mjs new file mode 100644 index 00000000..520dcb84 --- /dev/null +++ b/src/internal/polyfill/file.node.mjs @@ -0,0 +1,9 @@ +/** + * This file polyfills the global `File` object for you if it's not already defined + * when running on Node.js + * + * This is only needed on Node.js v18 & v19. Newer versions already define `File` + * as a global. + */ + +import './file.node.js'; diff --git a/tests/responses.test.ts b/tests/responses.test.ts new file mode 100644 index 00000000..7d08ea09 --- /dev/null +++ b/tests/responses.test.ts @@ -0,0 +1,24 @@ +import { createResponseHeaders } from '@onkernel/sdk/internal/headers'; + +describe('response parsing', () => { + // TODO: test unicode characters + test('headers are case agnostic', async () => { + const headers = createResponseHeaders(new Headers({ 'Content-Type': 'foo', Accept: 'text/plain' })); + expect(headers['content-type']).toEqual('foo'); + expect(headers['Content-type']).toEqual('foo'); + expect(headers['Content-Type']).toEqual('foo'); + expect(headers['accept']).toEqual('text/plain'); + expect(headers['Accept']).toEqual('text/plain'); + expect(headers['Hello-World']).toBeUndefined(); + }); + + test('duplicate headers are concatenated', () => { + const headers = createResponseHeaders( + new Headers([ + ['Content-Type', 'text/xml'], + ['Content-Type', 'application/json'], + ]), + ); + expect(headers['content-type']).toBe('text/xml, application/json'); + }); +}); From 47f0148e8516a1aad05fbf83f73717de29f55c48 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 6 Dec 2025 03:47:53 +0000 Subject: [PATCH 228/551] chore(internal): codegen related update --- .devcontainer/Dockerfile | 23 ----------------------- .eslintrc.js | 10 ---------- jest.setup.ts | 0 src/internal/polyfill/file.node.d.ts | 14 -------------- src/internal/polyfill/file.node.mjs | 9 --------- tests/responses.test.ts | 24 ------------------------ 6 files changed, 80 deletions(-) delete mode 100644 .devcontainer/Dockerfile delete mode 100644 .eslintrc.js delete mode 100644 jest.setup.ts delete mode 100644 src/internal/polyfill/file.node.d.ts delete mode 100644 src/internal/polyfill/file.node.mjs delete mode 100644 tests/responses.test.ts diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile deleted file mode 100644 index 8ea34be9..00000000 --- a/.devcontainer/Dockerfile +++ /dev/null @@ -1,23 +0,0 @@ -# syntax=docker/dockerfile:1 -FROM debian:bookworm-slim AS stainless - -RUN apt-get update && apt-get install -y \ - nodejs \ - npm \ - yarnpkg \ - && apt-get clean autoclean - -# Ensure UTF-8 encoding -ENV LANG=C.UTF-8 -ENV LC_ALL=C.UTF-8 - -# Yarn -RUN ln -sf /usr/bin/yarnpkg /usr/bin/yarn - -WORKDIR /workspace - -COPY package.json yarn.lock /workspace/ - -RUN yarn install - -COPY . /workspace diff --git a/.eslintrc.js b/.eslintrc.js deleted file mode 100644 index 60f0e7a3..00000000 --- a/.eslintrc.js +++ /dev/null @@ -1,10 +0,0 @@ -module.exports = { - parser: '@typescript-eslint/parser', - plugins: ['@typescript-eslint', 'unused-imports', 'prettier'], - rules: { - 'no-unused-vars': 'off', - 'prettier/prettier': 'error', - 'unused-imports/no-unused-imports': 'error', - }, - root: true, -}; diff --git a/jest.setup.ts b/jest.setup.ts deleted file mode 100644 index e69de29b..00000000 diff --git a/src/internal/polyfill/file.node.d.ts b/src/internal/polyfill/file.node.d.ts deleted file mode 100644 index c95276d8..00000000 --- a/src/internal/polyfill/file.node.d.ts +++ /dev/null @@ -1,14 +0,0 @@ -/** - * This file polyfills the global `File` object for you if it's not already defined - * when running on Node.js - * - * This is only needed on Node.js v18 & v19. Newer versions already define `File` - * as a global. - */ - -// @ts-ignore -type nodeBuffer = typeof import('node:buffer'); -declare const File: typeof globalThis extends { File: unknown } ? (typeof globalThis)['File'] -: nodeBuffer extends { File: unknown } ? nodeBuffer['File'] -: any; -export {}; diff --git a/src/internal/polyfill/file.node.mjs b/src/internal/polyfill/file.node.mjs deleted file mode 100644 index 520dcb84..00000000 --- a/src/internal/polyfill/file.node.mjs +++ /dev/null @@ -1,9 +0,0 @@ -/** - * This file polyfills the global `File` object for you if it's not already defined - * when running on Node.js - * - * This is only needed on Node.js v18 & v19. Newer versions already define `File` - * as a global. - */ - -import './file.node.js'; diff --git a/tests/responses.test.ts b/tests/responses.test.ts deleted file mode 100644 index 7d08ea09..00000000 --- a/tests/responses.test.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { createResponseHeaders } from '@onkernel/sdk/internal/headers'; - -describe('response parsing', () => { - // TODO: test unicode characters - test('headers are case agnostic', async () => { - const headers = createResponseHeaders(new Headers({ 'Content-Type': 'foo', Accept: 'text/plain' })); - expect(headers['content-type']).toEqual('foo'); - expect(headers['Content-type']).toEqual('foo'); - expect(headers['Content-Type']).toEqual('foo'); - expect(headers['accept']).toEqual('text/plain'); - expect(headers['Accept']).toEqual('text/plain'); - expect(headers['Hello-World']).toBeUndefined(); - }); - - test('duplicate headers are concatenated', () => { - const headers = createResponseHeaders( - new Headers([ - ['Content-Type', 'text/xml'], - ['Content-Type', 'application/json'], - ]), - ); - expect(headers['content-type']).toBe('text/xml, application/json'); - }); -}); From 0b2e6e07a895686c939ecf70bf986710a90a59be Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 8 Dec 2025 06:55:43 +0000 Subject: [PATCH 229/551] =?UTF-8?q?feat:=20enhance=20agent=20authenticatio?= =?UTF-8?q?n=20API=20with=20new=20endpoints=20and=20request=E2=80=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .stats.yml | 8 +- api.md | 8 +- src/resources/agents/agents.ts | 16 +- src/resources/agents/auth/auth.ts | 181 +++++++++++++----- src/resources/agents/auth/index.ts | 9 +- src/resources/agents/auth/invocations.ts | 28 +++ src/resources/agents/index.ts | 8 +- tests/api-resources/agents/auth/auth.test.ts | 48 +++-- .../agents/auth/invocations.test.ts | 17 ++ 9 files changed, 244 insertions(+), 79 deletions(-) diff --git a/.stats.yml b/.stats.yml index 0c474bba..4bf353aa 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 80 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-8a37652fa586b8932466d16285359a89988505f850787f8257d0c4c7053da173.yml -openapi_spec_hash: 042765a113f6d08109e8146b302323ec -config_hash: 113f1e5bc3567628a5d51c70bc00969d +configured_endpoints: 82 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-b6957db438b01d979b62de21d4e674601b37d55b850b95a6e2b4c771aad5e840.yml +openapi_spec_hash: 1c8aac8322bc9df8f1b82a7e7a0c692b +config_hash: a4b4d14bdf6af723b235a6981977627c diff --git a/api.md b/api.md index 6d64516b..2050a8d2 100644 --- a/api.md +++ b/api.md @@ -255,15 +255,18 @@ Types: - AgentAuthDiscoverResponse - AgentAuthInvocationResponse -- AgentAuthStartResponse - AgentAuthSubmitResponse - AuthAgent +- AuthAgentCreateRequest +- AuthAgentInvocationCreateRequest +- AuthAgentInvocationCreateResponse - DiscoveredField Methods: +- client.agents.auth.create({ ...params }) -> AuthAgent - client.agents.auth.retrieve(id) -> AuthAgent -- client.agents.auth.start({ ...params }) -> AgentAuthStartResponse +- client.agents.auth.list({ ...params }) -> AuthAgentsOffsetPagination ### Invocations @@ -273,6 +276,7 @@ Types: Methods: +- client.agents.auth.invocations.create({ ...params }) -> AuthAgentInvocationCreateResponse - client.agents.auth.invocations.retrieve(invocationID) -> AgentAuthInvocationResponse - client.agents.auth.invocations.discover(invocationID, { ...params }) -> AgentAuthDiscoverResponse - client.agents.auth.invocations.exchange(invocationID, { ...params }) -> InvocationExchangeResponse diff --git a/src/resources/agents/agents.ts b/src/resources/agents/agents.ts index 51550282..cf10a257 100644 --- a/src/resources/agents/agents.ts +++ b/src/resources/agents/agents.ts @@ -5,11 +5,15 @@ import * as AuthAPI from './auth/auth'; import { AgentAuthDiscoverResponse, AgentAuthInvocationResponse, - AgentAuthStartResponse, AgentAuthSubmitResponse, Auth, AuthAgent, - AuthStartParams, + AuthAgentCreateRequest, + AuthAgentInvocationCreateRequest, + AuthAgentInvocationCreateResponse, + AuthAgentsOffsetPagination, + AuthCreateParams, + AuthListParams, DiscoveredField, } from './auth/auth'; @@ -24,10 +28,14 @@ export declare namespace Agents { Auth as Auth, type AgentAuthDiscoverResponse as AgentAuthDiscoverResponse, type AgentAuthInvocationResponse as AgentAuthInvocationResponse, - type AgentAuthStartResponse as AgentAuthStartResponse, type AgentAuthSubmitResponse as AgentAuthSubmitResponse, type AuthAgent as AuthAgent, + type AuthAgentCreateRequest as AuthAgentCreateRequest, + type AuthAgentInvocationCreateRequest as AuthAgentInvocationCreateRequest, + type AuthAgentInvocationCreateResponse as AuthAgentInvocationCreateResponse, type DiscoveredField as DiscoveredField, - type AuthStartParams as AuthStartParams, + type AuthAgentsOffsetPagination as AuthAgentsOffsetPagination, + type AuthCreateParams as AuthCreateParams, + type AuthListParams as AuthListParams, }; } diff --git a/src/resources/agents/auth/auth.ts b/src/resources/agents/auth/auth.ts index 65d847eb..2ece2e29 100644 --- a/src/resources/agents/auth/auth.ts +++ b/src/resources/agents/auth/auth.ts @@ -3,6 +3,7 @@ import { APIResource } from '../../../core/resource'; import * as InvocationsAPI from './invocations'; import { + InvocationCreateParams, InvocationDiscoverParams, InvocationExchangeParams, InvocationExchangeResponse, @@ -10,12 +11,31 @@ import { Invocations, } from './invocations'; import { APIPromise } from '../../../core/api-promise'; +import { OffsetPagination, type OffsetPaginationParams, PagePromise } from '../../../core/pagination'; import { RequestOptions } from '../../../internal/request-options'; import { path } from '../../../internal/utils/path'; export class Auth extends APIResource { invocations: InvocationsAPI.Invocations = new InvocationsAPI.Invocations(this._client); + /** + * Creates a new auth agent for the specified domain and profile combination, or + * returns an existing one if it already exists. This is idempotent - calling with + * the same domain and profile will return the same agent. Does NOT start an + * invocation - use POST /agents/auth/invocations to start an auth flow. + * + * @example + * ```ts + * const authAgent = await client.agents.auth.create({ + * profile_name: 'user-123', + * target_domain: 'netflix.com', + * }); + * ``` + */ + create(body: AuthCreateParams, options?: RequestOptions): APIPromise { + return this._client.post('/agents/auth', { body, ...options }); + } + /** * Retrieve an auth agent by its ID. Returns the current authentication status of * the managed profile. @@ -30,24 +50,26 @@ export class Auth extends APIResource { } /** - * Creates a browser session and returns a handoff code for the hosted flow. Uses - * standard API key or JWT authentication (not the JWT returned by the exchange - * endpoint). + * List auth agents with optional filters for profile_name and target_domain. * * @example * ```ts - * const agentAuthStartResponse = - * await client.agents.auth.start({ - * profile_name: 'auth-abc123', - * target_domain: 'doordash.com', - * }); + * // Automatically fetches more pages as needed. + * for await (const authAgent of client.agents.auth.list()) { + * // ... + * } * ``` */ - start(body: AuthStartParams, options?: RequestOptions): APIPromise { - return this._client.post('/agents/auth/start', { body, ...options }); + list( + query: AuthListParams | null | undefined = {}, + options?: RequestOptions, + ): PagePromise { + return this._client.getAPIList('/agents/auth', OffsetPagination, { query, ...options }); } } +export type AuthAgentsOffsetPagination = OffsetPagination; + /** * Response from discover endpoint matching AuthBlueprint schema */ @@ -108,36 +130,6 @@ export interface AgentAuthInvocationResponse { target_domain: string; } -/** - * Response from starting an agent authentication invocation - */ -export interface AgentAuthStartResponse { - /** - * Unique identifier for the auth agent managing this domain/profile - */ - auth_agent_id: string; - - /** - * When the handoff code expires - */ - expires_at: string; - - /** - * One-time code for handoff - */ - handoff_code: string; - - /** - * URL to redirect user to - */ - hosted_url: string; - - /** - * Unique identifier for the invocation - */ - invocation_id: string; -} - /** * Response from submit endpoint matching SubmitResult schema */ @@ -205,6 +197,79 @@ export interface AuthAgent { status: 'AUTHENTICATED' | 'NEEDS_AUTH'; } +/** + * Request to create or find an auth agent + */ +export interface AuthAgentCreateRequest { + /** + * Name of the profile to use for this auth agent + */ + profile_name: string; + + /** + * Target domain for authentication + */ + target_domain: string; + + /** + * Optional login page URL. If provided, will be stored on the agent and used to + * skip discovery in future invocations. + */ + login_url?: string; + + /** + * Optional proxy configuration + */ + proxy?: AuthAgentCreateRequest.Proxy; +} + +export namespace AuthAgentCreateRequest { + /** + * Optional proxy configuration + */ + export interface Proxy { + /** + * ID of the proxy to use + */ + proxy_id?: string; + } +} + +/** + * Request to create an invocation for an existing auth agent + */ +export interface AuthAgentInvocationCreateRequest { + /** + * ID of the auth agent to create an invocation for + */ + auth_agent_id: string; +} + +/** + * Response from creating an auth agent invocation + */ +export interface AuthAgentInvocationCreateResponse { + /** + * When the handoff code expires + */ + expires_at: string; + + /** + * One-time code for handoff + */ + handoff_code: string; + + /** + * URL to redirect user to + */ + hosted_url: string; + + /** + * Unique identifier for the invocation + */ + invocation_id: string; +} + /** * A discovered form field */ @@ -240,9 +305,9 @@ export interface DiscoveredField { required?: boolean; } -export interface AuthStartParams { +export interface AuthCreateParams { /** - * Name of the profile to use for this flow + * Name of the profile to use for this auth agent */ profile_name: string; @@ -251,24 +316,19 @@ export interface AuthStartParams { */ target_domain: string; - /** - * Optional logo URL for the application - */ - app_logo_url?: string; - /** * Optional login page URL. If provided, will be stored on the agent and used to - * skip Phase 1 discovery in future invocations. + * skip discovery in future invocations. */ login_url?: string; /** * Optional proxy configuration */ - proxy?: AuthStartParams.Proxy; + proxy?: AuthCreateParams.Proxy; } -export namespace AuthStartParams { +export namespace AuthCreateParams { /** * Optional proxy configuration */ @@ -280,22 +340,39 @@ export namespace AuthStartParams { } } +export interface AuthListParams extends OffsetPaginationParams { + /** + * Filter by profile name + */ + profile_name?: string; + + /** + * Filter by target domain + */ + target_domain?: string; +} + Auth.Invocations = Invocations; export declare namespace Auth { export { type AgentAuthDiscoverResponse as AgentAuthDiscoverResponse, type AgentAuthInvocationResponse as AgentAuthInvocationResponse, - type AgentAuthStartResponse as AgentAuthStartResponse, type AgentAuthSubmitResponse as AgentAuthSubmitResponse, type AuthAgent as AuthAgent, + type AuthAgentCreateRequest as AuthAgentCreateRequest, + type AuthAgentInvocationCreateRequest as AuthAgentInvocationCreateRequest, + type AuthAgentInvocationCreateResponse as AuthAgentInvocationCreateResponse, type DiscoveredField as DiscoveredField, - type AuthStartParams as AuthStartParams, + type AuthAgentsOffsetPagination as AuthAgentsOffsetPagination, + type AuthCreateParams as AuthCreateParams, + type AuthListParams as AuthListParams, }; export { Invocations as Invocations, type InvocationExchangeResponse as InvocationExchangeResponse, + type InvocationCreateParams as InvocationCreateParams, type InvocationDiscoverParams as InvocationDiscoverParams, type InvocationExchangeParams as InvocationExchangeParams, type InvocationSubmitParams as InvocationSubmitParams, diff --git a/src/resources/agents/auth/index.ts b/src/resources/agents/auth/index.ts index b3646430..e0a41704 100644 --- a/src/resources/agents/auth/index.ts +++ b/src/resources/agents/auth/index.ts @@ -4,15 +4,20 @@ export { Auth, type AgentAuthDiscoverResponse, type AgentAuthInvocationResponse, - type AgentAuthStartResponse, type AgentAuthSubmitResponse, type AuthAgent, + type AuthAgentCreateRequest, + type AuthAgentInvocationCreateRequest, + type AuthAgentInvocationCreateResponse, type DiscoveredField, - type AuthStartParams, + type AuthCreateParams, + type AuthListParams, + type AuthAgentsOffsetPagination, } from './auth'; export { Invocations, type InvocationExchangeResponse, + type InvocationCreateParams, type InvocationDiscoverParams, type InvocationExchangeParams, type InvocationSubmitParams, diff --git a/src/resources/agents/auth/invocations.ts b/src/resources/agents/auth/invocations.ts index 4c87d5dc..47dc4602 100644 --- a/src/resources/agents/auth/invocations.ts +++ b/src/resources/agents/auth/invocations.ts @@ -7,6 +7,26 @@ import { RequestOptions } from '../../../internal/request-options'; import { path } from '../../../internal/utils/path'; export class Invocations extends APIResource { + /** + * Creates a new authentication invocation for the specified auth agent. This + * starts the auth flow and returns a hosted URL for the user to complete + * authentication. + * + * @example + * ```ts + * const authAgentInvocationCreateResponse = + * await client.agents.auth.invocations.create({ + * auth_agent_id: 'abc123xyz', + * }); + * ``` + */ + create( + body: InvocationCreateParams, + options?: RequestOptions, + ): APIPromise { + return this._client.post('/agents/auth/invocations', { body, ...options }); + } + /** * Returns invocation details including app_name and target_domain. Uses the JWT * returned by the exchange endpoint, or standard API key or JWT authentication. @@ -107,6 +127,13 @@ export interface InvocationExchangeResponse { jwt: string; } +export interface InvocationCreateParams { + /** + * ID of the auth agent to create an invocation for + */ + auth_agent_id: string; +} + export interface InvocationDiscoverParams { /** * Optional login page URL. If provided, will override the stored login URL for @@ -132,6 +159,7 @@ export interface InvocationSubmitParams { export declare namespace Invocations { export { type InvocationExchangeResponse as InvocationExchangeResponse, + type InvocationCreateParams as InvocationCreateParams, type InvocationDiscoverParams as InvocationDiscoverParams, type InvocationExchangeParams as InvocationExchangeParams, type InvocationSubmitParams as InvocationSubmitParams, diff --git a/src/resources/agents/index.ts b/src/resources/agents/index.ts index 86baf266..4d4ea821 100644 --- a/src/resources/agents/index.ts +++ b/src/resources/agents/index.ts @@ -5,9 +5,13 @@ export { Auth, type AgentAuthDiscoverResponse, type AgentAuthInvocationResponse, - type AgentAuthStartResponse, type AgentAuthSubmitResponse, type AuthAgent, + type AuthAgentCreateRequest, + type AuthAgentInvocationCreateRequest, + type AuthAgentInvocationCreateResponse, type DiscoveredField, - type AuthStartParams, + type AuthCreateParams, + type AuthListParams, + type AuthAgentsOffsetPagination, } from './auth/index'; diff --git a/tests/api-resources/agents/auth/auth.test.ts b/tests/api-resources/agents/auth/auth.test.ts index d0007db1..a51a775f 100644 --- a/tests/api-resources/agents/auth/auth.test.ts +++ b/tests/api-resources/agents/auth/auth.test.ts @@ -8,6 +8,31 @@ const client = new Kernel({ }); describe('resource auth', () => { + // Prism tests are disabled + test.skip('create: only required params', async () => { + const responsePromise = client.agents.auth.create({ + profile_name: 'user-123', + target_domain: 'netflix.com', + }); + 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); + }); + + // Prism tests are disabled + test.skip('create: required and optional params', async () => { + const response = await client.agents.auth.create({ + profile_name: 'user-123', + target_domain: 'netflix.com', + login_url: 'https://netflix.com/login', + proxy: { proxy_id: 'proxy_id' }, + }); + }); + // Prism tests are disabled test.skip('retrieve', async () => { const responsePromise = client.agents.auth.retrieve('id'); @@ -21,11 +46,8 @@ describe('resource auth', () => { }); // Prism tests are disabled - test.skip('start: only required params', async () => { - const responsePromise = client.agents.auth.start({ - profile_name: 'auth-abc123', - target_domain: 'doordash.com', - }); + test.skip('list', async () => { + const responsePromise = client.agents.auth.list(); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -36,13 +58,13 @@ describe('resource auth', () => { }); // Prism tests are disabled - test.skip('start: required and optional params', async () => { - const response = await client.agents.auth.start({ - profile_name: 'auth-abc123', - target_domain: 'doordash.com', - app_logo_url: 'https://example.com/logo.png', - login_url: 'https://doordash.com/account/login', - proxy: { proxy_id: 'proxy_id' }, - }); + test.skip('list: 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.agents.auth.list( + { limit: 100, offset: 0, profile_name: 'profile_name', target_domain: 'target_domain' }, + { path: '/_stainless_unknown_path' }, + ), + ).rejects.toThrow(Kernel.NotFoundError); }); }); diff --git a/tests/api-resources/agents/auth/invocations.test.ts b/tests/api-resources/agents/auth/invocations.test.ts index 33a58f93..8bc769c5 100644 --- a/tests/api-resources/agents/auth/invocations.test.ts +++ b/tests/api-resources/agents/auth/invocations.test.ts @@ -8,6 +8,23 @@ const client = new Kernel({ }); describe('resource invocations', () => { + // Prism tests are disabled + test.skip('create: only required params', async () => { + const responsePromise = client.agents.auth.invocations.create({ auth_agent_id: 'abc123xyz' }); + 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); + }); + + // Prism tests are disabled + test.skip('create: required and optional params', async () => { + const response = await client.agents.auth.invocations.create({ auth_agent_id: 'abc123xyz' }); + }); + // Prism tests are disabled test.skip('retrieve', async () => { const responsePromise = client.agents.auth.invocations.retrieve('invocation_id'); From 244ecc06e7169ca7b4cfb1d363f291a5a6abba96 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 11 Dec 2025 19:34:57 +0000 Subject: [PATCH 230/551] feat: Enhance AuthAgent model with last_auth_check_at field --- .stats.yml | 4 ++-- src/resources/agents/auth/auth.ts | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 4bf353aa..135345a5 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 82 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-b6957db438b01d979b62de21d4e674601b37d55b850b95a6e2b4c771aad5e840.yml -openapi_spec_hash: 1c8aac8322bc9df8f1b82a7e7a0c692b +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-dac11bdb857e700a8c39d183e753ddd1ebaaca69fd9fc5ee57d6b56b70b00e6e.yml +openapi_spec_hash: 78fbc50dd0b61cdc87564fbea278ee23 config_hash: a4b4d14bdf6af723b235a6981977627c diff --git a/src/resources/agents/auth/auth.ts b/src/resources/agents/auth/auth.ts index 2ece2e29..ca02544b 100644 --- a/src/resources/agents/auth/auth.ts +++ b/src/resources/agents/auth/auth.ts @@ -195,6 +195,11 @@ export interface AuthAgent { * Current authentication status of the managed profile */ status: 'AUTHENTICATED' | 'NEEDS_AUTH'; + + /** + * When the last authentication check was performed + */ + last_auth_check_at?: string; } /** From f842349c4ed3c905036874836db9b2759c128982 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 11 Dec 2025 20:14:29 +0000 Subject: [PATCH 231/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 788b0fa7..97bce112 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.22.0" + ".": "0.23.0" } diff --git a/package.json b/package.json index 76cf5a42..5383c206 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.22.0", + "version": "0.23.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index db66d332..d77fad47 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.22.0'; // x-release-please-version +export const VERSION = '0.23.0'; // x-release-please-version From 38db0a5f3b8c61caff80bb9071efb758205f0f55 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 17 Dec 2025 02:00:46 +0000 Subject: [PATCH 232/551] =?UTF-8?q?feat:=20Enhance=20AuthAgentInvocationCr?= =?UTF-8?q?eateResponse=20to=20include=20already=5Fauthenti=E2=80=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .stats.yml | 8 +- api.md | 19 ++ src/client.ts | 23 ++ src/resources/agents/agents.ts | 2 + src/resources/agents/auth/auth.ts | 152 +++++++++++-- src/resources/agents/auth/index.ts | 1 + src/resources/agents/auth/invocations.ts | 7 + src/resources/agents/index.ts | 1 + src/resources/credentials.ts | 205 ++++++++++++++++++ src/resources/index.ts | 10 + tests/api-resources/agents/auth/auth.test.ts | 25 +++ .../agents/auth/invocations.test.ts | 5 +- tests/api-resources/credentials.test.ts | 94 ++++++++ 13 files changed, 533 insertions(+), 19 deletions(-) create mode 100644 src/resources/credentials.ts create mode 100644 tests/api-resources/credentials.test.ts diff --git a/.stats.yml b/.stats.yml index 135345a5..0a02606e 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 82 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-dac11bdb857e700a8c39d183e753ddd1ebaaca69fd9fc5ee57d6b56b70b00e6e.yml -openapi_spec_hash: 78fbc50dd0b61cdc87564fbea278ee23 -config_hash: a4b4d14bdf6af723b235a6981977627c +configured_endpoints: 89 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-486d57f189abcec3a678ad4a619ee8a6b8aec3a3c2f3620c0423cb16cc755a13.yml +openapi_spec_hash: affde047293fc74a8343a121d5e58a9c +config_hash: 7225e7b7e4695c81d7be26c7108b5494 diff --git a/api.md b/api.md index 2050a8d2..6f476873 100644 --- a/api.md +++ b/api.md @@ -261,12 +261,15 @@ Types: - AuthAgentInvocationCreateRequest - AuthAgentInvocationCreateResponse - DiscoveredField +- ReauthResponse Methods: - client.agents.auth.create({ ...params }) -> AuthAgent - client.agents.auth.retrieve(id) -> AuthAgent - client.agents.auth.list({ ...params }) -> AuthAgentsOffsetPagination +- client.agents.auth.delete(id) -> void +- client.agents.auth.reauth(id) -> ReauthResponse ### Invocations @@ -281,3 +284,19 @@ Methods: - client.agents.auth.invocations.discover(invocationID, { ...params }) -> AgentAuthDiscoverResponse - client.agents.auth.invocations.exchange(invocationID, { ...params }) -> InvocationExchangeResponse - client.agents.auth.invocations.submit(invocationID, { ...params }) -> AgentAuthSubmitResponse + +# Credentials + +Types: + +- CreateCredentialRequest +- Credential +- UpdateCredentialRequest + +Methods: + +- client.credentials.create({ ...params }) -> Credential +- client.credentials.retrieve(id) -> Credential +- client.credentials.update(id, { ...params }) -> Credential +- client.credentials.list({ ...params }) -> CredentialsOffsetPagination +- client.credentials.delete(id) -> void diff --git a/src/client.ts b/src/client.ts index 13526536..91007927 100644 --- a/src/client.ts +++ b/src/client.ts @@ -34,6 +34,16 @@ import { BrowserPoolUpdateRequest, BrowserPools, } from './resources/browser-pools'; +import { + CreateCredentialRequest, + Credential, + CredentialCreateParams, + CredentialListParams, + CredentialUpdateParams, + Credentials, + CredentialsOffsetPagination, + UpdateCredentialRequest, +} from './resources/credentials'; import { DeploymentCreateParams, DeploymentCreateResponse, @@ -838,6 +848,7 @@ export class Kernel { extensions: API.Extensions = new API.Extensions(this); browserPools: API.BrowserPools = new API.BrowserPools(this); agents: API.Agents = new API.Agents(this); + credentials: API.Credentials = new API.Credentials(this); } Kernel.Deployments = Deployments; @@ -849,6 +860,7 @@ Kernel.Proxies = Proxies; Kernel.Extensions = Extensions; Kernel.BrowserPools = BrowserPools; Kernel.Agents = Agents; +Kernel.Credentials = Credentials; export declare namespace Kernel { export type RequestOptions = Opts.RequestOptions; @@ -948,6 +960,17 @@ export declare namespace Kernel { export { Agents as Agents }; + export { + Credentials as Credentials, + type CreateCredentialRequest as CreateCredentialRequest, + type Credential as Credential, + type UpdateCredentialRequest as UpdateCredentialRequest, + type CredentialsOffsetPagination as CredentialsOffsetPagination, + type CredentialCreateParams as CredentialCreateParams, + type CredentialUpdateParams as CredentialUpdateParams, + type CredentialListParams as CredentialListParams, + }; + export type AppAction = API.AppAction; export type BrowserExtension = API.BrowserExtension; export type BrowserProfile = API.BrowserProfile; diff --git a/src/resources/agents/agents.ts b/src/resources/agents/agents.ts index cf10a257..cb213145 100644 --- a/src/resources/agents/agents.ts +++ b/src/resources/agents/agents.ts @@ -15,6 +15,7 @@ import { AuthCreateParams, AuthListParams, DiscoveredField, + ReauthResponse, } from './auth/auth'; export class Agents extends APIResource { @@ -34,6 +35,7 @@ export declare namespace Agents { type AuthAgentInvocationCreateRequest as AuthAgentInvocationCreateRequest, type AuthAgentInvocationCreateResponse as AuthAgentInvocationCreateResponse, type DiscoveredField as DiscoveredField, + type ReauthResponse as ReauthResponse, type AuthAgentsOffsetPagination as AuthAgentsOffsetPagination, type AuthCreateParams as AuthCreateParams, type AuthListParams as AuthListParams, diff --git a/src/resources/agents/auth/auth.ts b/src/resources/agents/auth/auth.ts index ca02544b..636dabab 100644 --- a/src/resources/agents/auth/auth.ts +++ b/src/resources/agents/auth/auth.ts @@ -12,6 +12,7 @@ import { } from './invocations'; import { APIPromise } from '../../../core/api-promise'; import { OffsetPagination, type OffsetPaginationParams, PagePromise } from '../../../core/pagination'; +import { buildHeaders } from '../../../internal/headers'; import { RequestOptions } from '../../../internal/request-options'; import { path } from '../../../internal/utils/path'; @@ -66,6 +67,42 @@ export class Auth extends APIResource { ): PagePromise { return this._client.getAPIList('/agents/auth', OffsetPagination, { query, ...options }); } + + /** + * Deletes an auth agent and terminates its workflow. This will: + * + * - Soft delete the auth agent record + * - Gracefully terminate the agent's Temporal workflow + * - Cancel any in-progress invocations + * + * @example + * ```ts + * await client.agents.auth.delete('id'); + * ``` + */ + delete(id: string, options?: RequestOptions): APIPromise { + return this._client.delete(path`/agents/auth/${id}`, { + ...options, + headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), + }); + } + + /** + * Triggers automatic re-authentication for an auth agent using stored credentials. + * Requires the auth agent to have a linked credential, stored selectors, and + * login_url. Returns immediately with status indicating whether re-auth was + * started. + * + * @example + * ```ts + * const reauthResponse = await client.agents.auth.reauth( + * 'id', + * ); + * ``` + */ + reauth(id: string, options?: RequestOptions): APIPromise { + return this._client.post(path`/agents/auth/${id}/reauth`, options); + } } export type AuthAgentsOffsetPagination = OffsetPagination; @@ -196,6 +233,27 @@ export interface AuthAgent { */ status: 'AUTHENTICATED' | 'NEEDS_AUTH'; + /** + * Whether automatic re-authentication is possible (has credential_id, selectors, + * and login_url) + */ + can_reauth?: boolean; + + /** + * ID of the linked credential for automatic re-authentication + */ + credential_id?: string; + + /** + * Name of the linked credential for automatic re-authentication + */ + credential_name?: string; + + /** + * Whether this auth agent has stored selectors for deterministic re-authentication + */ + has_selectors?: boolean; + /** * When the last authentication check was performed */ @@ -216,6 +274,13 @@ export interface AuthAgentCreateRequest { */ target_domain: string; + /** + * Optional name of an existing credential to use for this auth agent. If provided, + * the credential will be linked to the agent and its values will be used to + * auto-fill the login form on invocation. + */ + credential_name?: string; + /** * Optional login page URL. If provided, will be stored on the agent and used to * skip discovery in future invocations. @@ -248,31 +313,62 @@ export interface AuthAgentInvocationCreateRequest { * ID of the auth agent to create an invocation for */ auth_agent_id: string; + + /** + * If provided, saves the submitted credentials under this name upon successful + * login. The credential will be linked to the auth agent for automatic + * re-authentication. + */ + save_credential_as?: string; } /** - * Response from creating an auth agent invocation + * Response when the agent is already authenticated. */ -export interface AuthAgentInvocationCreateResponse { - /** - * When the handoff code expires - */ - expires_at: string; +export type AuthAgentInvocationCreateResponse = + | AuthAgentInvocationCreateResponse.AuthAgentAlreadyAuthenticated + | AuthAgentInvocationCreateResponse.AuthAgentInvocationCreated; +export namespace AuthAgentInvocationCreateResponse { /** - * One-time code for handoff + * Response when the agent is already authenticated. */ - handoff_code: string; + export interface AuthAgentAlreadyAuthenticated { + /** + * Indicates the agent is already authenticated and no invocation was created. + */ + status: 'already_authenticated'; + } /** - * URL to redirect user to + * Response when a new invocation was created. */ - hosted_url: string; + export interface AuthAgentInvocationCreated { + /** + * When the handoff code expires. + */ + expires_at: string; - /** - * Unique identifier for the invocation - */ - invocation_id: string; + /** + * One-time code for handoff. + */ + handoff_code: string; + + /** + * URL to redirect user to. + */ + hosted_url: string; + + /** + * Unique identifier for the invocation. + */ + invocation_id: string; + + /** + * Indicates an invocation was created. + */ + status: 'invocation_created'; + } } /** @@ -310,6 +406,26 @@ export interface DiscoveredField { required?: boolean; } +/** + * Response from triggering re-authentication + */ +export interface ReauthResponse { + /** + * Result of the re-authentication attempt + */ + status: 'reauth_started' | 'already_authenticated' | 'cannot_reauth'; + + /** + * ID of the re-auth invocation if one was created + */ + invocation_id?: string; + + /** + * Human-readable description of the result + */ + message?: string; +} + export interface AuthCreateParams { /** * Name of the profile to use for this auth agent @@ -321,6 +437,13 @@ export interface AuthCreateParams { */ target_domain: string; + /** + * Optional name of an existing credential to use for this auth agent. If provided, + * the credential will be linked to the agent and its values will be used to + * auto-fill the login form on invocation. + */ + credential_name?: string; + /** * Optional login page URL. If provided, will be stored on the agent and used to * skip discovery in future invocations. @@ -369,6 +492,7 @@ export declare namespace Auth { type AuthAgentInvocationCreateRequest as AuthAgentInvocationCreateRequest, type AuthAgentInvocationCreateResponse as AuthAgentInvocationCreateResponse, type DiscoveredField as DiscoveredField, + type ReauthResponse as ReauthResponse, type AuthAgentsOffsetPagination as AuthAgentsOffsetPagination, type AuthCreateParams as AuthCreateParams, type AuthListParams as AuthListParams, diff --git a/src/resources/agents/auth/index.ts b/src/resources/agents/auth/index.ts index e0a41704..bf85b044 100644 --- a/src/resources/agents/auth/index.ts +++ b/src/resources/agents/auth/index.ts @@ -10,6 +10,7 @@ export { type AuthAgentInvocationCreateRequest, type AuthAgentInvocationCreateResponse, type DiscoveredField, + type ReauthResponse, type AuthCreateParams, type AuthListParams, type AuthAgentsOffsetPagination, diff --git a/src/resources/agents/auth/invocations.ts b/src/resources/agents/auth/invocations.ts index 47dc4602..84e9cf7d 100644 --- a/src/resources/agents/auth/invocations.ts +++ b/src/resources/agents/auth/invocations.ts @@ -132,6 +132,13 @@ export interface InvocationCreateParams { * ID of the auth agent to create an invocation for */ auth_agent_id: string; + + /** + * If provided, saves the submitted credentials under this name upon successful + * login. The credential will be linked to the auth agent for automatic + * re-authentication. + */ + save_credential_as?: string; } export interface InvocationDiscoverParams { diff --git a/src/resources/agents/index.ts b/src/resources/agents/index.ts index 4d4ea821..fbd90052 100644 --- a/src/resources/agents/index.ts +++ b/src/resources/agents/index.ts @@ -11,6 +11,7 @@ export { type AuthAgentInvocationCreateRequest, type AuthAgentInvocationCreateResponse, type DiscoveredField, + type ReauthResponse, type AuthCreateParams, type AuthListParams, type AuthAgentsOffsetPagination, diff --git a/src/resources/credentials.ts b/src/resources/credentials.ts new file mode 100644 index 00000000..a90dea7a --- /dev/null +++ b/src/resources/credentials.ts @@ -0,0 +1,205 @@ +// 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 { OffsetPagination, type OffsetPaginationParams, PagePromise } from '../core/pagination'; +import { buildHeaders } from '../internal/headers'; +import { RequestOptions } from '../internal/request-options'; +import { path } from '../internal/utils/path'; + +export class Credentials extends APIResource { + /** + * Create a new credential for storing login information. Values are encrypted at + * rest. + * + * @example + * ```ts + * const credential = await client.credentials.create({ + * domain: 'netflix.com', + * name: 'my-netflix-login', + * values: { + * username: 'user@example.com', + * password: 'mysecretpassword', + * }, + * }); + * ``` + */ + create(body: CredentialCreateParams, options?: RequestOptions): APIPromise { + return this._client.post('/credentials', { body, ...options }); + } + + /** + * Retrieve a credential by its ID. Credential values are not returned. + * + * @example + * ```ts + * const credential = await client.credentials.retrieve('id'); + * ``` + */ + retrieve(id: string, options?: RequestOptions): APIPromise { + return this._client.get(path`/credentials/${id}`, options); + } + + /** + * Update a credential's name or values. Values are encrypted at rest. + * + * @example + * ```ts + * const credential = await client.credentials.update('id'); + * ``` + */ + update(id: string, body: CredentialUpdateParams, options?: RequestOptions): APIPromise { + return this._client.patch(path`/credentials/${id}`, { body, ...options }); + } + + /** + * List credentials owned by the caller's organization. Credential values are not + * returned. + * + * @example + * ```ts + * // Automatically fetches more pages as needed. + * for await (const credential of client.credentials.list()) { + * // ... + * } + * ``` + */ + list( + query: CredentialListParams | null | undefined = {}, + options?: RequestOptions, + ): PagePromise { + return this._client.getAPIList('/credentials', OffsetPagination, { query, ...options }); + } + + /** + * Delete a credential by its ID. + * + * @example + * ```ts + * await client.credentials.delete('id'); + * ``` + */ + delete(id: string, options?: RequestOptions): APIPromise { + return this._client.delete(path`/credentials/${id}`, { + ...options, + headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), + }); + } +} + +export type CredentialsOffsetPagination = OffsetPagination; + +/** + * Request to create a new credential + */ +export interface CreateCredentialRequest { + /** + * Target domain this credential is for + */ + domain: string; + + /** + * Unique name for the credential within the organization + */ + name: string; + + /** + * Field name to value mapping (e.g., username, password) + */ + values: { [key: string]: string }; +} + +/** + * A stored credential for automatic re-authentication + */ +export interface Credential { + /** + * Unique identifier for the credential + */ + id: string; + + /** + * When the credential was created + */ + created_at: string; + + /** + * Target domain this credential is for + */ + domain: string; + + /** + * Unique name for the credential within the organization + */ + name: string; + + /** + * When the credential was last updated + */ + updated_at: string; +} + +/** + * Request to update an existing credential + */ +export interface UpdateCredentialRequest { + /** + * New name for the credential + */ + name?: string; + + /** + * Field name to value mapping (e.g., username, password). Replaces all existing + * values. + */ + values?: { [key: string]: string }; +} + +export interface CredentialCreateParams { + /** + * Target domain this credential is for + */ + domain: string; + + /** + * Unique name for the credential within the organization + */ + name: string; + + /** + * Field name to value mapping (e.g., username, password) + */ + values: { [key: string]: string }; +} + +export interface CredentialUpdateParams { + /** + * New name for the credential + */ + name?: string; + + /** + * Field name to value mapping (e.g., username, password). Replaces all existing + * values. + */ + values?: { [key: string]: string }; +} + +export interface CredentialListParams extends OffsetPaginationParams { + /** + * Filter by domain + */ + domain?: string; +} + +export declare namespace Credentials { + export { + type CreateCredentialRequest as CreateCredentialRequest, + type Credential as Credential, + type UpdateCredentialRequest as UpdateCredentialRequest, + type CredentialsOffsetPagination as CredentialsOffsetPagination, + type CredentialCreateParams as CredentialCreateParams, + type CredentialUpdateParams as CredentialUpdateParams, + type CredentialListParams as CredentialListParams, + }; +} diff --git a/src/resources/index.ts b/src/resources/index.ts index bab015bb..c198953a 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -36,6 +36,16 @@ export { type BrowserLoadExtensionsParams, type BrowserListResponsesOffsetPagination, } from './browsers/browsers'; +export { + Credentials, + type CreateCredentialRequest, + type Credential, + type UpdateCredentialRequest, + type CredentialCreateParams, + type CredentialUpdateParams, + type CredentialListParams, + type CredentialsOffsetPagination, +} from './credentials'; export { Deployments, type DeploymentStateEvent, diff --git a/tests/api-resources/agents/auth/auth.test.ts b/tests/api-resources/agents/auth/auth.test.ts index a51a775f..1882e825 100644 --- a/tests/api-resources/agents/auth/auth.test.ts +++ b/tests/api-resources/agents/auth/auth.test.ts @@ -28,6 +28,7 @@ describe('resource auth', () => { const response = await client.agents.auth.create({ profile_name: 'user-123', target_domain: 'netflix.com', + credential_name: 'my-netflix-login', login_url: 'https://netflix.com/login', proxy: { proxy_id: 'proxy_id' }, }); @@ -67,4 +68,28 @@ describe('resource auth', () => { ), ).rejects.toThrow(Kernel.NotFoundError); }); + + // Prism tests are disabled + test.skip('delete', async () => { + const responsePromise = client.agents.auth.delete('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); + }); + + // Prism tests are disabled + test.skip('reauth', async () => { + const responsePromise = client.agents.auth.reauth('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); + }); }); diff --git a/tests/api-resources/agents/auth/invocations.test.ts b/tests/api-resources/agents/auth/invocations.test.ts index 8bc769c5..fc178bbb 100644 --- a/tests/api-resources/agents/auth/invocations.test.ts +++ b/tests/api-resources/agents/auth/invocations.test.ts @@ -22,7 +22,10 @@ describe('resource invocations', () => { // Prism tests are disabled test.skip('create: required and optional params', async () => { - const response = await client.agents.auth.invocations.create({ auth_agent_id: 'abc123xyz' }); + const response = await client.agents.auth.invocations.create({ + auth_agent_id: 'abc123xyz', + save_credential_as: 'my-netflix-login', + }); }); // Prism tests are disabled diff --git a/tests/api-resources/credentials.test.ts b/tests/api-resources/credentials.test.ts new file mode 100644 index 00000000..eaf6c337 --- /dev/null +++ b/tests/api-resources/credentials.test.ts @@ -0,0 +1,94 @@ +// 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 credentials', () => { + // Prism tests are disabled + test.skip('create: only required params', async () => { + const responsePromise = client.credentials.create({ + domain: 'netflix.com', + name: 'my-netflix-login', + values: { username: 'user@example.com', password: 'mysecretpassword' }, + }); + 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); + }); + + // Prism tests are disabled + test.skip('create: required and optional params', async () => { + const response = await client.credentials.create({ + domain: 'netflix.com', + name: 'my-netflix-login', + values: { username: 'user@example.com', password: 'mysecretpassword' }, + }); + }); + + // Prism tests are disabled + test.skip('retrieve', async () => { + const responsePromise = client.credentials.retrieve('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); + }); + + // Prism tests are disabled + test.skip('update', async () => { + const responsePromise = client.credentials.update('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); + }); + + // Prism tests are disabled + test.skip('list', async () => { + const responsePromise = client.credentials.list(); + 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); + }); + + // Prism tests are disabled + test.skip('list: 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.credentials.list( + { domain: 'domain', limit: 100, offset: 0 }, + { path: '/_stainless_unknown_path' }, + ), + ).rejects.toThrow(Kernel.NotFoundError); + }); + + // Prism tests are disabled + test.skip('delete', async () => { + const responsePromise = client.credentials.delete('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); + }); +}); From 555eb8aa691e25fe80d11c2c11389eff211af4e0 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 17 Dec 2025 04:35:16 +0000 Subject: [PATCH 233/551] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 0a02606e..299cb5a6 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 89 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-486d57f189abcec3a678ad4a619ee8a6b8aec3a3c2f3620c0423cb16cc755a13.yml -openapi_spec_hash: affde047293fc74a8343a121d5e58a9c +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-13214b99e392aab631aa1ca99b6a51a58df81e34156d21b8d639bea779566123.yml +openapi_spec_hash: a88d175fc3980de3097ac1411d8dcbff config_hash: 7225e7b7e4695c81d7be26c7108b5494 From a9cb95f210cc317a95ff9fbc88bd21e0e66dc0a6 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 17 Dec 2025 23:31:25 +0000 Subject: [PATCH 234/551] feat: Fix browser pool sdk types --- .stats.yml | 2 +- api.md | 4 - src/client.ts | 8 -- src/resources/browser-pools.ts | 187 +++++++++++++-------------------- src/resources/index.ts | 4 - 5 files changed, 73 insertions(+), 132 deletions(-) diff --git a/.stats.yml b/.stats.yml index 299cb5a6..99bb6c41 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 89 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-13214b99e392aab631aa1ca99b6a51a58df81e34156d21b8d639bea779566123.yml openapi_spec_hash: a88d175fc3980de3097ac1411d8dcbff -config_hash: 7225e7b7e4695c81d7be26c7108b5494 +config_hash: 179f33af31ece83563163d5b3d751d13 diff --git a/api.md b/api.md index 6f476873..4086b1a0 100644 --- a/api.md +++ b/api.md @@ -229,10 +229,6 @@ Methods: Types: - BrowserPool -- BrowserPoolAcquireRequest -- BrowserPoolReleaseRequest -- BrowserPoolRequest -- BrowserPoolUpdateRequest - BrowserPoolListResponse - BrowserPoolAcquireResponse diff --git a/src/client.ts b/src/client.ts index 91007927..97ab0dee 100644 --- a/src/client.ts +++ b/src/client.ts @@ -22,16 +22,12 @@ import { AppListParams, AppListResponse, AppListResponsesOffsetPagination, Apps import { BrowserPool, BrowserPoolAcquireParams, - BrowserPoolAcquireRequest, BrowserPoolAcquireResponse, BrowserPoolCreateParams, BrowserPoolDeleteParams, BrowserPoolListResponse, BrowserPoolReleaseParams, - BrowserPoolReleaseRequest, - BrowserPoolRequest, BrowserPoolUpdateParams, - BrowserPoolUpdateRequest, BrowserPools, } from './resources/browser-pools'; import { @@ -945,10 +941,6 @@ export declare namespace Kernel { export { BrowserPools as BrowserPools, type BrowserPool as BrowserPool, - type BrowserPoolAcquireRequest as BrowserPoolAcquireRequest, - type BrowserPoolReleaseRequest as BrowserPoolReleaseRequest, - type BrowserPoolRequest as BrowserPoolRequest, - type BrowserPoolUpdateRequest as BrowserPoolUpdateRequest, type BrowserPoolListResponse as BrowserPoolListResponse, type BrowserPoolAcquireResponse as BrowserPoolAcquireResponse, type BrowserPoolCreateParams as BrowserPoolCreateParams, diff --git a/src/resources/browser-pools.ts b/src/resources/browser-pools.ts index 6aa09c2e..9e67f7c8 100644 --- a/src/resources/browser-pools.ts +++ b/src/resources/browser-pools.ts @@ -162,7 +162,7 @@ export interface BrowserPool { /** * Configuration used to create all browsers in this pool */ - browser_pool_config: BrowserPoolRequest; + browser_pool_config: BrowserPool.BrowserPoolConfig; /** * Timestamp when the browser pool was created @@ -175,118 +175,79 @@ export interface BrowserPool { name?: string; } -/** - * Request body for acquiring a browser from the pool. - */ -export interface BrowserPoolAcquireRequest { - /** - * Maximum number of seconds to wait for a browser to be available. Defaults to the - * calculated time it would take to fill the pool at the currently configured fill - * rate. - */ - acquire_timeout_seconds?: number; -} - -/** - * Request body for releasing a browser back to the pool. - */ -export interface BrowserPoolReleaseRequest { - /** - * Browser session ID to release back to the pool - */ - session_id: string; - - /** - * Whether to reuse the browser instance or destroy it and create a new one. - * Defaults to true. - */ - reuse?: boolean; -} - -/** - * Parameters for creating a browser pool. All browsers in the pool will be created - * with the same configuration. - */ -export interface BrowserPoolRequest { - /** - * Number of browsers to create in the pool - */ - size: number; - - /** - * List of browser extensions to load into the session. Provide each by id or name. - */ - extensions?: Array; - - /** - * Percentage of the pool to fill per minute. Defaults to 10%. - */ - fill_rate_per_minute?: number; - - /** - * If true, launches the browser using a headless image. Defaults to false. - */ - headless?: boolean; - - /** - * If true, launches the browser in kiosk mode to hide address bar and tabs in live - * view. - */ - kiosk_mode?: boolean; - - /** - * Optional name for the browser pool. Must be unique within the organization. - */ - name?: string; - - /** - * Profile selection for the browser session. Provide either id or name. If - * specified, the matching profile will be loaded into the browser session. - * Profiles must be created beforehand. - */ - profile?: Shared.BrowserProfile; - +export namespace BrowserPool { /** - * Optional proxy to associate to the browser session. Must reference a proxy - * belonging to the caller's org. - */ - proxy_id?: string; - - /** - * If true, launches the browser in stealth mode to reduce detection by anti-bot - * mechanisms. - */ - stealth?: boolean; - - /** - * Default idle timeout in seconds for browsers acquired from this pool before they - * are destroyed. Defaults to 600 seconds if not specified - */ - timeout_seconds?: number; - - /** - * Initial browser window size in pixels with optional refresh rate. If omitted, - * image defaults apply (1920x1080@25). Only specific viewport configurations are - * supported. The server will reject unsupported combinations. Supported - * resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25, 1440x900@25, - * 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will be - * automatically determined from the width and height if they match a supported - * configuration exactly. Note: Higher resolutions may affect the responsiveness of - * live view browser - */ - viewport?: Shared.BrowserViewport; -} - -/** - * Parameters for updating a browser pool. All browsers in the pool will be created - * with the same configuration. - */ -export interface BrowserPoolUpdateRequest extends BrowserPoolRequest { - /** - * Whether to discard all idle browsers and rebuild the pool immediately. Defaults - * to false. + * Configuration used to create all browsers in this pool */ - discard_all_idle?: boolean; + export interface BrowserPoolConfig { + /** + * Number of browsers to create in the pool + */ + size: number; + + /** + * List of browser extensions to load into the session. Provide each by id or name. + */ + extensions?: Array; + + /** + * Percentage of the pool to fill per minute. Defaults to 10%. + */ + fill_rate_per_minute?: number; + + /** + * If true, launches the browser using a headless image. Defaults to false. + */ + headless?: boolean; + + /** + * If true, launches the browser in kiosk mode to hide address bar and tabs in live + * view. + */ + kiosk_mode?: boolean; + + /** + * Optional name for the browser pool. Must be unique within the organization. + */ + name?: string; + + /** + * Profile selection for the browser session. Provide either id or name. If + * specified, the matching profile will be loaded into the browser session. + * Profiles must be created beforehand. + */ + profile?: Shared.BrowserProfile; + + /** + * Optional proxy to associate to the browser session. Must reference a proxy + * belonging to the caller's org. + */ + proxy_id?: string; + + /** + * If true, launches the browser in stealth mode to reduce detection by anti-bot + * mechanisms. + */ + stealth?: boolean; + + /** + * Default idle timeout in seconds for browsers acquired from this pool before they + * are destroyed. Defaults to 600 seconds if not specified + */ + timeout_seconds?: number; + + /** + * Initial browser window size in pixels with optional refresh rate. If omitted, + * image defaults apply (1920x1080@25). Only specific viewport configurations are + * supported. The server will reject unsupported combinations. Supported + * resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25, 1440x900@25, + * 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will be + * automatically determined from the width and height if they match a supported + * configuration exactly. Note: Higher resolutions may affect the responsiveness of + * live view browser + */ + viewport?: Shared.BrowserViewport; + } } export type BrowserPoolListResponse = Array; @@ -546,10 +507,6 @@ export interface BrowserPoolReleaseParams { export declare namespace BrowserPools { export { type BrowserPool as BrowserPool, - type BrowserPoolAcquireRequest as BrowserPoolAcquireRequest, - type BrowserPoolReleaseRequest as BrowserPoolReleaseRequest, - type BrowserPoolRequest as BrowserPoolRequest, - type BrowserPoolUpdateRequest as BrowserPoolUpdateRequest, type BrowserPoolListResponse as BrowserPoolListResponse, type BrowserPoolAcquireResponse as BrowserPoolAcquireResponse, type BrowserPoolCreateParams as BrowserPoolCreateParams, diff --git a/src/resources/index.ts b/src/resources/index.ts index c198953a..c7a0aa18 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -11,10 +11,6 @@ export { export { BrowserPools, type BrowserPool, - type BrowserPoolAcquireRequest, - type BrowserPoolReleaseRequest, - type BrowserPoolRequest, - type BrowserPoolUpdateRequest, type BrowserPoolListResponse, type BrowserPoolAcquireResponse, type BrowserPoolCreateParams, From 07840eabf237958bdedf8ed65c5cc193d591ed57 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 17 Dec 2025 23:34:10 +0000 Subject: [PATCH 235/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 97bce112..fc5553b0 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.23.0" + ".": "0.24.0" } diff --git a/package.json b/package.json index 5383c206..ce072cc5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.23.0", + "version": "0.24.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index d77fad47..7434729b 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.23.0'; // x-release-please-version +export const VERSION = '0.24.0'; // x-release-please-version From 759dc812f3d2914c53bcb37adc5135f9a637abb0 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 20 Dec 2025 00:26:36 +0000 Subject: [PATCH 236/551] feat: Enhance AuthAgentInvocation with step and last activity tracking --- .stats.yml | 4 ++-- src/resources/agents/auth/auth.ts | 11 ++++++++--- src/resources/agents/auth/invocations.ts | 9 +++++---- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/.stats.yml b/.stats.yml index 99bb6c41..91fb4072 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 89 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-13214b99e392aab631aa1ca99b6a51a58df81e34156d21b8d639bea779566123.yml -openapi_spec_hash: a88d175fc3980de3097ac1411d8dcbff +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-2cf104c4b88159c6a50713b019188f83983748b9cacec598089cf9068dc5b1cd.yml +openapi_spec_hash: 84ea30ae65ad7ebcc04d2f3907d1e73b config_hash: 179f33af31ece83563163d5b3d751d13 diff --git a/src/resources/agents/auth/auth.ts b/src/resources/agents/auth/auth.ts index 636dabab..4478e6b3 100644 --- a/src/resources/agents/auth/auth.ts +++ b/src/resources/agents/auth/auth.ts @@ -161,6 +161,11 @@ export interface AgentAuthInvocationResponse { */ status: 'IN_PROGRESS' | 'SUCCESS' | 'EXPIRED' | 'CANCELED'; + /** + * Current step in the invocation workflow + */ + step: 'initialized' | 'discovering' | 'awaiting_input' | 'submitting' | 'completed' | 'expired'; + /** * Target domain for authentication */ @@ -337,7 +342,7 @@ export namespace AuthAgentInvocationCreateResponse { /** * Indicates the agent is already authenticated and no invocation was created. */ - status: 'already_authenticated'; + status: 'ALREADY_AUTHENTICATED'; } /** @@ -367,7 +372,7 @@ export namespace AuthAgentInvocationCreateResponse { /** * Indicates an invocation was created. */ - status: 'invocation_created'; + status: 'INVOCATION_CREATED'; } } @@ -413,7 +418,7 @@ export interface ReauthResponse { /** * Result of the re-authentication attempt */ - status: 'reauth_started' | 'already_authenticated' | 'cannot_reauth'; + status: 'REAUTH_STARTED' | 'ALREADY_AUTHENTICATED' | 'CANNOT_REAUTH'; /** * ID of the re-auth invocation if one was created diff --git a/src/resources/agents/auth/invocations.ts b/src/resources/agents/auth/invocations.ts index 84e9cf7d..31781063 100644 --- a/src/resources/agents/auth/invocations.ts +++ b/src/resources/agents/auth/invocations.ts @@ -28,8 +28,8 @@ export class Invocations extends APIResource { } /** - * Returns invocation details including app_name and target_domain. Uses the JWT - * returned by the exchange endpoint, or standard API key or JWT authentication. + * Returns invocation details including status, app_name, and target_domain. + * Supports both API key and JWT (from exchange endpoint) authentication. * * @example * ```ts @@ -46,7 +46,7 @@ export class Invocations extends APIResource { /** * Inspects the target site to detect logged-in state or discover required fields. * Returns 200 with success: true when fields are found, or 4xx/5xx for failures. - * Requires the JWT returned by the exchange endpoint. + * Supports both API key and JWT (from exchange endpoint) authentication. * * @example * ```ts @@ -87,7 +87,8 @@ export class Invocations extends APIResource { /** * Submits field values for the discovered login form and may return additional - * auth fields or success. Requires the JWT returned by the exchange endpoint. + * auth fields or success. Supports both API key and JWT (from exchange endpoint) + * authentication. * * @example * ```ts From 72953e88d592479a863587748c868f7f605caa83 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 30 Dec 2025 21:51:18 +0000 Subject: [PATCH 237/551] feat(api): add health check endpoint for proxies --- .stats.yml | 8 +- api.md | 2 + src/client.ts | 2 + src/resources/index.ts | 1 + src/resources/proxies.ts | 228 ++++++++++++++++++++++++++++ tests/api-resources/proxies.test.ts | 12 ++ 6 files changed, 249 insertions(+), 4 deletions(-) diff --git a/.stats.yml b/.stats.yml index 91fb4072..579e071d 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 89 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-2cf104c4b88159c6a50713b019188f83983748b9cacec598089cf9068dc5b1cd.yml -openapi_spec_hash: 84ea30ae65ad7ebcc04d2f3907d1e73b -config_hash: 179f33af31ece83563163d5b3d751d13 +configured_endpoints: 90 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-20fac779e9e13dc9421e467be31dbf274c39072ba0c01528ba451b48698d43c1.yml +openapi_spec_hash: c3fc5784297ccc8f729326b62000d1f0 +config_hash: e47e015528251ee83e30367dbbb51044 diff --git a/api.md b/api.md index 4086b1a0..1cad769a 100644 --- a/api.md +++ b/api.md @@ -201,6 +201,7 @@ Types: - ProxyCreateResponse - ProxyRetrieveResponse - ProxyListResponse +- ProxyCheckResponse Methods: @@ -208,6 +209,7 @@ Methods: - client.proxies.retrieve(id) -> ProxyRetrieveResponse - client.proxies.list() -> ProxyListResponse - client.proxies.delete(id) -> void +- client.proxies.check(id) -> ProxyCheckResponse # Extensions diff --git a/src/client.ts b/src/client.ts index 97ab0dee..f7634a99 100644 --- a/src/client.ts +++ b/src/client.ts @@ -76,6 +76,7 @@ import { import { ProfileCreateParams, ProfileListResponse, Profiles } from './resources/profiles'; import { Proxies, + ProxyCheckResponse, ProxyCreateParams, ProxyCreateResponse, ProxyListResponse, @@ -927,6 +928,7 @@ export declare namespace Kernel { type ProxyCreateResponse as ProxyCreateResponse, type ProxyRetrieveResponse as ProxyRetrieveResponse, type ProxyListResponse as ProxyListResponse, + type ProxyCheckResponse as ProxyCheckResponse, type ProxyCreateParams as ProxyCreateParams, }; diff --git a/src/resources/index.ts b/src/resources/index.ts index c7a0aa18..b626b9ec 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -81,5 +81,6 @@ export { type ProxyCreateResponse, type ProxyRetrieveResponse, type ProxyListResponse, + type ProxyCheckResponse, type ProxyCreateParams, } from './proxies'; diff --git a/src/resources/proxies.ts b/src/resources/proxies.ts index 7c409f5e..a8040b1f 100644 --- a/src/resources/proxies.ts +++ b/src/resources/proxies.ts @@ -37,6 +37,13 @@ export class Proxies extends APIResource { headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), }); } + + /** + * Run a health check on the proxy to verify it's working. + */ + check(id: string, options?: RequestOptions): APIPromise { + return this._client.post(path`/proxies/${id}/check`, options); + } } /** @@ -703,6 +710,226 @@ export namespace ProxyListResponse { } } +/** + * Configuration for routing traffic through a proxy. + */ +export interface ProxyCheckResponse { + /** + * Proxy type to use. In terms of quality for avoiding bot-detection, from best to + * worst: `mobile` > `residential` > `isp` > `datacenter`. + */ + type: 'datacenter' | 'isp' | 'residential' | 'mobile' | 'custom'; + + id?: string; + + /** + * Configuration specific to the selected proxy `type`. + */ + config?: + | ProxyCheckResponse.DatacenterProxyConfig + | ProxyCheckResponse.IspProxyConfig + | ProxyCheckResponse.ResidentialProxyConfig + | ProxyCheckResponse.MobileProxyConfig + | ProxyCheckResponse.CustomProxyConfig; + + /** + * Timestamp of the last health check performed on this proxy. + */ + last_checked?: string; + + /** + * Readable name of the proxy. + */ + name?: string; + + /** + * Protocol to use for the proxy connection. + */ + protocol?: 'http' | 'https'; + + /** + * Current health status of the proxy. + */ + status?: 'available' | 'unavailable'; +} + +export namespace ProxyCheckResponse { + /** + * Configuration for a datacenter proxy. + */ + export interface DatacenterProxyConfig { + /** + * ISO 3166 country code. Defaults to US if not provided. + */ + country?: string; + } + + /** + * Configuration for an ISP proxy. + */ + export interface IspProxyConfig { + /** + * ISO 3166 country code. Defaults to US if not provided. + */ + country?: string; + } + + /** + * Configuration for residential proxies. + */ + export interface ResidentialProxyConfig { + /** + * Autonomous system number. See https://bgp.potaroo.net/cidr/autnums.html + */ + asn?: string; + + /** + * City name (no spaces, e.g. `sanfrancisco`). If provided, `country` must also be + * provided. + */ + city?: string; + + /** + * ISO 3166 country code. + */ + country?: string; + + /** + * @deprecated Operating system of the residential device. + */ + os?: 'windows' | 'macos' | 'android'; + + /** + * Two-letter state code. + */ + state?: string; + + /** + * US ZIP code. + */ + zip?: string; + } + + /** + * Configuration for mobile proxies. + */ + export interface MobileProxyConfig { + /** + * Autonomous system number. See https://bgp.potaroo.net/cidr/autnums.html + */ + asn?: string; + + /** + * Mobile carrier. + */ + carrier?: + | 'a1' + | 'aircel' + | 'airtel' + | 'att' + | 'celcom' + | 'chinamobile' + | 'claro' + | 'comcast' + | 'cox' + | 'digi' + | 'dt' + | 'docomo' + | 'dtac' + | 'etisalat' + | 'idea' + | 'kyivstar' + | 'meo' + | 'megafon' + | 'mtn' + | 'mtnza' + | 'mts' + | 'optus' + | 'orange' + | 'qwest' + | 'reliance_jio' + | 'robi' + | 'sprint' + | 'telefonica' + | 'telstra' + | 'tmobile' + | 'tigo' + | 'tim' + | 'verizon' + | 'vimpelcom' + | 'vodacomza' + | 'vodafone' + | 'vivo' + | 'zain' + | 'vivabo' + | 'telenormyanmar' + | 'kcelljsc' + | 'swisscom' + | 'singtel' + | 'asiacell' + | 'windit' + | 'cellc' + | 'ooredoo' + | 'drei' + | 'umobile' + | 'cableone' + | 'proximus' + | 'tele2' + | 'mobitel' + | 'o2' + | 'bouygues' + | 'free' + | 'sfr' + | 'digicel'; + + /** + * City name (no spaces, e.g. `sanfrancisco`). If provided, `country` must also be + * provided. + */ + city?: string; + + /** + * ISO 3166 country code + */ + country?: string; + + /** + * Two-letter state code. + */ + state?: string; + + /** + * US ZIP code. + */ + zip?: string; + } + + /** + * Configuration for a custom proxy (e.g., private proxy server). + */ + export interface CustomProxyConfig { + /** + * Proxy host address or IP. + */ + host: string; + + /** + * Proxy port. + */ + port: number; + + /** + * Whether the proxy has a password. + */ + has_password?: boolean; + + /** + * Username for proxy authentication. + */ + username?: string; + } +} + export interface ProxyCreateParams { /** * Proxy type to use. In terms of quality for avoiding bot-detection, from best to @@ -913,6 +1140,7 @@ export declare namespace Proxies { type ProxyCreateResponse as ProxyCreateResponse, type ProxyRetrieveResponse as ProxyRetrieveResponse, type ProxyListResponse as ProxyListResponse, + type ProxyCheckResponse as ProxyCheckResponse, type ProxyCreateParams as ProxyCreateParams, }; } diff --git a/tests/api-resources/proxies.test.ts b/tests/api-resources/proxies.test.ts index ebc101ad..1086c4fe 100644 --- a/tests/api-resources/proxies.test.ts +++ b/tests/api-resources/proxies.test.ts @@ -65,4 +65,16 @@ describe('resource proxies', () => { expect(dataAndResponse.data).toBe(response); expect(dataAndResponse.response).toBe(rawResponse); }); + + // Prism tests are disabled + test.skip('check', async () => { + const responsePromise = client.proxies.check('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); + }); }); From d3a97df2b6ff395429e93b4501d15c5b31fbba57 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 6 Jan 2026 03:49:42 +0000 Subject: [PATCH 238/551] chore(internal): codegen related update --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index b32a077a..3b7d20d9 100644 --- a/LICENSE +++ b/LICENSE @@ -186,7 +186,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright 2025 Kernel + Copyright 2026 Kernel Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. From dcec7d3a0ec6913f3ce146ea62de22847ec9e036 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 7 Jan 2026 03:56:40 +0000 Subject: [PATCH 239/551] chore: break long lines in snippets into multiline --- README.md | 9 ++- tests/api-resources/agents/auth/auth.test.ts | 7 +- tests/api-resources/apps.test.ts | 7 +- tests/api-resources/browser-pools.test.ts | 24 +++++-- tests/api-resources/browsers/browsers.test.ts | 18 ++++- tests/api-resources/browsers/computer.test.ts | 15 +++- tests/api-resources/credentials.test.ts | 6 +- tests/api-resources/deployments.test.ts | 6 +- tests/index.test.ts | 72 +++++++++++++++---- 9 files changed, 137 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index 3007e652..586ba14c 100644 --- a/README.md +++ b/README.md @@ -163,7 +163,10 @@ You can use the `for await … of` syntax to iterate through items across all pa async function fetchAllDeploymentListResponses(params) { const allDeploymentListResponses = []; // Automatically fetches more pages as needed. - for await (const deploymentListResponse of client.deployments.list({ app_name: 'YOUR_APP', limit: 2 })) { + for await (const deploymentListResponse of client.deployments.list({ + app_name: 'YOUR_APP', + limit: 2, + })) { allDeploymentListResponses.push(deploymentListResponse); } return allDeploymentListResponses; @@ -203,7 +206,9 @@ const response = await client.browsers.create({ stealth: true }).asResponse(); console.log(response.headers.get('X-My-Header')); console.log(response.statusText); // access the underlying Response object -const { data: browser, response: raw } = await client.browsers.create({ stealth: true }).withResponse(); +const { data: browser, response: raw } = await client.browsers + .create({ stealth: true }) + .withResponse(); console.log(raw.headers.get('X-My-Header')); console.log(browser.session_id); ``` diff --git a/tests/api-resources/agents/auth/auth.test.ts b/tests/api-resources/agents/auth/auth.test.ts index 1882e825..8729d4f0 100644 --- a/tests/api-resources/agents/auth/auth.test.ts +++ b/tests/api-resources/agents/auth/auth.test.ts @@ -63,7 +63,12 @@ describe('resource auth', () => { // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error await expect( client.agents.auth.list( - { limit: 100, offset: 0, profile_name: 'profile_name', target_domain: 'target_domain' }, + { + limit: 100, + offset: 0, + profile_name: 'profile_name', + target_domain: 'target_domain', + }, { path: '/_stainless_unknown_path' }, ), ).rejects.toThrow(Kernel.NotFoundError); diff --git a/tests/api-resources/apps.test.ts b/tests/api-resources/apps.test.ts index 85debc71..d1a35f28 100644 --- a/tests/api-resources/apps.test.ts +++ b/tests/api-resources/apps.test.ts @@ -25,7 +25,12 @@ describe('resource apps', () => { // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error await expect( client.apps.list( - { app_name: 'app_name', limit: 1, offset: 0, version: 'version' }, + { + app_name: 'app_name', + limit: 1, + offset: 0, + version: 'version', + }, { path: '/_stainless_unknown_path' }, ), ).rejects.toThrow(Kernel.NotFoundError); diff --git a/tests/api-resources/browser-pools.test.ts b/tests/api-resources/browser-pools.test.ts index 2fdc93e3..97737bbb 100644 --- a/tests/api-resources/browser-pools.test.ts +++ b/tests/api-resources/browser-pools.test.ts @@ -29,11 +29,19 @@ describe('resource browserPools', () => { headless: false, kiosk_mode: true, name: 'my-pool', - profile: { id: 'id', name: 'name', save_changes: true }, + profile: { + id: 'id', + name: 'name', + save_changes: true, + }, proxy_id: 'proxy_id', stealth: true, timeout_seconds: 60, - viewport: { height: 800, width: 1280, refresh_rate: 60 }, + viewport: { + height: 800, + width: 1280, + refresh_rate: 60, + }, }); }); @@ -71,11 +79,19 @@ describe('resource browserPools', () => { headless: false, kiosk_mode: true, name: 'my-pool', - profile: { id: 'id', name: 'name', save_changes: true }, + profile: { + id: 'id', + name: 'name', + save_changes: true, + }, proxy_id: 'proxy_id', stealth: true, timeout_seconds: 60, - viewport: { height: 800, width: 1280, refresh_rate: 60 }, + viewport: { + height: 800, + width: 1280, + refresh_rate: 60, + }, }); }); diff --git a/tests/api-resources/browsers/browsers.test.ts b/tests/api-resources/browsers/browsers.test.ts index c44ac77a..5b315b4e 100644 --- a/tests/api-resources/browsers/browsers.test.ts +++ b/tests/api-resources/browsers/browsers.test.ts @@ -31,11 +31,19 @@ describe('resource browsers', () => { invocation_id: 'rr33xuugxj9h0bkf1rdt2bet', kiosk_mode: true, persistence: { id: 'my-awesome-browser-for-user-1234' }, - profile: { id: 'id', name: 'name', save_changes: true }, + profile: { + id: 'id', + name: 'name', + save_changes: true, + }, proxy_id: 'proxy_id', stealth: true, timeout_seconds: 10, - viewport: { height: 800, width: 1280, refresh_rate: 60 }, + viewport: { + height: 800, + width: 1280, + refresh_rate: 60, + }, }, { path: '/_stainless_unknown_path' }, ), @@ -71,7 +79,11 @@ describe('resource browsers', () => { // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error await expect( client.browsers.list( - { include_deleted: true, limit: 1, offset: 0 }, + { + include_deleted: true, + limit: 1, + offset: 0, + }, { path: '/_stainless_unknown_path' }, ), ).rejects.toThrow(Kernel.NotFoundError); diff --git a/tests/api-resources/browsers/computer.test.ts b/tests/api-resources/browsers/computer.test.ts index eb938fd2..b95f0fa7 100644 --- a/tests/api-resources/browsers/computer.test.ts +++ b/tests/api-resources/browsers/computer.test.ts @@ -13,7 +13,14 @@ describe('resource computer', () => { await expect( client.browsers.computer.captureScreenshot( 'id', - { region: { height: 0, width: 0, x: 0, y: 0 } }, + { + region: { + height: 0, + width: 0, + x: 0, + y: 0, + }, + }, { path: '/_stainless_unknown_path' }, ), ).rejects.toThrow(Kernel.NotFoundError); @@ -89,7 +96,11 @@ describe('resource computer', () => { // Prism tests are disabled test.skip('moveMouse: required and optional params', async () => { - const response = await client.browsers.computer.moveMouse('id', { x: 0, y: 0, hold_keys: ['string'] }); + const response = await client.browsers.computer.moveMouse('id', { + x: 0, + y: 0, + hold_keys: ['string'], + }); }); // Prism tests are disabled diff --git a/tests/api-resources/credentials.test.ts b/tests/api-resources/credentials.test.ts index eaf6c337..69fd93e3 100644 --- a/tests/api-resources/credentials.test.ts +++ b/tests/api-resources/credentials.test.ts @@ -74,7 +74,11 @@ describe('resource credentials', () => { // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error await expect( client.credentials.list( - { domain: 'domain', limit: 100, offset: 0 }, + { + domain: 'domain', + limit: 100, + offset: 0, + }, { path: '/_stainless_unknown_path' }, ), ).rejects.toThrow(Kernel.NotFoundError); diff --git a/tests/api-resources/deployments.test.ts b/tests/api-resources/deployments.test.ts index 12d3bb7b..b3f0c201 100644 --- a/tests/api-resources/deployments.test.ts +++ b/tests/api-resources/deployments.test.ts @@ -49,7 +49,11 @@ describe('resource deployments', () => { // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error await expect( client.deployments.list( - { app_name: 'app_name', limit: 1, offset: 0 }, + { + app_name: 'app_name', + limit: 1, + offset: 0, + }, { path: '/_stainless_unknown_path' }, ), ).rejects.toThrow(Kernel.NotFoundError); diff --git a/tests/index.test.ts b/tests/index.test.ts index 68b144c9..90d04c42 100644 --- a/tests/index.test.ts +++ b/tests/index.test.ts @@ -87,7 +87,11 @@ describe('instantiate client', () => { error: jest.fn(), }; - const client = new Kernel({ logger: logger, logLevel: 'debug', apiKey: 'My API Key' }); + const client = new Kernel({ + logger: logger, + logLevel: 'debug', + apiKey: 'My API Key', + }); await forceAPIResponseForClient(client); expect(debugMock).toHaveBeenCalled(); @@ -107,7 +111,11 @@ describe('instantiate client', () => { error: jest.fn(), }; - const client = new Kernel({ logger: logger, logLevel: 'info', apiKey: 'My API Key' }); + const client = new Kernel({ + logger: logger, + logLevel: 'info', + apiKey: 'My API Key', + }); await forceAPIResponseForClient(client); expect(debugMock).not.toHaveBeenCalled(); @@ -157,7 +165,11 @@ describe('instantiate client', () => { }; process.env['KERNEL_LOG'] = 'debug'; - const client = new Kernel({ logger: logger, logLevel: 'off', apiKey: 'My API Key' }); + const client = new Kernel({ + logger: logger, + logLevel: 'off', + apiKey: 'My API Key', + }); await forceAPIResponseForClient(client); expect(debugMock).not.toHaveBeenCalled(); @@ -173,7 +185,11 @@ describe('instantiate client', () => { }; process.env['KERNEL_LOG'] = 'not a log level'; - const client = new Kernel({ logger: logger, logLevel: 'debug', apiKey: 'My API Key' }); + const client = new Kernel({ + logger: logger, + logLevel: 'debug', + apiKey: 'My API Key', + }); expect(client.logLevel).toBe('debug'); expect(warnMock).not.toHaveBeenCalled(); }); @@ -267,7 +283,11 @@ describe('instantiate client', () => { return new Response(JSON.stringify({}), { headers: { 'Content-Type': 'application/json' } }); }; - const client = new Kernel({ baseURL: 'http://localhost:5000/', apiKey: 'My API Key', fetch: testFetch }); + const client = new Kernel({ + baseURL: 'http://localhost:5000/', + apiKey: 'My API Key', + fetch: testFetch, + }); await client.patch('/foo'); expect(capturedRequest?.method).toEqual('PATCH'); @@ -320,7 +340,11 @@ describe('instantiate client', () => { `"Ambiguous URL; The \`baseURL\` option (or KERNEL_BASE_URL env var) and the \`environment\` option are given. If you want to use the environment you must pass baseURL: null"`, ); - const client = new Kernel({ apiKey: 'My API Key', baseURL: null, environment: 'production' }); + const client = new Kernel({ + apiKey: 'My API Key', + baseURL: null, + environment: 'production', + }); expect(client.baseURL).toEqual('https://api.onkernel.com/'); }); @@ -358,7 +382,11 @@ describe('instantiate client', () => { describe('withOptions', () => { test('creates a new client with overridden options', async () => { - const client = new Kernel({ baseURL: 'http://localhost:5000/', maxRetries: 3, apiKey: 'My API Key' }); + const client = new Kernel({ + baseURL: 'http://localhost:5000/', + maxRetries: 3, + apiKey: 'My API Key', + }); const newClient = client.withOptions({ maxRetries: 5, @@ -398,7 +426,11 @@ describe('instantiate client', () => { }); test('respects runtime property changes when creating new client', () => { - const client = new Kernel({ baseURL: 'http://localhost:5000/', timeout: 1000, apiKey: 'My API Key' }); + const client = new Kernel({ + baseURL: 'http://localhost:5000/', + timeout: 1000, + apiKey: 'My API Key', + }); // Modify the client properties directly after creation client.baseURL = 'http://localhost:6000/'; @@ -544,7 +576,11 @@ describe('retries', () => { return new Response(JSON.stringify({ a: 1 }), { headers: { 'Content-Type': 'application/json' } }); }; - const client = new Kernel({ apiKey: 'My API Key', timeout: 10, fetch: testFetch }); + const client = new Kernel({ + apiKey: 'My API Key', + timeout: 10, + fetch: testFetch, + }); expect(await client.request({ path: '/foo', method: 'get' })).toEqual({ a: 1 }); expect(count).toEqual(2); @@ -574,7 +610,11 @@ describe('retries', () => { return new Response(JSON.stringify({ a: 1 }), { headers: { 'Content-Type': 'application/json' } }); }; - const client = new Kernel({ apiKey: 'My API Key', fetch: testFetch, maxRetries: 4 }); + const client = new Kernel({ + apiKey: 'My API Key', + fetch: testFetch, + maxRetries: 4, + }); expect(await client.request({ path: '/foo', method: 'get' })).toEqual({ a: 1 }); @@ -598,7 +638,11 @@ describe('retries', () => { capturedRequest = init; return new Response(JSON.stringify({ a: 1 }), { headers: { 'Content-Type': 'application/json' } }); }; - const client = new Kernel({ apiKey: 'My API Key', fetch: testFetch, maxRetries: 4 }); + const client = new Kernel({ + apiKey: 'My API Key', + fetch: testFetch, + maxRetries: 4, + }); expect( await client.request({ @@ -660,7 +704,11 @@ describe('retries', () => { capturedRequest = init; return new Response(JSON.stringify({ a: 1 }), { headers: { 'Content-Type': 'application/json' } }); }; - const client = new Kernel({ apiKey: 'My API Key', fetch: testFetch, maxRetries: 4 }); + const client = new Kernel({ + apiKey: 'My API Key', + fetch: testFetch, + maxRetries: 4, + }); expect( await client.request({ From 135d684b2d5ceb031ac48982565553b6b030de6b Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 7 Jan 2026 04:53:21 +0000 Subject: [PATCH 240/551] feat(auth): add auto_login credential flow --- .stats.yml | 8 +- api.md | 12 +- src/client.ts | 2 + src/resources/agents/agents.ts | 4 - src/resources/agents/auth/auth.ts | 260 ++++++++---------- src/resources/agents/auth/index.ts | 3 - src/resources/agents/auth/invocations.ts | 61 ++-- src/resources/agents/index.ts | 2 - src/resources/credentials.ts | 145 ++++++++-- src/resources/index.ts | 1 + tests/api-resources/agents/auth/auth.test.ts | 22 +- .../agents/auth/invocations.test.ts | 24 -- tests/api-resources/credentials.test.ts | 20 +- 13 files changed, 295 insertions(+), 269 deletions(-) diff --git a/.stats.yml b/.stats.yml index 579e071d..434275ee 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 90 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-20fac779e9e13dc9421e467be31dbf274c39072ba0c01528ba451b48698d43c1.yml -openapi_spec_hash: c3fc5784297ccc8f729326b62000d1f0 -config_hash: e47e015528251ee83e30367dbbb51044 +configured_endpoints: 89 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-8d66dbedea5b240936b338809f272568ca84a452fc13dbda835479f2ec068b41.yml +openapi_spec_hash: 7c499bfce2e996f1fff5e7791cea390e +config_hash: fcc2db3ed48ab4e8d1b588d31d394a23 diff --git a/api.md b/api.md index 1cad769a..8d44e74a 100644 --- a/api.md +++ b/api.md @@ -251,7 +251,6 @@ Methods: Types: -- AgentAuthDiscoverResponse - AgentAuthInvocationResponse - AgentAuthSubmitResponse - AuthAgent @@ -259,7 +258,6 @@ Types: - AuthAgentInvocationCreateRequest - AuthAgentInvocationCreateResponse - DiscoveredField -- ReauthResponse Methods: @@ -267,7 +265,6 @@ Methods: - client.agents.auth.retrieve(id) -> AuthAgent - client.agents.auth.list({ ...params }) -> AuthAgentsOffsetPagination - client.agents.auth.delete(id) -> void -- client.agents.auth.reauth(id) -> ReauthResponse ### Invocations @@ -279,7 +276,6 @@ Methods: - client.agents.auth.invocations.create({ ...params }) -> AuthAgentInvocationCreateResponse - client.agents.auth.invocations.retrieve(invocationID) -> AgentAuthInvocationResponse -- client.agents.auth.invocations.discover(invocationID, { ...params }) -> AgentAuthDiscoverResponse - client.agents.auth.invocations.exchange(invocationID, { ...params }) -> InvocationExchangeResponse - client.agents.auth.invocations.submit(invocationID, { ...params }) -> AgentAuthSubmitResponse @@ -290,11 +286,13 @@ Types: - CreateCredentialRequest - Credential - UpdateCredentialRequest +- CredentialTotpCodeResponse Methods: - client.credentials.create({ ...params }) -> Credential -- client.credentials.retrieve(id) -> Credential -- client.credentials.update(id, { ...params }) -> Credential +- client.credentials.retrieve(idOrName) -> Credential +- client.credentials.update(idOrName, { ...params }) -> Credential - client.credentials.list({ ...params }) -> CredentialsOffsetPagination -- client.credentials.delete(id) -> void +- client.credentials.delete(idOrName) -> void +- client.credentials.totpCode(idOrName) -> CredentialTotpCodeResponse diff --git a/src/client.ts b/src/client.ts index f7634a99..050b24ee 100644 --- a/src/client.ts +++ b/src/client.ts @@ -35,6 +35,7 @@ import { Credential, CredentialCreateParams, CredentialListParams, + CredentialTotpCodeResponse, CredentialUpdateParams, Credentials, CredentialsOffsetPagination, @@ -959,6 +960,7 @@ export declare namespace Kernel { type CreateCredentialRequest as CreateCredentialRequest, type Credential as Credential, type UpdateCredentialRequest as UpdateCredentialRequest, + type CredentialTotpCodeResponse as CredentialTotpCodeResponse, type CredentialsOffsetPagination as CredentialsOffsetPagination, type CredentialCreateParams as CredentialCreateParams, type CredentialUpdateParams as CredentialUpdateParams, diff --git a/src/resources/agents/agents.ts b/src/resources/agents/agents.ts index cb213145..dd0955e8 100644 --- a/src/resources/agents/agents.ts +++ b/src/resources/agents/agents.ts @@ -3,7 +3,6 @@ import { APIResource } from '../../core/resource'; import * as AuthAPI from './auth/auth'; import { - AgentAuthDiscoverResponse, AgentAuthInvocationResponse, AgentAuthSubmitResponse, Auth, @@ -15,7 +14,6 @@ import { AuthCreateParams, AuthListParams, DiscoveredField, - ReauthResponse, } from './auth/auth'; export class Agents extends APIResource { @@ -27,7 +25,6 @@ Agents.Auth = Auth; export declare namespace Agents { export { Auth as Auth, - type AgentAuthDiscoverResponse as AgentAuthDiscoverResponse, type AgentAuthInvocationResponse as AgentAuthInvocationResponse, type AgentAuthSubmitResponse as AgentAuthSubmitResponse, type AuthAgent as AuthAgent, @@ -35,7 +32,6 @@ export declare namespace Agents { type AuthAgentInvocationCreateRequest as AuthAgentInvocationCreateRequest, type AuthAgentInvocationCreateResponse as AuthAgentInvocationCreateResponse, type DiscoveredField as DiscoveredField, - type ReauthResponse as ReauthResponse, type AuthAgentsOffsetPagination as AuthAgentsOffsetPagination, type AuthCreateParams as AuthCreateParams, type AuthListParams as AuthListParams, diff --git a/src/resources/agents/auth/auth.ts b/src/resources/agents/auth/auth.ts index 4478e6b3..6e9372e4 100644 --- a/src/resources/agents/auth/auth.ts +++ b/src/resources/agents/auth/auth.ts @@ -4,7 +4,6 @@ import { APIResource } from '../../../core/resource'; import * as InvocationsAPI from './invocations'; import { InvocationCreateParams, - InvocationDiscoverParams, InvocationExchangeParams, InvocationExchangeResponse, InvocationSubmitParams, @@ -28,8 +27,8 @@ export class Auth extends APIResource { * @example * ```ts * const authAgent = await client.agents.auth.create({ + * domain: 'netflix.com', * profile_name: 'user-123', - * target_domain: 'netflix.com', * }); * ``` */ @@ -51,7 +50,7 @@ export class Auth extends APIResource { } /** - * List auth agents with optional filters for profile_name and target_domain. + * List auth agents with optional filters for profile_name and domain. * * @example * ```ts @@ -86,62 +85,10 @@ export class Auth extends APIResource { headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), }); } - - /** - * Triggers automatic re-authentication for an auth agent using stored credentials. - * Requires the auth agent to have a linked credential, stored selectors, and - * login_url. Returns immediately with status indicating whether re-auth was - * started. - * - * @example - * ```ts - * const reauthResponse = await client.agents.auth.reauth( - * 'id', - * ); - * ``` - */ - reauth(id: string, options?: RequestOptions): APIPromise { - return this._client.post(path`/agents/auth/${id}/reauth`, options); - } } export type AuthAgentsOffsetPagination = OffsetPagination; -/** - * Response from discover endpoint matching AuthBlueprint schema - */ -export interface AgentAuthDiscoverResponse { - /** - * Whether discovery succeeded - */ - success: boolean; - - /** - * Error message if discovery failed - */ - error_message?: string; - - /** - * Discovered form fields (present when success is true) - */ - fields?: Array; - - /** - * Whether user is already logged in - */ - logged_in?: boolean; - - /** - * URL of the discovered login page - */ - login_url?: string; - - /** - * Title of the login page - */ - page_title?: string; -} - /** * Response from get invocation endpoint */ @@ -151,6 +98,11 @@ export interface AgentAuthInvocationResponse { */ app_name: string; + /** + * Domain for authentication + */ + domain: string; + /** * When the handoff code expires */ @@ -159,58 +111,91 @@ export interface AgentAuthInvocationResponse { /** * Invocation status */ - status: 'IN_PROGRESS' | 'SUCCESS' | 'EXPIRED' | 'CANCELED'; + status: 'IN_PROGRESS' | 'SUCCESS' | 'EXPIRED' | 'CANCELED' | 'FAILED'; /** * Current step in the invocation workflow */ - step: 'initialized' | 'discovering' | 'awaiting_input' | 'submitting' | 'completed' | 'expired'; + step: + | 'initialized' + | 'discovering' + | 'awaiting_input' + | 'awaiting_external_action' + | 'submitting' + | 'completed' + | 'expired'; /** - * Target domain for authentication + * The invocation type: + * + * - login: First-time authentication + * - reauth: Re-authentication for previously authenticated agents + * - auto_login: Legacy type (no longer created, kept for backward compatibility) */ - target_domain: string; -} + type: 'login' | 'auto_login' | 'reauth'; -/** - * Response from submit endpoint matching SubmitResult schema - */ -export interface AgentAuthSubmitResponse { /** - * Whether submission succeeded + * Error message explaining why the invocation failed (present when status=FAILED) */ - success: boolean; + error_message?: string | null; /** - * Additional fields needed (e.g., OTP) - present when needs_additional_auth is - * true + * Instructions for user when external action is required (present when + * step=awaiting_external_action) */ - additional_fields?: Array; + external_action_message?: string | null; /** - * App name (only present when logged_in is true) + * Browser live view URL for debugging the invocation */ - app_name?: string; + live_view_url?: string | null; /** - * Error message if submission failed + * Fields currently awaiting input (present when step=awaiting_input) */ - error_message?: string; + pending_fields?: Array | null; /** - * Whether user is now logged in + * SSO buttons available on the page (present when step=awaiting_input) */ - logged_in?: boolean; + pending_sso_buttons?: Array | null; /** - * Whether additional authentication fields are needed + * Names of fields that have been submitted (present when step=submitting or later) */ - needs_additional_auth?: boolean; + submitted_fields?: Array | null; +} + +export namespace AgentAuthInvocationResponse { + /** + * An SSO button for signing in with an external identity provider + */ + export interface PendingSSOButton { + /** + * Visible button text + */ + label: string; + + /** + * Identity provider name + */ + provider: string; + + /** + * XPath selector for the button + */ + selector: string; + } +} +/** + * Response from submit endpoint - returns immediately after submission is accepted + */ +export interface AgentAuthSubmitResponse { /** - * Target domain (only present when logged_in is true) + * Whether the submission was accepted for processing */ - target_domain?: string; + accepted: boolean; } /** @@ -238,6 +223,13 @@ export interface AuthAgent { */ status: 'AUTHENTICATED' | 'NEEDS_AUTH'; + /** + * Additional domains that are valid for this auth agent's authentication flow + * (besides the primary domain). Useful when login pages redirect to different + * domains. + */ + allowed_domains?: Array; + /** * Whether automatic re-authentication is possible (has credential_id, selectors, * and login_url) @@ -269,15 +261,22 @@ export interface AuthAgent { * Request to create or find an auth agent */ export interface AuthAgentCreateRequest { + /** + * Domain for authentication + */ + domain: string; + /** * Name of the profile to use for this auth agent */ profile_name: string; /** - * Target domain for authentication + * Additional domains that are valid for this auth agent's authentication flow + * (besides the primary domain). Useful when login pages redirect to different + * domains. */ - target_domain: string; + allowed_domains?: Array; /** * Optional name of an existing credential to use for this auth agent. If provided, @@ -328,52 +327,37 @@ export interface AuthAgentInvocationCreateRequest { } /** - * Response when the agent is already authenticated. + * Response from creating an invocation. Always returns an invocation_id. */ -export type AuthAgentInvocationCreateResponse = - | AuthAgentInvocationCreateResponse.AuthAgentAlreadyAuthenticated - | AuthAgentInvocationCreateResponse.AuthAgentInvocationCreated; - -export namespace AuthAgentInvocationCreateResponse { +export interface AuthAgentInvocationCreateResponse { /** - * Response when the agent is already authenticated. + * When the handoff code expires. */ - export interface AuthAgentAlreadyAuthenticated { - /** - * Indicates the agent is already authenticated and no invocation was created. - */ - status: 'ALREADY_AUTHENTICATED'; - } + expires_at: string; /** - * Response when a new invocation was created. + * One-time code for handoff. */ - export interface AuthAgentInvocationCreated { - /** - * When the handoff code expires. - */ - expires_at: string; + handoff_code: string; - /** - * One-time code for handoff. - */ - handoff_code: string; - - /** - * URL to redirect user to. - */ - hosted_url: string; + /** + * URL to redirect user to. + */ + hosted_url: string; - /** - * Unique identifier for the invocation. - */ - invocation_id: string; + /** + * Unique identifier for the invocation. + */ + invocation_id: string; - /** - * Indicates an invocation was created. - */ - status: 'INVOCATION_CREATED'; - } + /** + * The invocation type: + * + * - login: First-time authentication + * - reauth: Re-authentication for previously authenticated agents + * - auto_login: Legacy type (no longer created, kept for backward compatibility) + */ + type: 'login' | 'auto_login' | 'reauth'; } /** @@ -398,7 +382,7 @@ export interface DiscoveredField { /** * Field type */ - type: 'text' | 'email' | 'password' | 'tel' | 'number' | 'url' | 'code'; + type: 'text' | 'email' | 'password' | 'tel' | 'number' | 'url' | 'code' | 'totp'; /** * Field placeholder @@ -411,36 +395,23 @@ export interface DiscoveredField { required?: boolean; } -/** - * Response from triggering re-authentication - */ -export interface ReauthResponse { - /** - * Result of the re-authentication attempt - */ - status: 'REAUTH_STARTED' | 'ALREADY_AUTHENTICATED' | 'CANNOT_REAUTH'; - +export interface AuthCreateParams { /** - * ID of the re-auth invocation if one was created + * Domain for authentication */ - invocation_id?: string; + domain: string; - /** - * Human-readable description of the result - */ - message?: string; -} - -export interface AuthCreateParams { /** * Name of the profile to use for this auth agent */ profile_name: string; /** - * Target domain for authentication + * Additional domains that are valid for this auth agent's authentication flow + * (besides the primary domain). Useful when login pages redirect to different + * domains. */ - target_domain: string; + allowed_domains?: Array; /** * Optional name of an existing credential to use for this auth agent. If provided, @@ -475,21 +446,20 @@ export namespace AuthCreateParams { export interface AuthListParams extends OffsetPaginationParams { /** - * Filter by profile name + * Filter by domain */ - profile_name?: string; + domain?: string; /** - * Filter by target domain + * Filter by profile name */ - target_domain?: string; + profile_name?: string; } Auth.Invocations = Invocations; export declare namespace Auth { export { - type AgentAuthDiscoverResponse as AgentAuthDiscoverResponse, type AgentAuthInvocationResponse as AgentAuthInvocationResponse, type AgentAuthSubmitResponse as AgentAuthSubmitResponse, type AuthAgent as AuthAgent, @@ -497,7 +467,6 @@ export declare namespace Auth { type AuthAgentInvocationCreateRequest as AuthAgentInvocationCreateRequest, type AuthAgentInvocationCreateResponse as AuthAgentInvocationCreateResponse, type DiscoveredField as DiscoveredField, - type ReauthResponse as ReauthResponse, type AuthAgentsOffsetPagination as AuthAgentsOffsetPagination, type AuthCreateParams as AuthCreateParams, type AuthListParams as AuthListParams, @@ -507,7 +476,6 @@ export declare namespace Auth { Invocations as Invocations, type InvocationExchangeResponse as InvocationExchangeResponse, type InvocationCreateParams as InvocationCreateParams, - type InvocationDiscoverParams as InvocationDiscoverParams, type InvocationExchangeParams as InvocationExchangeParams, type InvocationSubmitParams as InvocationSubmitParams, }; diff --git a/src/resources/agents/auth/index.ts b/src/resources/agents/auth/index.ts index bf85b044..490ad25c 100644 --- a/src/resources/agents/auth/index.ts +++ b/src/resources/agents/auth/index.ts @@ -2,7 +2,6 @@ export { Auth, - type AgentAuthDiscoverResponse, type AgentAuthInvocationResponse, type AgentAuthSubmitResponse, type AuthAgent, @@ -10,7 +9,6 @@ export { type AuthAgentInvocationCreateRequest, type AuthAgentInvocationCreateResponse, type DiscoveredField, - type ReauthResponse, type AuthCreateParams, type AuthListParams, type AuthAgentsOffsetPagination, @@ -19,7 +17,6 @@ export { Invocations, type InvocationExchangeResponse, type InvocationCreateParams, - type InvocationDiscoverParams, type InvocationExchangeParams, type InvocationSubmitParams, } from './invocations'; diff --git a/src/resources/agents/auth/invocations.ts b/src/resources/agents/auth/invocations.ts index 31781063..94cefbd1 100644 --- a/src/resources/agents/auth/invocations.ts +++ b/src/resources/agents/auth/invocations.ts @@ -28,8 +28,8 @@ export class Invocations extends APIResource { } /** - * Returns invocation details including status, app_name, and target_domain. - * Supports both API key and JWT (from exchange endpoint) authentication. + * Returns invocation details including status, app_name, and domain. Supports both + * API key and JWT (from exchange endpoint) authentication. * * @example * ```ts @@ -43,27 +43,6 @@ export class Invocations extends APIResource { return this._client.get(path`/agents/auth/invocations/${invocationID}`, options); } - /** - * Inspects the target site to detect logged-in state or discover required fields. - * Returns 200 with success: true when fields are found, or 4xx/5xx for failures. - * Supports both API key and JWT (from exchange endpoint) authentication. - * - * @example - * ```ts - * const agentAuthDiscoverResponse = - * await client.agents.auth.invocations.discover( - * 'invocation_id', - * ); - * ``` - */ - discover( - invocationID: string, - body: InvocationDiscoverParams | null | undefined = {}, - options?: RequestOptions, - ): APIPromise { - return this._client.post(path`/agents/auth/invocations/${invocationID}/discover`, { body, ...options }); - } - /** * Validates the handoff code and returns a JWT token for subsequent requests. No * authentication required (the handoff code serves as the credential). @@ -86,9 +65,9 @@ export class Invocations extends APIResource { } /** - * Submits field values for the discovered login form and may return additional - * auth fields or success. Supports both API key and JWT (from exchange endpoint) - * authentication. + * Submits field values for the discovered login form. Returns immediately after + * submission is accepted. Poll the invocation endpoint to track progress and get + * results. * * @example * ```ts @@ -142,14 +121,6 @@ export interface InvocationCreateParams { save_credential_as?: string; } -export interface InvocationDiscoverParams { - /** - * Optional login page URL. If provided, will override the stored login URL for - * this discovery invocation and skip Phase 1 discovery. - */ - login_url?: string; -} - export interface InvocationExchangeParams { /** * Handoff code from start endpoint @@ -157,18 +128,28 @@ export interface InvocationExchangeParams { code: string; } -export interface InvocationSubmitParams { - /** - * Values for the discovered login fields - */ - field_values: { [key: string]: string }; +export type InvocationSubmitParams = InvocationSubmitParams.Variant0 | InvocationSubmitParams.Variant1; + +export declare namespace InvocationSubmitParams { + export interface Variant0 { + /** + * Values for the discovered login fields + */ + field_values: { [key: string]: string }; + } + + export interface Variant1 { + /** + * Selector of SSO button to click + */ + sso_button: string; + } } export declare namespace Invocations { export { type InvocationExchangeResponse as InvocationExchangeResponse, type InvocationCreateParams as InvocationCreateParams, - type InvocationDiscoverParams as InvocationDiscoverParams, type InvocationExchangeParams as InvocationExchangeParams, type InvocationSubmitParams as InvocationSubmitParams, }; diff --git a/src/resources/agents/index.ts b/src/resources/agents/index.ts index fbd90052..65bd5a46 100644 --- a/src/resources/agents/index.ts +++ b/src/resources/agents/index.ts @@ -3,7 +3,6 @@ export { Agents } from './agents'; export { Auth, - type AgentAuthDiscoverResponse, type AgentAuthInvocationResponse, type AgentAuthSubmitResponse, type AuthAgent, @@ -11,7 +10,6 @@ export { type AuthAgentInvocationCreateRequest, type AuthAgentInvocationCreateResponse, type DiscoveredField, - type ReauthResponse, type AuthCreateParams, type AuthListParams, type AuthAgentsOffsetPagination, diff --git a/src/resources/credentials.ts b/src/resources/credentials.ts index a90dea7a..2f384a7b 100644 --- a/src/resources/credentials.ts +++ b/src/resources/credentials.ts @@ -9,8 +9,7 @@ import { path } from '../internal/utils/path'; export class Credentials extends APIResource { /** - * Create a new credential for storing login information. Values are encrypted at - * rest. + * Create a new credential for storing login information. * * @example * ```ts @@ -29,27 +28,32 @@ export class Credentials extends APIResource { } /** - * Retrieve a credential by its ID. Credential values are not returned. + * Retrieve a credential by its ID or name. Credential values are not returned. * * @example * ```ts - * const credential = await client.credentials.retrieve('id'); + * const credential = await client.credentials.retrieve( + * 'id_or_name', + * ); * ``` */ - retrieve(id: string, options?: RequestOptions): APIPromise { - return this._client.get(path`/credentials/${id}`, options); + retrieve(idOrName: string, options?: RequestOptions): APIPromise { + return this._client.get(path`/credentials/${idOrName}`, options); } /** - * Update a credential's name or values. Values are encrypted at rest. + * Update a credential's name or values. When values are provided, they are merged + * with existing values (new keys are added, existing keys are overwritten). * * @example * ```ts - * const credential = await client.credentials.update('id'); + * const credential = await client.credentials.update( + * 'id_or_name', + * ); * ``` */ - update(id: string, body: CredentialUpdateParams, options?: RequestOptions): APIPromise { - return this._client.patch(path`/credentials/${id}`, { body, ...options }); + update(idOrName: string, body: CredentialUpdateParams, options?: RequestOptions): APIPromise { + return this._client.patch(path`/credentials/${idOrName}`, { body, ...options }); } /** @@ -72,19 +76,35 @@ export class Credentials extends APIResource { } /** - * Delete a credential by its ID. + * Delete a credential by its ID or name. * * @example * ```ts - * await client.credentials.delete('id'); + * await client.credentials.delete('id_or_name'); * ``` */ - delete(id: string, options?: RequestOptions): APIPromise { - return this._client.delete(path`/credentials/${id}`, { + delete(idOrName: string, options?: RequestOptions): APIPromise { + return this._client.delete(path`/credentials/${idOrName}`, { ...options, headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), }); } + + /** + * Returns the current 6-digit TOTP code for a credential with a configured + * totp_secret. Use this to complete 2FA setup on sites or when you need a fresh + * code. + * + * @example + * ```ts + * const response = await client.credentials.totpCode( + * 'id_or_name', + * ); + * ``` + */ + totpCode(idOrName: string, options?: RequestOptions): APIPromise { + return this._client.get(path`/credentials/${idOrName}/totp-code`, options); + } } export type CredentialsOffsetPagination = OffsetPagination; @@ -107,6 +127,20 @@ export interface CreateCredentialRequest { * Field name to value mapping (e.g., username, password) */ values: { [key: string]: string }; + + /** + * If set, indicates this credential should be used with the specified SSO provider + * (e.g., google, github, microsoft). When the target site has a matching SSO + * button, it will be clicked first before filling credential values on the + * identity provider's login page. + */ + sso_provider?: string; + + /** + * Base32-encoded TOTP secret for generating one-time passwords. Used for automatic + * 2FA during login. + */ + totp_secret?: string; } /** @@ -137,6 +171,30 @@ export interface Credential { * When the credential was last updated */ updated_at: string; + + /** + * Whether this credential has a TOTP secret configured for automatic 2FA + */ + has_totp_secret?: boolean; + + /** + * If set, indicates this credential should be used with the specified SSO provider + * (e.g., google, github, microsoft). When the target site has a matching SSO + * button, it will be clicked first before filling credential values on the + * identity provider's login page. + */ + sso_provider?: string | null; + + /** + * Current 6-digit TOTP code. Only included in create/update responses when + * totp_secret was just set. + */ + totp_code?: string; + + /** + * When the totp_code expires. Only included when totp_code is present. + */ + totp_code_expires_at?: string; } /** @@ -149,12 +207,36 @@ export interface UpdateCredentialRequest { name?: string; /** - * Field name to value mapping (e.g., username, password). Replaces all existing - * values. + * If set, indicates this credential should be used with the specified SSO + * provider. Set to empty string or null to remove. + */ + sso_provider?: string | null; + + /** + * Base32-encoded TOTP secret for generating one-time passwords. Spaces and + * formatting are automatically normalized. Set to empty string to remove. + */ + totp_secret?: string; + + /** + * Field name to value mapping. Values are merged with existing values (new keys + * added, existing keys overwritten). */ values?: { [key: string]: string }; } +export interface CredentialTotpCodeResponse { + /** + * Current 6-digit TOTP code + */ + code: string; + + /** + * When this code expires (ISO 8601 timestamp) + */ + expires_at: string; +} + export interface CredentialCreateParams { /** * Target domain this credential is for @@ -170,6 +252,20 @@ export interface CredentialCreateParams { * Field name to value mapping (e.g., username, password) */ values: { [key: string]: string }; + + /** + * If set, indicates this credential should be used with the specified SSO provider + * (e.g., google, github, microsoft). When the target site has a matching SSO + * button, it will be clicked first before filling credential values on the + * identity provider's login page. + */ + sso_provider?: string; + + /** + * Base32-encoded TOTP secret for generating one-time passwords. Used for automatic + * 2FA during login. + */ + totp_secret?: string; } export interface CredentialUpdateParams { @@ -179,8 +275,20 @@ export interface CredentialUpdateParams { name?: string; /** - * Field name to value mapping (e.g., username, password). Replaces all existing - * values. + * If set, indicates this credential should be used with the specified SSO + * provider. Set to empty string or null to remove. + */ + sso_provider?: string | null; + + /** + * Base32-encoded TOTP secret for generating one-time passwords. Spaces and + * formatting are automatically normalized. Set to empty string to remove. + */ + totp_secret?: string; + + /** + * Field name to value mapping. Values are merged with existing values (new keys + * added, existing keys overwritten). */ values?: { [key: string]: string }; } @@ -197,6 +305,7 @@ export declare namespace Credentials { type CreateCredentialRequest as CreateCredentialRequest, type Credential as Credential, type UpdateCredentialRequest as UpdateCredentialRequest, + type CredentialTotpCodeResponse as CredentialTotpCodeResponse, type CredentialsOffsetPagination as CredentialsOffsetPagination, type CredentialCreateParams as CredentialCreateParams, type CredentialUpdateParams as CredentialUpdateParams, diff --git a/src/resources/index.ts b/src/resources/index.ts index b626b9ec..f4877266 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -37,6 +37,7 @@ export { type CreateCredentialRequest, type Credential, type UpdateCredentialRequest, + type CredentialTotpCodeResponse, type CredentialCreateParams, type CredentialUpdateParams, type CredentialListParams, diff --git a/tests/api-resources/agents/auth/auth.test.ts b/tests/api-resources/agents/auth/auth.test.ts index 8729d4f0..1f8a9237 100644 --- a/tests/api-resources/agents/auth/auth.test.ts +++ b/tests/api-resources/agents/auth/auth.test.ts @@ -10,10 +10,7 @@ const client = new Kernel({ describe('resource auth', () => { // Prism tests are disabled test.skip('create: only required params', async () => { - const responsePromise = client.agents.auth.create({ - profile_name: 'user-123', - target_domain: 'netflix.com', - }); + const responsePromise = client.agents.auth.create({ domain: 'netflix.com', profile_name: 'user-123' }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -26,8 +23,9 @@ describe('resource auth', () => { // Prism tests are disabled test.skip('create: required and optional params', async () => { const response = await client.agents.auth.create({ + domain: 'netflix.com', profile_name: 'user-123', - target_domain: 'netflix.com', + allowed_domains: ['login.netflix.com', 'auth.netflix.com'], credential_name: 'my-netflix-login', login_url: 'https://netflix.com/login', proxy: { proxy_id: 'proxy_id' }, @@ -64,10 +62,10 @@ describe('resource auth', () => { await expect( client.agents.auth.list( { + domain: 'domain', limit: 100, offset: 0, profile_name: 'profile_name', - target_domain: 'target_domain', }, { path: '/_stainless_unknown_path' }, ), @@ -85,16 +83,4 @@ describe('resource auth', () => { expect(dataAndResponse.data).toBe(response); expect(dataAndResponse.response).toBe(rawResponse); }); - - // Prism tests are disabled - test.skip('reauth', async () => { - const responsePromise = client.agents.auth.reauth('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); - }); }); diff --git a/tests/api-resources/agents/auth/invocations.test.ts b/tests/api-resources/agents/auth/invocations.test.ts index fc178bbb..b30496c8 100644 --- a/tests/api-resources/agents/auth/invocations.test.ts +++ b/tests/api-resources/agents/auth/invocations.test.ts @@ -40,30 +40,6 @@ describe('resource invocations', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled - test.skip('discover', async () => { - const responsePromise = client.agents.auth.invocations.discover('invocation_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); - }); - - // Prism tests are disabled - test.skip('discover: 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.agents.auth.invocations.discover( - 'invocation_id', - { login_url: 'https://doordash.com/account/login' }, - { path: '/_stainless_unknown_path' }, - ), - ).rejects.toThrow(Kernel.NotFoundError); - }); - // Prism tests are disabled test.skip('exchange: only required params', async () => { const responsePromise = client.agents.auth.invocations.exchange('invocation_id', { code: 'abc123xyz' }); diff --git a/tests/api-resources/credentials.test.ts b/tests/api-resources/credentials.test.ts index 69fd93e3..d825b4e0 100644 --- a/tests/api-resources/credentials.test.ts +++ b/tests/api-resources/credentials.test.ts @@ -30,12 +30,14 @@ describe('resource credentials', () => { domain: 'netflix.com', name: 'my-netflix-login', values: { username: 'user@example.com', password: 'mysecretpassword' }, + sso_provider: 'google', + totp_secret: 'JBSWY3DPEHPK3PXP', }); }); // Prism tests are disabled test.skip('retrieve', async () => { - const responsePromise = client.credentials.retrieve('id'); + const responsePromise = client.credentials.retrieve('id_or_name'); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -47,7 +49,7 @@ describe('resource credentials', () => { // Prism tests are disabled test.skip('update', async () => { - const responsePromise = client.credentials.update('id', {}); + const responsePromise = client.credentials.update('id_or_name', {}); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -86,7 +88,19 @@ describe('resource credentials', () => { // Prism tests are disabled test.skip('delete', async () => { - const responsePromise = client.credentials.delete('id'); + const responsePromise = client.credentials.delete('id_or_name'); + 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); + }); + + // Prism tests are disabled + test.skip('totpCode', async () => { + const responsePromise = client.credentials.totpCode('id_or_name'); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; From dac6c846631a0a042dad9bba4ae1cb9f359548d4 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 7 Jan 2026 18:05:48 +0000 Subject: [PATCH 241/551] feat(api): update production repos --- .github/workflows/publish-npm.yml | 2 +- .github/workflows/release-doctor.yml | 2 +- .stats.yml | 2 +- CONTRIBUTING.md | 6 +++--- README.md | 2 +- package.json | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/publish-npm.yml b/.github/workflows/publish-npm.yml index 45c2cfde..9032e71c 100644 --- a/.github/workflows/publish-npm.yml +++ b/.github/workflows/publish-npm.yml @@ -1,6 +1,6 @@ # This workflow is triggered when a GitHub release is created. # It can also be run manually to re-publish to NPM in case it failed for some reason. -# You can run this workflow by navigating to https://www.github.com/onkernel/kernel-node-sdk/actions/workflows/publish-npm.yml +# You can run this workflow by navigating to https://www.github.com/kernel/kernel-node-sdk/actions/workflows/publish-npm.yml name: Publish NPM on: workflow_dispatch: diff --git a/.github/workflows/release-doctor.yml b/.github/workflows/release-doctor.yml index 9e9b38d1..8e587753 100644 --- a/.github/workflows/release-doctor.yml +++ b/.github/workflows/release-doctor.yml @@ -9,7 +9,7 @@ jobs: release_doctor: name: release doctor runs-on: ubuntu-latest - if: github.repository == 'onkernel/kernel-node-sdk' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch' || startsWith(github.head_ref, 'release-please') || github.head_ref == 'next') + if: github.repository == 'kernel/kernel-node-sdk' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch' || startsWith(github.head_ref, 'release-please') || github.head_ref == 'next') steps: - uses: actions/checkout@v4 diff --git a/.stats.yml b/.stats.yml index 434275ee..9ab4346b 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 89 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-8d66dbedea5b240936b338809f272568ca84a452fc13dbda835479f2ec068b41.yml openapi_spec_hash: 7c499bfce2e996f1fff5e7791cea390e -config_hash: fcc2db3ed48ab4e8d1b588d31d394a23 +config_hash: 2ee8c7057fa9b05cd0dabd23247c40ec diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 679eb772..30dc1266 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -42,14 +42,14 @@ If you’d like to use the repository from source, you can either install from g To install via git: ```sh -$ npm install git+ssh://git@github.com:onkernel/kernel-node-sdk.git +$ npm install git+ssh://git@github.com:kernel/kernel-node-sdk.git ``` Alternatively, to link a local copy of the repo: ```sh # Clone -$ git clone https://www.github.com/onkernel/kernel-node-sdk +$ git clone https://www.github.com/kernel/kernel-node-sdk $ cd kernel-node-sdk # With yarn @@ -99,7 +99,7 @@ the changes aren't made through the automated pipeline, you may want to make rel ### Publish with a GitHub workflow -You can release to package managers by using [the `Publish NPM` GitHub action](https://www.github.com/onkernel/kernel-node-sdk/actions/workflows/publish-npm.yml). This requires a setup organization or repository secret to be set up. +You can release to package managers by using [the `Publish NPM` GitHub action](https://www.github.com/kernel/kernel-node-sdk/actions/workflows/publish-npm.yml). This requires a setup organization or repository secret to be set up. ### Publish manually diff --git a/README.md b/README.md index 586ba14c..b5ae4926 100644 --- a/README.md +++ b/README.md @@ -400,7 +400,7 @@ This package generally follows [SemVer](https://semver.org/spec/v2.0.0.html) con We take backwards-compatibility seriously and work hard to ensure you can rely on a smooth upgrade experience. -We are keen for your feedback; please open an [issue](https://www.github.com/onkernel/kernel-node-sdk/issues) with questions, bugs, or suggestions. +We are keen for your feedback; please open an [issue](https://www.github.com/kernel/kernel-node-sdk/issues) with questions, bugs, or suggestions. ## Requirements diff --git a/package.json b/package.json index ce072cc5..a270b0ae 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "types": "dist/index.d.ts", "main": "dist/index.js", "type": "commonjs", - "repository": "github:onkernel/kernel-node-sdk", + "repository": "github:kernel/kernel-node-sdk", "license": "Apache-2.0", "packageManager": "yarn@1.22.22", "files": [ From fc2984b88a74ac5f4854f86f157e7a9ac9fc93de Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 13 Jan 2026 20:40:45 +0000 Subject: [PATCH 242/551] feat: add MFA options to agent authentication workflow --- .stats.yml | 6 ++-- CONTRIBUTING.md | 4 +-- README.md | 26 ++++++++-------- eslint.config.mjs | 2 +- jest.config.ts | 4 +-- package.json | 2 +- scripts/build | 6 ++-- src/client.ts | 6 ++-- src/resources/agents/auth/auth.ts | 31 +++++++++++++++++++ src/resources/agents/auth/invocations.ts | 12 ++++++- tests/api-resources/agents/auth/auth.test.ts | 2 +- .../agents/auth/invocations.test.ts | 2 +- tests/api-resources/apps.test.ts | 2 +- tests/api-resources/browser-pools.test.ts | 2 +- tests/api-resources/browsers/browsers.test.ts | 2 +- tests/api-resources/browsers/computer.test.ts | 2 +- tests/api-resources/browsers/fs/fs.test.ts | 2 +- tests/api-resources/browsers/fs/watch.test.ts | 2 +- tests/api-resources/browsers/logs.test.ts | 2 +- .../api-resources/browsers/playwright.test.ts | 2 +- tests/api-resources/browsers/process.test.ts | 2 +- tests/api-resources/browsers/replays.test.ts | 2 +- tests/api-resources/credentials.test.ts | 2 +- tests/api-resources/deployments.test.ts | 2 +- tests/api-resources/extensions.test.ts | 2 +- tests/api-resources/invocations.test.ts | 2 +- tests/api-resources/profiles.test.ts | 2 +- tests/api-resources/proxies.test.ts | 2 +- tests/base64.test.ts | 2 +- tests/buildHeaders.test.ts | 2 +- tests/form.test.ts | 4 +-- tests/index.test.ts | 12 +++---- tests/internal/decoders/line.test.ts | 2 +- tests/path.test.ts | 2 +- tests/streaming.test.ts | 4 +-- tests/stringifyQuery.test.ts | 2 +- tests/uploads.test.ts | 6 ++-- tsconfig.build.json | 4 +-- tsconfig.json | 4 +-- 39 files changed, 110 insertions(+), 69 deletions(-) diff --git a/.stats.yml b/.stats.yml index 9ab4346b..ce759c07 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 89 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-8d66dbedea5b240936b338809f272568ca84a452fc13dbda835479f2ec068b41.yml -openapi_spec_hash: 7c499bfce2e996f1fff5e7791cea390e -config_hash: 2ee8c7057fa9b05cd0dabd23247c40ec +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-8e4a29d23d2882fcb0864606091790fd58bffa4f5d5c8d081052b72ad47b215b.yml +openapi_spec_hash: fc82d930dad739ac01e3c2bddba7bf61 +config_hash: 3a5e36dfb245210cfd978f679b3641d2 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 30dc1266..6434ec2b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -55,12 +55,12 @@ $ cd kernel-node-sdk # With yarn $ yarn link $ cd ../my-package -$ yarn link @onkernel/sdk +$ yarn link @kernel/sdk # With pnpm $ pnpm link --global $ cd ../my-package -$ pnpm link -—global @onkernel/sdk +$ pnpm link -—global @kernel/sdk ``` ## Running tests diff --git a/README.md b/README.md index b5ae4926..17efd10f 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,17 @@ # Kernel TypeScript API Library -[![NPM version]()](https://npmjs.org/package/@onkernel/sdk) ![npm bundle size](https://img.shields.io/bundlephobia/minzip/@onkernel/sdk) +[![NPM version]()](https://npmjs.org/package/@kernel/sdk) ![npm bundle size](https://img.shields.io/bundlephobia/minzip/@kernel/sdk) This library provides convenient access to the Kernel REST API from server-side TypeScript or JavaScript. -The REST API documentation can be found on [docs.onkernel.com](https://docs.onkernel.com). The full API of this library can be found in [api.md](api.md). +The REST API documentation can be found on [docs.kernel.com](https://docs.kernel.com). The full API of this library can be found in [api.md](api.md). It is generated with [Stainless](https://www.stainless.com/). ## Installation ```sh -npm install @onkernel/sdk +npm install @kernel/sdk ``` ## Usage @@ -20,7 +20,7 @@ The full API of this library can be found in [api.md](api.md). ```js -import Kernel from '@onkernel/sdk'; +import Kernel from '@kernel/sdk'; const client = new Kernel({ apiKey: process.env['KERNEL_API_KEY'], // This is the default and can be omitted @@ -38,7 +38,7 @@ This library includes TypeScript definitions for all request params and response ```ts -import Kernel from '@onkernel/sdk'; +import Kernel from '@kernel/sdk'; const client = new Kernel({ apiKey: process.env['KERNEL_API_KEY'], // This is the default and can be omitted @@ -62,7 +62,7 @@ Request parameters that correspond to file uploads can be passed in many differe ```ts import fs from 'fs'; -import Kernel, { toFile } from '@onkernel/sdk'; +import Kernel, { toFile } from '@kernel/sdk'; const client = new Kernel(); @@ -227,7 +227,7 @@ The log level can be configured in two ways: 2. Using the `logLevel` client option (overrides the environment variable if set) ```ts -import Kernel from '@onkernel/sdk'; +import Kernel from '@kernel/sdk'; const client = new Kernel({ logLevel: 'debug', // Show all log messages @@ -255,7 +255,7 @@ When providing a custom logger, the `logLevel` option still controls which messa below the configured level will not be sent to your logger. ```ts -import Kernel from '@onkernel/sdk'; +import Kernel from '@kernel/sdk'; import pino from 'pino'; const logger = pino(); @@ -324,7 +324,7 @@ globalThis.fetch = fetch; Or pass it to the client: ```ts -import Kernel from '@onkernel/sdk'; +import Kernel from '@kernel/sdk'; import fetch from 'my-fetch'; const client = new Kernel({ fetch }); @@ -335,7 +335,7 @@ const client = new Kernel({ fetch }); If you want to set custom `fetch` options without overriding the `fetch` function, you can provide a `fetchOptions` object when instantiating the client or making a request. (Request-specific options override client options.) ```ts -import Kernel from '@onkernel/sdk'; +import Kernel from '@kernel/sdk'; const client = new Kernel({ fetchOptions: { @@ -352,7 +352,7 @@ options to requests: **Node** [[docs](https://github.com/nodejs/undici/blob/main/docs/docs/api/ProxyAgent.md#example---proxyagent-with-fetch)] ```ts -import Kernel from '@onkernel/sdk'; +import Kernel from '@kernel/sdk'; import * as undici from 'undici'; const proxyAgent = new undici.ProxyAgent('http://localhost:8888'); @@ -366,7 +366,7 @@ const client = new Kernel({ **Bun** [[docs](https://bun.sh/guides/http/proxy)] ```ts -import Kernel from '@onkernel/sdk'; +import Kernel from '@kernel/sdk'; const client = new Kernel({ fetchOptions: { @@ -378,7 +378,7 @@ const client = new Kernel({ **Deno** [[docs](https://docs.deno.com/api/deno/~/Deno.createHttpClient)] ```ts -import Kernel from 'npm:@onkernel/sdk'; +import Kernel from 'npm:@kernel/sdk'; const httpClient = Deno.createHttpClient({ proxy: { url: 'http://localhost:8888' } }); const client = new Kernel({ diff --git a/eslint.config.mjs b/eslint.config.mjs index 341aac52..b9c449d2 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -25,7 +25,7 @@ export default tseslint.config( { patterns: [ { - regex: '^@onkernel/sdk(/.*)?', + regex: '^@kernel/sdk(/.*)?', message: 'Use a relative import, not a package import.', }, ], diff --git a/jest.config.ts b/jest.config.ts index f21115cf..091bd928 100644 --- a/jest.config.ts +++ b/jest.config.ts @@ -7,8 +7,8 @@ const config: JestConfigWithTsJest = { '^.+\\.(t|j)sx?$': ['@swc/jest', { sourceMaps: 'inline' }], }, moduleNameMapper: { - '^@onkernel/sdk$': '/src/index.ts', - '^@onkernel/sdk/(.*)$': '/src/$1', + '^@kernel/sdk$': '/src/index.ts', + '^@kernel/sdk/(.*)$': '/src/$1', }, modulePathIgnorePatterns: [ '/ecosystem-tests/', diff --git a/package.json b/package.json index a270b0ae..3628a29f 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "@onkernel/sdk", + "name": "@kernel/sdk", "version": "0.24.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", diff --git a/scripts/build b/scripts/build index a008cb00..c92df216 100755 --- a/scripts/build +++ b/scripts/build @@ -8,7 +8,7 @@ node scripts/utils/check-version.cjs # Build into dist and will publish the package from there, # so that src/resources/foo.ts becomes /resources/foo.js -# This way importing from `"@onkernel/sdk/resources/foo"` works +# This way importing from `"@kernel/sdk/resources/foo"` works # even with `"moduleResolution": "node"` rm -rf dist; mkdir dist @@ -42,8 +42,8 @@ node scripts/utils/postprocess-files.cjs # make sure that nothing crashes when we require the output CJS or # import the output ESM -(cd dist && node -e 'require("@onkernel/sdk")') -(cd dist && node -e 'import("@onkernel/sdk")' --input-type=module) +(cd dist && node -e 'require("@kernel/sdk")') +(cd dist && node -e 'import("@kernel/sdk")' --input-type=module) if [ -e ./scripts/build-deno ] then diff --git a/src/client.ts b/src/client.ts index 050b24ee..7a2c9431 100644 --- a/src/client.ts +++ b/src/client.ts @@ -111,7 +111,7 @@ import { import { isEmptyObj } from './internal/utils/values'; const environments = { - production: 'https://api.onkernel.com/', + production: 'https://api.kernel.com/', development: 'https://localhost:3001/', }; type Environment = keyof typeof environments; @@ -126,7 +126,7 @@ export interface ClientOptions { * Specifies the environment to use for the API. * * Each environment maps to a different base URL: - * - `production` corresponds to `https://api.onkernel.com/` + * - `production` corresponds to `https://api.kernel.com/` * - `development` corresponds to `https://localhost:3001/` */ environment?: Environment | undefined; @@ -223,7 +223,7 @@ export class Kernel { * * @param {string | undefined} [opts.apiKey=process.env['KERNEL_API_KEY'] ?? undefined] * @param {Environment} [opts.environment=production] - Specifies the environment URL to use for the API. - * @param {string} [opts.baseURL=process.env['KERNEL_BASE_URL'] ?? https://api.onkernel.com/] - Override the default base URL for the API. + * @param {string} [opts.baseURL=process.env['KERNEL_BASE_URL'] ?? https://api.kernel.com/] - Override the default base URL for the API. * @param {number} [opts.timeout=1 minute] - The maximum amount of time (in milliseconds) the client will wait for a response before timing out. * @param {MergedRequestInit} [opts.fetchOptions] - Additional `RequestInit` options to be passed to `fetch` calls. * @param {Fetch} [opts.fetch] - Specify a custom `fetch` function implementation. diff --git a/src/resources/agents/auth/auth.ts b/src/resources/agents/auth/auth.ts index 6e9372e4..a02a64f8 100644 --- a/src/resources/agents/auth/auth.ts +++ b/src/resources/agents/auth/auth.ts @@ -150,6 +150,12 @@ export interface AgentAuthInvocationResponse { */ live_view_url?: string | null; + /** + * MFA method options to choose from (present when step=awaiting_input and MFA + * selection is required) + */ + mfa_options?: Array | null; + /** * Fields currently awaiting input (present when step=awaiting_input) */ @@ -167,6 +173,31 @@ export interface AgentAuthInvocationResponse { } export namespace AgentAuthInvocationResponse { + /** + * An MFA method option for verification + */ + export interface MfaOption { + /** + * The visible option text + */ + label: string; + + /** + * The MFA delivery method type + */ + type: 'sms' | 'call' | 'email' | 'totp' | 'push' | 'security_key'; + + /** + * Additional instructions from the site + */ + description?: string | null; + + /** + * The masked destination (phone/email) if shown + */ + target?: string | null; + } + /** * An SSO button for signing in with an external identity provider */ diff --git a/src/resources/agents/auth/invocations.ts b/src/resources/agents/auth/invocations.ts index 94cefbd1..3a25011d 100644 --- a/src/resources/agents/auth/invocations.ts +++ b/src/resources/agents/auth/invocations.ts @@ -128,7 +128,10 @@ export interface InvocationExchangeParams { code: string; } -export type InvocationSubmitParams = InvocationSubmitParams.Variant0 | InvocationSubmitParams.Variant1; +export type InvocationSubmitParams = + | InvocationSubmitParams.Variant0 + | InvocationSubmitParams.Variant1 + | InvocationSubmitParams.Variant2; export declare namespace InvocationSubmitParams { export interface Variant0 { @@ -144,6 +147,13 @@ export declare namespace InvocationSubmitParams { */ sso_button: string; } + + export interface Variant2 { + /** + * The MFA delivery method type + */ + selected_mfa_type: 'sms' | 'call' | 'email' | 'totp' | 'push' | 'security_key'; + } } export declare namespace Invocations { diff --git a/tests/api-resources/agents/auth/auth.test.ts b/tests/api-resources/agents/auth/auth.test.ts index 1f8a9237..ea592ca2 100644 --- a/tests/api-resources/agents/auth/auth.test.ts +++ b/tests/api-resources/agents/auth/auth.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Kernel from '@onkernel/sdk'; +import Kernel from '@kernel/sdk'; const client = new Kernel({ apiKey: 'My API Key', diff --git a/tests/api-resources/agents/auth/invocations.test.ts b/tests/api-resources/agents/auth/invocations.test.ts index b30496c8..de72d35b 100644 --- a/tests/api-resources/agents/auth/invocations.test.ts +++ b/tests/api-resources/agents/auth/invocations.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Kernel from '@onkernel/sdk'; +import Kernel from '@kernel/sdk'; const client = new Kernel({ apiKey: 'My API Key', diff --git a/tests/api-resources/apps.test.ts b/tests/api-resources/apps.test.ts index d1a35f28..68cc9661 100644 --- a/tests/api-resources/apps.test.ts +++ b/tests/api-resources/apps.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Kernel from '@onkernel/sdk'; +import Kernel from '@kernel/sdk'; const client = new Kernel({ apiKey: 'My API Key', diff --git a/tests/api-resources/browser-pools.test.ts b/tests/api-resources/browser-pools.test.ts index 97737bbb..148b4395 100644 --- a/tests/api-resources/browser-pools.test.ts +++ b/tests/api-resources/browser-pools.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Kernel from '@onkernel/sdk'; +import Kernel from '@kernel/sdk'; const client = new Kernel({ apiKey: 'My API Key', diff --git a/tests/api-resources/browsers/browsers.test.ts b/tests/api-resources/browsers/browsers.test.ts index 5b315b4e..a9bc8254 100644 --- a/tests/api-resources/browsers/browsers.test.ts +++ b/tests/api-resources/browsers/browsers.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Kernel, { toFile } from '@onkernel/sdk'; +import Kernel, { toFile } from '@kernel/sdk'; const client = new Kernel({ apiKey: 'My API Key', diff --git a/tests/api-resources/browsers/computer.test.ts b/tests/api-resources/browsers/computer.test.ts index b95f0fa7..acdc93dc 100644 --- a/tests/api-resources/browsers/computer.test.ts +++ b/tests/api-resources/browsers/computer.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Kernel from '@onkernel/sdk'; +import Kernel from '@kernel/sdk'; const client = new Kernel({ apiKey: 'My API Key', diff --git a/tests/api-resources/browsers/fs/fs.test.ts b/tests/api-resources/browsers/fs/fs.test.ts index 92a0c9ce..ebb6d481 100644 --- a/tests/api-resources/browsers/fs/fs.test.ts +++ b/tests/api-resources/browsers/fs/fs.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Kernel, { toFile } from '@onkernel/sdk'; +import Kernel, { toFile } from '@kernel/sdk'; const client = new Kernel({ apiKey: 'My API Key', diff --git a/tests/api-resources/browsers/fs/watch.test.ts b/tests/api-resources/browsers/fs/watch.test.ts index 47ddfb80..0e4e3a6c 100644 --- a/tests/api-resources/browsers/fs/watch.test.ts +++ b/tests/api-resources/browsers/fs/watch.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Kernel from '@onkernel/sdk'; +import Kernel from '@kernel/sdk'; const client = new Kernel({ apiKey: 'My API Key', diff --git a/tests/api-resources/browsers/logs.test.ts b/tests/api-resources/browsers/logs.test.ts index 0fa405ec..3fb0227d 100644 --- a/tests/api-resources/browsers/logs.test.ts +++ b/tests/api-resources/browsers/logs.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Kernel from '@onkernel/sdk'; +import Kernel from '@kernel/sdk'; const client = new Kernel({ apiKey: 'My API Key', diff --git a/tests/api-resources/browsers/playwright.test.ts b/tests/api-resources/browsers/playwright.test.ts index 5c45947d..b2a6fe55 100644 --- a/tests/api-resources/browsers/playwright.test.ts +++ b/tests/api-resources/browsers/playwright.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Kernel from '@onkernel/sdk'; +import Kernel from '@kernel/sdk'; const client = new Kernel({ apiKey: 'My API Key', diff --git a/tests/api-resources/browsers/process.test.ts b/tests/api-resources/browsers/process.test.ts index 138070a4..6418355d 100644 --- a/tests/api-resources/browsers/process.test.ts +++ b/tests/api-resources/browsers/process.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Kernel from '@onkernel/sdk'; +import Kernel from '@kernel/sdk'; const client = new Kernel({ apiKey: 'My API Key', diff --git a/tests/api-resources/browsers/replays.test.ts b/tests/api-resources/browsers/replays.test.ts index d0ee498b..3484b8c6 100644 --- a/tests/api-resources/browsers/replays.test.ts +++ b/tests/api-resources/browsers/replays.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Kernel from '@onkernel/sdk'; +import Kernel from '@kernel/sdk'; const client = new Kernel({ apiKey: 'My API Key', diff --git a/tests/api-resources/credentials.test.ts b/tests/api-resources/credentials.test.ts index d825b4e0..f0e11b65 100644 --- a/tests/api-resources/credentials.test.ts +++ b/tests/api-resources/credentials.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Kernel from '@onkernel/sdk'; +import Kernel from '@kernel/sdk'; const client = new Kernel({ apiKey: 'My API Key', diff --git a/tests/api-resources/deployments.test.ts b/tests/api-resources/deployments.test.ts index b3f0c201..bbc3793e 100644 --- a/tests/api-resources/deployments.test.ts +++ b/tests/api-resources/deployments.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Kernel from '@onkernel/sdk'; +import Kernel from '@kernel/sdk'; const client = new Kernel({ apiKey: 'My API Key', diff --git a/tests/api-resources/extensions.test.ts b/tests/api-resources/extensions.test.ts index 515415fe..eaeb5879 100644 --- a/tests/api-resources/extensions.test.ts +++ b/tests/api-resources/extensions.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Kernel, { toFile } from '@onkernel/sdk'; +import Kernel, { toFile } from '@kernel/sdk'; const client = new Kernel({ apiKey: 'My API Key', diff --git a/tests/api-resources/invocations.test.ts b/tests/api-resources/invocations.test.ts index b8c80247..d8f4e5df 100644 --- a/tests/api-resources/invocations.test.ts +++ b/tests/api-resources/invocations.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Kernel from '@onkernel/sdk'; +import Kernel from '@kernel/sdk'; const client = new Kernel({ apiKey: 'My API Key', diff --git a/tests/api-resources/profiles.test.ts b/tests/api-resources/profiles.test.ts index 9fe686a5..51a2925d 100644 --- a/tests/api-resources/profiles.test.ts +++ b/tests/api-resources/profiles.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Kernel from '@onkernel/sdk'; +import Kernel from '@kernel/sdk'; const client = new Kernel({ apiKey: 'My API Key', diff --git a/tests/api-resources/proxies.test.ts b/tests/api-resources/proxies.test.ts index 1086c4fe..afe5fcef 100644 --- a/tests/api-resources/proxies.test.ts +++ b/tests/api-resources/proxies.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Kernel from '@onkernel/sdk'; +import Kernel from '@kernel/sdk'; const client = new Kernel({ apiKey: 'My API Key', diff --git a/tests/base64.test.ts b/tests/base64.test.ts index 2e2538eb..9b722466 100644 --- a/tests/base64.test.ts +++ b/tests/base64.test.ts @@ -1,4 +1,4 @@ -import { fromBase64, toBase64 } from '@onkernel/sdk/internal/utils/base64'; +import { fromBase64, toBase64 } from '@kernel/sdk/internal/utils/base64'; describe.each(['Buffer', 'atob'])('with %s', (mode) => { let originalBuffer: BufferConstructor; diff --git a/tests/buildHeaders.test.ts b/tests/buildHeaders.test.ts index 039a8008..ec9447af 100644 --- a/tests/buildHeaders.test.ts +++ b/tests/buildHeaders.test.ts @@ -1,5 +1,5 @@ import { inspect } from 'node:util'; -import { buildHeaders, type HeadersLike, type NullableHeaders } from '@onkernel/sdk/internal/headers'; +import { buildHeaders, type HeadersLike, type NullableHeaders } from '@kernel/sdk/internal/headers'; function inspectNullableHeaders(headers: NullableHeaders) { return `NullableHeaders {${[ diff --git a/tests/form.test.ts b/tests/form.test.ts index 56981ca7..68fda151 100644 --- a/tests/form.test.ts +++ b/tests/form.test.ts @@ -1,5 +1,5 @@ -import { multipartFormRequestOptions, createForm } from '@onkernel/sdk/internal/uploads'; -import { toFile } from '@onkernel/sdk/core/uploads'; +import { multipartFormRequestOptions, createForm } from '@kernel/sdk/internal/uploads'; +import { toFile } from '@kernel/sdk/core/uploads'; describe('form data validation', () => { test('valid values do not error', async () => { diff --git a/tests/index.test.ts b/tests/index.test.ts index 90d04c42..39fcf67a 100644 --- a/tests/index.test.ts +++ b/tests/index.test.ts @@ -1,10 +1,10 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { APIPromise } from '@onkernel/sdk/core/api-promise'; +import { APIPromise } from '@kernel/sdk/core/api-promise'; import util from 'node:util'; -import Kernel from '@onkernel/sdk'; -import { APIUserAbortError } from '@onkernel/sdk'; +import Kernel from '@kernel/sdk'; +import { APIUserAbortError } from '@kernel/sdk'; const defaultFetch = fetch; describe('instantiate client', () => { @@ -322,13 +322,13 @@ describe('instantiate client', () => { test('empty env variable', () => { process.env['KERNEL_BASE_URL'] = ''; // empty const client = new Kernel({ apiKey: 'My API Key' }); - expect(client.baseURL).toEqual('https://api.onkernel.com/'); + expect(client.baseURL).toEqual('https://api.kernel.com/'); }); test('blank env variable', () => { process.env['KERNEL_BASE_URL'] = ' '; // blank const client = new Kernel({ apiKey: 'My API Key' }); - expect(client.baseURL).toEqual('https://api.onkernel.com/'); + expect(client.baseURL).toEqual('https://api.kernel.com/'); }); test('env variable with environment', () => { @@ -345,7 +345,7 @@ describe('instantiate client', () => { baseURL: null, environment: 'production', }); - expect(client.baseURL).toEqual('https://api.onkernel.com/'); + expect(client.baseURL).toEqual('https://api.kernel.com/'); }); test('in request options', () => { diff --git a/tests/internal/decoders/line.test.ts b/tests/internal/decoders/line.test.ts index 11466788..9f835645 100644 --- a/tests/internal/decoders/line.test.ts +++ b/tests/internal/decoders/line.test.ts @@ -1,4 +1,4 @@ -import { findDoubleNewlineIndex, LineDecoder } from '@onkernel/sdk/internal/decoders/line'; +import { findDoubleNewlineIndex, LineDecoder } from '@kernel/sdk/internal/decoders/line'; function decodeChunks(chunks: string[], { flush }: { flush: boolean } = { flush: false }): string[] { const decoder = new LineDecoder(); diff --git a/tests/path.test.ts b/tests/path.test.ts index b209e96f..247f0c8f 100644 --- a/tests/path.test.ts +++ b/tests/path.test.ts @@ -1,4 +1,4 @@ -import { createPathTagFunction, encodeURIPath } from '@onkernel/sdk/internal/utils/path'; +import { createPathTagFunction, encodeURIPath } from '@kernel/sdk/internal/utils/path'; import { inspect } from 'node:util'; import { runInNewContext } from 'node:vm'; diff --git a/tests/streaming.test.ts b/tests/streaming.test.ts index 0124e210..ac5aa48f 100644 --- a/tests/streaming.test.ts +++ b/tests/streaming.test.ts @@ -1,6 +1,6 @@ import assert from 'assert'; -import { _iterSSEMessages } from '@onkernel/sdk/core/streaming'; -import { ReadableStreamFrom } from '@onkernel/sdk/internal/shims'; +import { _iterSSEMessages } from '@kernel/sdk/core/streaming'; +import { ReadableStreamFrom } from '@kernel/sdk/internal/shims'; describe('streaming decoding', () => { test('basic', async () => { diff --git a/tests/stringifyQuery.test.ts b/tests/stringifyQuery.test.ts index 1170f010..05e5cc3c 100644 --- a/tests/stringifyQuery.test.ts +++ b/tests/stringifyQuery.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { Kernel } from '@onkernel/sdk'; +import { Kernel } from '@kernel/sdk'; const { stringifyQuery } = Kernel.prototype as any; diff --git a/tests/uploads.test.ts b/tests/uploads.test.ts index ba84b0c1..df09f708 100644 --- a/tests/uploads.test.ts +++ b/tests/uploads.test.ts @@ -1,6 +1,6 @@ import fs from 'fs'; -import type { ResponseLike } from '@onkernel/sdk/internal/to-file'; -import { toFile } from '@onkernel/sdk/core/uploads'; +import type { ResponseLike } from '@kernel/sdk/internal/to-file'; +import { toFile } from '@kernel/sdk/core/uploads'; import { File } from 'node:buffer'; class MyClass { @@ -97,7 +97,7 @@ describe('missing File error message', () => { }); test('is thrown', async () => { - const uploads = await import('@onkernel/sdk/core/uploads'); + const uploads = await import('@kernel/sdk/core/uploads'); await expect( uploads.toFile(mockResponse({ url: 'https://example.com/my/audio.mp3' })), ).rejects.toMatchInlineSnapshot( diff --git a/tsconfig.build.json b/tsconfig.build.json index 762269d0..f161b5d3 100644 --- a/tsconfig.build.json +++ b/tsconfig.build.json @@ -5,8 +5,8 @@ "compilerOptions": { "rootDir": "./dist/src", "paths": { - "@onkernel/sdk/*": ["./dist/src/*"], - "@onkernel/sdk": ["./dist/src/index.ts"] + "@kernel/sdk/*": ["./dist/src/*"], + "@kernel/sdk": ["./dist/src/index.ts"] }, "noEmit": false, "declaration": true, diff --git a/tsconfig.json b/tsconfig.json index 73ce2185..57fc9d66 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -8,8 +8,8 @@ "moduleResolution": "node", "esModuleInterop": true, "paths": { - "@onkernel/sdk/*": ["./src/*"], - "@onkernel/sdk": ["./src/index.ts"] + "@kernel/sdk/*": ["./src/*"], + "@kernel/sdk": ["./src/index.ts"] }, "noEmit": true, From 5fe91d714f0f54f6f5f1d34c86bab43a450cfde2 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 14 Jan 2026 15:19:44 +0000 Subject: [PATCH 243/551] feat(api): manual updates Updated TypeScript package name and API URL to correct values. --- .stats.yml | 2 +- CONTRIBUTING.md | 4 ++-- README.md | 24 +++++++++---------- eslint.config.mjs | 2 +- jest.config.ts | 4 ++-- package.json | 2 +- scripts/build | 6 ++--- src/client.ts | 6 ++--- tests/api-resources/agents/auth/auth.test.ts | 2 +- .../agents/auth/invocations.test.ts | 2 +- tests/api-resources/apps.test.ts | 2 +- tests/api-resources/browser-pools.test.ts | 2 +- tests/api-resources/browsers/browsers.test.ts | 2 +- tests/api-resources/browsers/computer.test.ts | 2 +- tests/api-resources/browsers/fs/fs.test.ts | 2 +- tests/api-resources/browsers/fs/watch.test.ts | 2 +- tests/api-resources/browsers/logs.test.ts | 2 +- .../api-resources/browsers/playwright.test.ts | 2 +- tests/api-resources/browsers/process.test.ts | 2 +- tests/api-resources/browsers/replays.test.ts | 2 +- tests/api-resources/credentials.test.ts | 2 +- tests/api-resources/deployments.test.ts | 2 +- tests/api-resources/extensions.test.ts | 2 +- tests/api-resources/invocations.test.ts | 2 +- tests/api-resources/profiles.test.ts | 2 +- tests/api-resources/proxies.test.ts | 2 +- tests/base64.test.ts | 2 +- tests/buildHeaders.test.ts | 2 +- tests/form.test.ts | 4 ++-- tests/index.test.ts | 12 +++++----- tests/internal/decoders/line.test.ts | 2 +- tests/path.test.ts | 2 +- tests/streaming.test.ts | 4 ++-- tests/stringifyQuery.test.ts | 2 +- tests/uploads.test.ts | 6 ++--- tsconfig.build.json | 4 ++-- tsconfig.json | 4 ++-- 37 files changed, 65 insertions(+), 65 deletions(-) diff --git a/.stats.yml b/.stats.yml index ce759c07..8bd6c680 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 89 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-8e4a29d23d2882fcb0864606091790fd58bffa4f5d5c8d081052b72ad47b215b.yml openapi_spec_hash: fc82d930dad739ac01e3c2bddba7bf61 -config_hash: 3a5e36dfb245210cfd978f679b3641d2 +config_hash: d0585c44724cd7deecea60a5ffae69df diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6434ec2b..30dc1266 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -55,12 +55,12 @@ $ cd kernel-node-sdk # With yarn $ yarn link $ cd ../my-package -$ yarn link @kernel/sdk +$ yarn link @onkernel/sdk # With pnpm $ pnpm link --global $ cd ../my-package -$ pnpm link -—global @kernel/sdk +$ pnpm link -—global @onkernel/sdk ``` ## Running tests diff --git a/README.md b/README.md index 17efd10f..21f35245 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Kernel TypeScript API Library -[![NPM version]()](https://npmjs.org/package/@kernel/sdk) ![npm bundle size](https://img.shields.io/bundlephobia/minzip/@kernel/sdk) +[![NPM version]()](https://npmjs.org/package/@onkernel/sdk) ![npm bundle size](https://img.shields.io/bundlephobia/minzip/@onkernel/sdk) This library provides convenient access to the Kernel REST API from server-side TypeScript or JavaScript. @@ -11,7 +11,7 @@ It is generated with [Stainless](https://www.stainless.com/). ## Installation ```sh -npm install @kernel/sdk +npm install @onkernel/sdk ``` ## Usage @@ -20,7 +20,7 @@ The full API of this library can be found in [api.md](api.md). ```js -import Kernel from '@kernel/sdk'; +import Kernel from '@onkernel/sdk'; const client = new Kernel({ apiKey: process.env['KERNEL_API_KEY'], // This is the default and can be omitted @@ -38,7 +38,7 @@ This library includes TypeScript definitions for all request params and response ```ts -import Kernel from '@kernel/sdk'; +import Kernel from '@onkernel/sdk'; const client = new Kernel({ apiKey: process.env['KERNEL_API_KEY'], // This is the default and can be omitted @@ -62,7 +62,7 @@ Request parameters that correspond to file uploads can be passed in many differe ```ts import fs from 'fs'; -import Kernel, { toFile } from '@kernel/sdk'; +import Kernel, { toFile } from '@onkernel/sdk'; const client = new Kernel(); @@ -227,7 +227,7 @@ The log level can be configured in two ways: 2. Using the `logLevel` client option (overrides the environment variable if set) ```ts -import Kernel from '@kernel/sdk'; +import Kernel from '@onkernel/sdk'; const client = new Kernel({ logLevel: 'debug', // Show all log messages @@ -255,7 +255,7 @@ When providing a custom logger, the `logLevel` option still controls which messa below the configured level will not be sent to your logger. ```ts -import Kernel from '@kernel/sdk'; +import Kernel from '@onkernel/sdk'; import pino from 'pino'; const logger = pino(); @@ -324,7 +324,7 @@ globalThis.fetch = fetch; Or pass it to the client: ```ts -import Kernel from '@kernel/sdk'; +import Kernel from '@onkernel/sdk'; import fetch from 'my-fetch'; const client = new Kernel({ fetch }); @@ -335,7 +335,7 @@ const client = new Kernel({ fetch }); If you want to set custom `fetch` options without overriding the `fetch` function, you can provide a `fetchOptions` object when instantiating the client or making a request. (Request-specific options override client options.) ```ts -import Kernel from '@kernel/sdk'; +import Kernel from '@onkernel/sdk'; const client = new Kernel({ fetchOptions: { @@ -352,7 +352,7 @@ options to requests: **Node** [[docs](https://github.com/nodejs/undici/blob/main/docs/docs/api/ProxyAgent.md#example---proxyagent-with-fetch)] ```ts -import Kernel from '@kernel/sdk'; +import Kernel from '@onkernel/sdk'; import * as undici from 'undici'; const proxyAgent = new undici.ProxyAgent('http://localhost:8888'); @@ -366,7 +366,7 @@ const client = new Kernel({ **Bun** [[docs](https://bun.sh/guides/http/proxy)] ```ts -import Kernel from '@kernel/sdk'; +import Kernel from '@onkernel/sdk'; const client = new Kernel({ fetchOptions: { @@ -378,7 +378,7 @@ const client = new Kernel({ **Deno** [[docs](https://docs.deno.com/api/deno/~/Deno.createHttpClient)] ```ts -import Kernel from 'npm:@kernel/sdk'; +import Kernel from 'npm:@onkernel/sdk'; const httpClient = Deno.createHttpClient({ proxy: { url: 'http://localhost:8888' } }); const client = new Kernel({ diff --git a/eslint.config.mjs b/eslint.config.mjs index b9c449d2..341aac52 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -25,7 +25,7 @@ export default tseslint.config( { patterns: [ { - regex: '^@kernel/sdk(/.*)?', + regex: '^@onkernel/sdk(/.*)?', message: 'Use a relative import, not a package import.', }, ], diff --git a/jest.config.ts b/jest.config.ts index 091bd928..f21115cf 100644 --- a/jest.config.ts +++ b/jest.config.ts @@ -7,8 +7,8 @@ const config: JestConfigWithTsJest = { '^.+\\.(t|j)sx?$': ['@swc/jest', { sourceMaps: 'inline' }], }, moduleNameMapper: { - '^@kernel/sdk$': '/src/index.ts', - '^@kernel/sdk/(.*)$': '/src/$1', + '^@onkernel/sdk$': '/src/index.ts', + '^@onkernel/sdk/(.*)$': '/src/$1', }, modulePathIgnorePatterns: [ '/ecosystem-tests/', diff --git a/package.json b/package.json index 3628a29f..a270b0ae 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "@kernel/sdk", + "name": "@onkernel/sdk", "version": "0.24.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", diff --git a/scripts/build b/scripts/build index c92df216..a008cb00 100755 --- a/scripts/build +++ b/scripts/build @@ -8,7 +8,7 @@ node scripts/utils/check-version.cjs # Build into dist and will publish the package from there, # so that src/resources/foo.ts becomes /resources/foo.js -# This way importing from `"@kernel/sdk/resources/foo"` works +# This way importing from `"@onkernel/sdk/resources/foo"` works # even with `"moduleResolution": "node"` rm -rf dist; mkdir dist @@ -42,8 +42,8 @@ node scripts/utils/postprocess-files.cjs # make sure that nothing crashes when we require the output CJS or # import the output ESM -(cd dist && node -e 'require("@kernel/sdk")') -(cd dist && node -e 'import("@kernel/sdk")' --input-type=module) +(cd dist && node -e 'require("@onkernel/sdk")') +(cd dist && node -e 'import("@onkernel/sdk")' --input-type=module) if [ -e ./scripts/build-deno ] then diff --git a/src/client.ts b/src/client.ts index 7a2c9431..050b24ee 100644 --- a/src/client.ts +++ b/src/client.ts @@ -111,7 +111,7 @@ import { import { isEmptyObj } from './internal/utils/values'; const environments = { - production: 'https://api.kernel.com/', + production: 'https://api.onkernel.com/', development: 'https://localhost:3001/', }; type Environment = keyof typeof environments; @@ -126,7 +126,7 @@ export interface ClientOptions { * Specifies the environment to use for the API. * * Each environment maps to a different base URL: - * - `production` corresponds to `https://api.kernel.com/` + * - `production` corresponds to `https://api.onkernel.com/` * - `development` corresponds to `https://localhost:3001/` */ environment?: Environment | undefined; @@ -223,7 +223,7 @@ export class Kernel { * * @param {string | undefined} [opts.apiKey=process.env['KERNEL_API_KEY'] ?? undefined] * @param {Environment} [opts.environment=production] - Specifies the environment URL to use for the API. - * @param {string} [opts.baseURL=process.env['KERNEL_BASE_URL'] ?? https://api.kernel.com/] - Override the default base URL for the API. + * @param {string} [opts.baseURL=process.env['KERNEL_BASE_URL'] ?? https://api.onkernel.com/] - Override the default base URL for the API. * @param {number} [opts.timeout=1 minute] - The maximum amount of time (in milliseconds) the client will wait for a response before timing out. * @param {MergedRequestInit} [opts.fetchOptions] - Additional `RequestInit` options to be passed to `fetch` calls. * @param {Fetch} [opts.fetch] - Specify a custom `fetch` function implementation. diff --git a/tests/api-resources/agents/auth/auth.test.ts b/tests/api-resources/agents/auth/auth.test.ts index ea592ca2..1f8a9237 100644 --- a/tests/api-resources/agents/auth/auth.test.ts +++ b/tests/api-resources/agents/auth/auth.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Kernel from '@kernel/sdk'; +import Kernel from '@onkernel/sdk'; const client = new Kernel({ apiKey: 'My API Key', diff --git a/tests/api-resources/agents/auth/invocations.test.ts b/tests/api-resources/agents/auth/invocations.test.ts index de72d35b..b30496c8 100644 --- a/tests/api-resources/agents/auth/invocations.test.ts +++ b/tests/api-resources/agents/auth/invocations.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Kernel from '@kernel/sdk'; +import Kernel from '@onkernel/sdk'; const client = new Kernel({ apiKey: 'My API Key', diff --git a/tests/api-resources/apps.test.ts b/tests/api-resources/apps.test.ts index 68cc9661..d1a35f28 100644 --- a/tests/api-resources/apps.test.ts +++ b/tests/api-resources/apps.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Kernel from '@kernel/sdk'; +import Kernel from '@onkernel/sdk'; const client = new Kernel({ apiKey: 'My API Key', diff --git a/tests/api-resources/browser-pools.test.ts b/tests/api-resources/browser-pools.test.ts index 148b4395..97737bbb 100644 --- a/tests/api-resources/browser-pools.test.ts +++ b/tests/api-resources/browser-pools.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Kernel from '@kernel/sdk'; +import Kernel from '@onkernel/sdk'; const client = new Kernel({ apiKey: 'My API Key', diff --git a/tests/api-resources/browsers/browsers.test.ts b/tests/api-resources/browsers/browsers.test.ts index a9bc8254..5b315b4e 100644 --- a/tests/api-resources/browsers/browsers.test.ts +++ b/tests/api-resources/browsers/browsers.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Kernel, { toFile } from '@kernel/sdk'; +import Kernel, { toFile } from '@onkernel/sdk'; const client = new Kernel({ apiKey: 'My API Key', diff --git a/tests/api-resources/browsers/computer.test.ts b/tests/api-resources/browsers/computer.test.ts index acdc93dc..b95f0fa7 100644 --- a/tests/api-resources/browsers/computer.test.ts +++ b/tests/api-resources/browsers/computer.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Kernel from '@kernel/sdk'; +import Kernel from '@onkernel/sdk'; const client = new Kernel({ apiKey: 'My API Key', diff --git a/tests/api-resources/browsers/fs/fs.test.ts b/tests/api-resources/browsers/fs/fs.test.ts index ebb6d481..92a0c9ce 100644 --- a/tests/api-resources/browsers/fs/fs.test.ts +++ b/tests/api-resources/browsers/fs/fs.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Kernel, { toFile } from '@kernel/sdk'; +import Kernel, { toFile } from '@onkernel/sdk'; const client = new Kernel({ apiKey: 'My API Key', diff --git a/tests/api-resources/browsers/fs/watch.test.ts b/tests/api-resources/browsers/fs/watch.test.ts index 0e4e3a6c..47ddfb80 100644 --- a/tests/api-resources/browsers/fs/watch.test.ts +++ b/tests/api-resources/browsers/fs/watch.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Kernel from '@kernel/sdk'; +import Kernel from '@onkernel/sdk'; const client = new Kernel({ apiKey: 'My API Key', diff --git a/tests/api-resources/browsers/logs.test.ts b/tests/api-resources/browsers/logs.test.ts index 3fb0227d..0fa405ec 100644 --- a/tests/api-resources/browsers/logs.test.ts +++ b/tests/api-resources/browsers/logs.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Kernel from '@kernel/sdk'; +import Kernel from '@onkernel/sdk'; const client = new Kernel({ apiKey: 'My API Key', diff --git a/tests/api-resources/browsers/playwright.test.ts b/tests/api-resources/browsers/playwright.test.ts index b2a6fe55..5c45947d 100644 --- a/tests/api-resources/browsers/playwright.test.ts +++ b/tests/api-resources/browsers/playwright.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Kernel from '@kernel/sdk'; +import Kernel from '@onkernel/sdk'; const client = new Kernel({ apiKey: 'My API Key', diff --git a/tests/api-resources/browsers/process.test.ts b/tests/api-resources/browsers/process.test.ts index 6418355d..138070a4 100644 --- a/tests/api-resources/browsers/process.test.ts +++ b/tests/api-resources/browsers/process.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Kernel from '@kernel/sdk'; +import Kernel from '@onkernel/sdk'; const client = new Kernel({ apiKey: 'My API Key', diff --git a/tests/api-resources/browsers/replays.test.ts b/tests/api-resources/browsers/replays.test.ts index 3484b8c6..d0ee498b 100644 --- a/tests/api-resources/browsers/replays.test.ts +++ b/tests/api-resources/browsers/replays.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Kernel from '@kernel/sdk'; +import Kernel from '@onkernel/sdk'; const client = new Kernel({ apiKey: 'My API Key', diff --git a/tests/api-resources/credentials.test.ts b/tests/api-resources/credentials.test.ts index f0e11b65..d825b4e0 100644 --- a/tests/api-resources/credentials.test.ts +++ b/tests/api-resources/credentials.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Kernel from '@kernel/sdk'; +import Kernel from '@onkernel/sdk'; const client = new Kernel({ apiKey: 'My API Key', diff --git a/tests/api-resources/deployments.test.ts b/tests/api-resources/deployments.test.ts index bbc3793e..b3f0c201 100644 --- a/tests/api-resources/deployments.test.ts +++ b/tests/api-resources/deployments.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Kernel from '@kernel/sdk'; +import Kernel from '@onkernel/sdk'; const client = new Kernel({ apiKey: 'My API Key', diff --git a/tests/api-resources/extensions.test.ts b/tests/api-resources/extensions.test.ts index eaeb5879..515415fe 100644 --- a/tests/api-resources/extensions.test.ts +++ b/tests/api-resources/extensions.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Kernel, { toFile } from '@kernel/sdk'; +import Kernel, { toFile } from '@onkernel/sdk'; const client = new Kernel({ apiKey: 'My API Key', diff --git a/tests/api-resources/invocations.test.ts b/tests/api-resources/invocations.test.ts index d8f4e5df..b8c80247 100644 --- a/tests/api-resources/invocations.test.ts +++ b/tests/api-resources/invocations.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Kernel from '@kernel/sdk'; +import Kernel from '@onkernel/sdk'; const client = new Kernel({ apiKey: 'My API Key', diff --git a/tests/api-resources/profiles.test.ts b/tests/api-resources/profiles.test.ts index 51a2925d..9fe686a5 100644 --- a/tests/api-resources/profiles.test.ts +++ b/tests/api-resources/profiles.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Kernel from '@kernel/sdk'; +import Kernel from '@onkernel/sdk'; const client = new Kernel({ apiKey: 'My API Key', diff --git a/tests/api-resources/proxies.test.ts b/tests/api-resources/proxies.test.ts index afe5fcef..1086c4fe 100644 --- a/tests/api-resources/proxies.test.ts +++ b/tests/api-resources/proxies.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Kernel from '@kernel/sdk'; +import Kernel from '@onkernel/sdk'; const client = new Kernel({ apiKey: 'My API Key', diff --git a/tests/base64.test.ts b/tests/base64.test.ts index 9b722466..2e2538eb 100644 --- a/tests/base64.test.ts +++ b/tests/base64.test.ts @@ -1,4 +1,4 @@ -import { fromBase64, toBase64 } from '@kernel/sdk/internal/utils/base64'; +import { fromBase64, toBase64 } from '@onkernel/sdk/internal/utils/base64'; describe.each(['Buffer', 'atob'])('with %s', (mode) => { let originalBuffer: BufferConstructor; diff --git a/tests/buildHeaders.test.ts b/tests/buildHeaders.test.ts index ec9447af..039a8008 100644 --- a/tests/buildHeaders.test.ts +++ b/tests/buildHeaders.test.ts @@ -1,5 +1,5 @@ import { inspect } from 'node:util'; -import { buildHeaders, type HeadersLike, type NullableHeaders } from '@kernel/sdk/internal/headers'; +import { buildHeaders, type HeadersLike, type NullableHeaders } from '@onkernel/sdk/internal/headers'; function inspectNullableHeaders(headers: NullableHeaders) { return `NullableHeaders {${[ diff --git a/tests/form.test.ts b/tests/form.test.ts index 68fda151..56981ca7 100644 --- a/tests/form.test.ts +++ b/tests/form.test.ts @@ -1,5 +1,5 @@ -import { multipartFormRequestOptions, createForm } from '@kernel/sdk/internal/uploads'; -import { toFile } from '@kernel/sdk/core/uploads'; +import { multipartFormRequestOptions, createForm } from '@onkernel/sdk/internal/uploads'; +import { toFile } from '@onkernel/sdk/core/uploads'; describe('form data validation', () => { test('valid values do not error', async () => { diff --git a/tests/index.test.ts b/tests/index.test.ts index 39fcf67a..90d04c42 100644 --- a/tests/index.test.ts +++ b/tests/index.test.ts @@ -1,10 +1,10 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { APIPromise } from '@kernel/sdk/core/api-promise'; +import { APIPromise } from '@onkernel/sdk/core/api-promise'; import util from 'node:util'; -import Kernel from '@kernel/sdk'; -import { APIUserAbortError } from '@kernel/sdk'; +import Kernel from '@onkernel/sdk'; +import { APIUserAbortError } from '@onkernel/sdk'; const defaultFetch = fetch; describe('instantiate client', () => { @@ -322,13 +322,13 @@ describe('instantiate client', () => { test('empty env variable', () => { process.env['KERNEL_BASE_URL'] = ''; // empty const client = new Kernel({ apiKey: 'My API Key' }); - expect(client.baseURL).toEqual('https://api.kernel.com/'); + expect(client.baseURL).toEqual('https://api.onkernel.com/'); }); test('blank env variable', () => { process.env['KERNEL_BASE_URL'] = ' '; // blank const client = new Kernel({ apiKey: 'My API Key' }); - expect(client.baseURL).toEqual('https://api.kernel.com/'); + expect(client.baseURL).toEqual('https://api.onkernel.com/'); }); test('env variable with environment', () => { @@ -345,7 +345,7 @@ describe('instantiate client', () => { baseURL: null, environment: 'production', }); - expect(client.baseURL).toEqual('https://api.kernel.com/'); + expect(client.baseURL).toEqual('https://api.onkernel.com/'); }); test('in request options', () => { diff --git a/tests/internal/decoders/line.test.ts b/tests/internal/decoders/line.test.ts index 9f835645..11466788 100644 --- a/tests/internal/decoders/line.test.ts +++ b/tests/internal/decoders/line.test.ts @@ -1,4 +1,4 @@ -import { findDoubleNewlineIndex, LineDecoder } from '@kernel/sdk/internal/decoders/line'; +import { findDoubleNewlineIndex, LineDecoder } from '@onkernel/sdk/internal/decoders/line'; function decodeChunks(chunks: string[], { flush }: { flush: boolean } = { flush: false }): string[] { const decoder = new LineDecoder(); diff --git a/tests/path.test.ts b/tests/path.test.ts index 247f0c8f..b209e96f 100644 --- a/tests/path.test.ts +++ b/tests/path.test.ts @@ -1,4 +1,4 @@ -import { createPathTagFunction, encodeURIPath } from '@kernel/sdk/internal/utils/path'; +import { createPathTagFunction, encodeURIPath } from '@onkernel/sdk/internal/utils/path'; import { inspect } from 'node:util'; import { runInNewContext } from 'node:vm'; diff --git a/tests/streaming.test.ts b/tests/streaming.test.ts index ac5aa48f..0124e210 100644 --- a/tests/streaming.test.ts +++ b/tests/streaming.test.ts @@ -1,6 +1,6 @@ import assert from 'assert'; -import { _iterSSEMessages } from '@kernel/sdk/core/streaming'; -import { ReadableStreamFrom } from '@kernel/sdk/internal/shims'; +import { _iterSSEMessages } from '@onkernel/sdk/core/streaming'; +import { ReadableStreamFrom } from '@onkernel/sdk/internal/shims'; describe('streaming decoding', () => { test('basic', async () => { diff --git a/tests/stringifyQuery.test.ts b/tests/stringifyQuery.test.ts index 05e5cc3c..1170f010 100644 --- a/tests/stringifyQuery.test.ts +++ b/tests/stringifyQuery.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { Kernel } from '@kernel/sdk'; +import { Kernel } from '@onkernel/sdk'; const { stringifyQuery } = Kernel.prototype as any; diff --git a/tests/uploads.test.ts b/tests/uploads.test.ts index df09f708..ba84b0c1 100644 --- a/tests/uploads.test.ts +++ b/tests/uploads.test.ts @@ -1,6 +1,6 @@ import fs from 'fs'; -import type { ResponseLike } from '@kernel/sdk/internal/to-file'; -import { toFile } from '@kernel/sdk/core/uploads'; +import type { ResponseLike } from '@onkernel/sdk/internal/to-file'; +import { toFile } from '@onkernel/sdk/core/uploads'; import { File } from 'node:buffer'; class MyClass { @@ -97,7 +97,7 @@ describe('missing File error message', () => { }); test('is thrown', async () => { - const uploads = await import('@kernel/sdk/core/uploads'); + const uploads = await import('@onkernel/sdk/core/uploads'); await expect( uploads.toFile(mockResponse({ url: 'https://example.com/my/audio.mp3' })), ).rejects.toMatchInlineSnapshot( diff --git a/tsconfig.build.json b/tsconfig.build.json index f161b5d3..762269d0 100644 --- a/tsconfig.build.json +++ b/tsconfig.build.json @@ -5,8 +5,8 @@ "compilerOptions": { "rootDir": "./dist/src", "paths": { - "@kernel/sdk/*": ["./dist/src/*"], - "@kernel/sdk": ["./dist/src/index.ts"] + "@onkernel/sdk/*": ["./dist/src/*"], + "@onkernel/sdk": ["./dist/src/index.ts"] }, "noEmit": false, "declaration": true, diff --git a/tsconfig.json b/tsconfig.json index 57fc9d66..73ce2185 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -8,8 +8,8 @@ "moduleResolution": "node", "esModuleInterop": true, "paths": { - "@kernel/sdk/*": ["./src/*"], - "@kernel/sdk": ["./src/index.ts"] + "@onkernel/sdk/*": ["./src/*"], + "@onkernel/sdk": ["./src/index.ts"] }, "noEmit": true, From bd9022358c4ab47b4e8569de03cf6113c1103daa Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 14 Jan 2026 23:58:32 +0000 Subject: [PATCH 244/551] feat: add WebSocket process attach and PTY support --- .stats.yml | 8 +-- api.md | 2 + src/resources/browsers/browsers.ts | 4 ++ src/resources/browsers/index.ts | 2 + src/resources/browsers/process.ts | 68 ++++++++++++++++++++ tests/api-resources/browsers/process.test.ts | 28 ++++++++ 6 files changed, 108 insertions(+), 4 deletions(-) diff --git a/.stats.yml b/.stats.yml index 8bd6c680..e7a094fa 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 89 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-8e4a29d23d2882fcb0864606091790fd58bffa4f5d5c8d081052b72ad47b215b.yml -openapi_spec_hash: fc82d930dad739ac01e3c2bddba7bf61 -config_hash: d0585c44724cd7deecea60a5ffae69df +configured_endpoints: 90 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-6a44c851ec955b997558a8524eb641355ff3097474f40772b8ea2fef5bee4134.yml +openapi_spec_hash: 155ee005a1b43e1c11e843de91e9f509 +config_hash: 6cbbf855a29bc675f35ddb1106ea9083 diff --git a/api.md b/api.md index 8d44e74a..48dff70b 100644 --- a/api.md +++ b/api.md @@ -133,6 +133,7 @@ Types: - ProcessExecResponse - ProcessKillResponse +- ProcessResizeResponse - ProcessSpawnResponse - ProcessStatusResponse - ProcessStdinResponse @@ -142,6 +143,7 @@ Methods: - client.browsers.process.exec(id, { ...params }) -> ProcessExecResponse - client.browsers.process.kill(processID, { ...params }) -> ProcessKillResponse +- client.browsers.process.resize(processID, { ...params }) -> ProcessResizeResponse - client.browsers.process.spawn(id, { ...params }) -> ProcessSpawnResponse - client.browsers.process.status(processID, { ...params }) -> ProcessStatusResponse - client.browsers.process.stdin(processID, { ...params }) -> ProcessStdinResponse diff --git a/src/resources/browsers/browsers.ts b/src/resources/browsers/browsers.ts index b42c3832..c12665d0 100644 --- a/src/resources/browsers/browsers.ts +++ b/src/resources/browsers/browsers.ts @@ -26,6 +26,8 @@ import { ProcessExecResponse, ProcessKillParams, ProcessKillResponse, + ProcessResizeParams, + ProcessResizeResponse, ProcessSpawnParams, ProcessSpawnResponse, ProcessStatusParams, @@ -615,12 +617,14 @@ export declare namespace Browsers { Process as Process, type ProcessExecResponse as ProcessExecResponse, type ProcessKillResponse as ProcessKillResponse, + type ProcessResizeResponse as ProcessResizeResponse, type ProcessSpawnResponse as ProcessSpawnResponse, type ProcessStatusResponse as ProcessStatusResponse, type ProcessStdinResponse as ProcessStdinResponse, type ProcessStdoutStreamResponse as ProcessStdoutStreamResponse, type ProcessExecParams as ProcessExecParams, type ProcessKillParams as ProcessKillParams, + type ProcessResizeParams as ProcessResizeParams, type ProcessSpawnParams as ProcessSpawnParams, type ProcessStatusParams as ProcessStatusParams, type ProcessStdinParams as ProcessStdinParams, diff --git a/src/resources/browsers/index.ts b/src/resources/browsers/index.ts index 569517ab..fc8f7c57 100644 --- a/src/resources/browsers/index.ts +++ b/src/resources/browsers/index.ts @@ -48,12 +48,14 @@ export { Process, type ProcessExecResponse, type ProcessKillResponse, + type ProcessResizeResponse, type ProcessSpawnResponse, type ProcessStatusResponse, type ProcessStdinResponse, type ProcessStdoutStreamResponse, type ProcessExecParams, type ProcessKillParams, + type ProcessResizeParams, type ProcessSpawnParams, type ProcessStatusParams, type ProcessStdinParams, diff --git a/src/resources/browsers/process.ts b/src/resources/browsers/process.ts index 2a3be958..a19f8b95 100644 --- a/src/resources/browsers/process.ts +++ b/src/resources/browsers/process.ts @@ -42,6 +42,30 @@ export class Process extends APIResource { return this._client.post(path`/browsers/${id}/process/${processID}/kill`, { body, ...options }); } + /** + * Resize a PTY-backed process terminal + * + * @example + * ```ts + * const response = await client.browsers.process.resize( + * '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', + * { + * id: 'id', + * cols: 1, + * rows: 1, + * }, + * ); + * ``` + */ + resize( + processID: string, + params: ProcessResizeParams, + options?: RequestOptions, + ): APIPromise { + const { id, ...body } = params; + return this._client.post(path`/browsers/${id}/process/${processID}/resize`, { body, ...options }); + } + /** * Execute a command asynchronously * @@ -156,6 +180,16 @@ export interface ProcessKillResponse { ok: boolean; } +/** + * Generic OK response. + */ +export interface ProcessResizeResponse { + /** + * Indicates success. + */ + ok: boolean; +} + /** * Information about a spawned process. */ @@ -285,12 +319,34 @@ export interface ProcessKillParams { signal: 'TERM' | 'KILL' | 'INT' | 'HUP'; } +export interface ProcessResizeParams { + /** + * Path param: Browser session ID + */ + id: string; + + /** + * Body param: New terminal columns. + */ + cols: number; + + /** + * Body param: New terminal rows. + */ + rows: number; +} + export interface ProcessSpawnParams { /** * Executable or shell command to run. */ command: string; + /** + * Allocate a pseudo-terminal (PTY) for interactive shells. + */ + allocate_tty?: boolean; + /** * Command arguments. */ @@ -306,6 +362,11 @@ export interface ProcessSpawnParams { */ as_user?: string | null; + /** + * Initial terminal columns. Only used when allocate_tty is true. + */ + cols?: number; + /** * Working directory (absolute path) to run the command in. */ @@ -316,6 +377,11 @@ export interface ProcessSpawnParams { */ env?: { [key: string]: string }; + /** + * Initial terminal rows. Only used when allocate_tty is true. + */ + rows?: number; + /** * Maximum execution time in seconds. */ @@ -352,12 +418,14 @@ export declare namespace Process { export { type ProcessExecResponse as ProcessExecResponse, type ProcessKillResponse as ProcessKillResponse, + type ProcessResizeResponse as ProcessResizeResponse, type ProcessSpawnResponse as ProcessSpawnResponse, type ProcessStatusResponse as ProcessStatusResponse, type ProcessStdinResponse as ProcessStdinResponse, type ProcessStdoutStreamResponse as ProcessStdoutStreamResponse, type ProcessExecParams as ProcessExecParams, type ProcessKillParams as ProcessKillParams, + type ProcessResizeParams as ProcessResizeParams, type ProcessSpawnParams as ProcessSpawnParams, type ProcessStatusParams as ProcessStatusParams, type ProcessStdinParams as ProcessStdinParams, diff --git a/tests/api-resources/browsers/process.test.ts b/tests/api-resources/browsers/process.test.ts index 138070a4..c608e246 100644 --- a/tests/api-resources/browsers/process.test.ts +++ b/tests/api-resources/browsers/process.test.ts @@ -56,6 +56,31 @@ describe('resource process', () => { }); }); + // Prism tests are disabled + test.skip('resize: only required params', async () => { + const responsePromise = client.browsers.process.resize('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', { + id: 'id', + cols: 1, + rows: 1, + }); + 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); + }); + + // Prism tests are disabled + test.skip('resize: required and optional params', async () => { + const response = await client.browsers.process.resize('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', { + id: 'id', + cols: 1, + rows: 1, + }); + }); + // Prism tests are disabled test.skip('spawn: only required params', async () => { const responsePromise = client.browsers.process.spawn('id', { command: 'command' }); @@ -72,11 +97,14 @@ describe('resource process', () => { test.skip('spawn: required and optional params', async () => { const response = await client.browsers.process.spawn('id', { command: 'command', + allocate_tty: true, args: ['string'], as_root: true, as_user: 'as_user', + cols: 1, cwd: '/J!', env: { foo: 'string' }, + rows: 1, timeout_sec: 0, }); }); From a555b770f4546e1288656dbd16f3f4dd7c6c3262 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 15 Jan 2026 05:08:33 +0000 Subject: [PATCH 245/551] chore(internal): upgrade babel, qs, js-yaml --- yarn.lock | 556 ++++++++++++++++++++++++------------------------------ 1 file changed, 249 insertions(+), 307 deletions(-) diff --git a/yarn.lock b/yarn.lock index 5f56a201..fc9f262b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7,14 +7,6 @@ resolved "https://registry.yarnpkg.com/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz#bd9154aec9983f77b3a034ecaa015c2e4201f6cf" integrity sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA== -"@ampproject/remapping@^2.2.0": - version "2.2.1" - resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.1.tgz#99e8e11851128b8702cd57c33684f1d0f260b630" - integrity sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg== - dependencies: - "@jridgewell/gen-mapping" "^0.3.0" - "@jridgewell/trace-mapping" "^0.3.9" - "@andrewbranch/untar.js@^1.0.3": version "1.0.3" resolved "https://registry.yarnpkg.com/@andrewbranch/untar.js/-/untar.js-1.0.3.tgz#ba9494f85eb83017c5c855763969caf1d0adea00" @@ -46,155 +38,119 @@ typescript "5.6.1-rc" validate-npm-package-name "^5.0.0" -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.22.13", "@babel/code-frame@^7.23.5": - version "7.23.5" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.23.5.tgz#9009b69a8c602293476ad598ff53e4562e15c244" - integrity sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA== +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.28.6": + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.28.6.tgz#72499312ec58b1e2245ba4a4f550c132be4982f7" + integrity sha512-JYgintcMjRiCvS8mMECzaEn+m3PfoQiyqukOMCCVQtoJGYJw8j/8LBJEiqkHLkfwCcs74E3pbAUFNg7d9VNJ+Q== dependencies: - "@babel/highlight" "^7.23.4" - chalk "^2.4.2" + "@babel/helper-validator-identifier" "^7.28.5" + js-tokens "^4.0.0" + picocolors "^1.1.1" -"@babel/compat-data@^7.23.5": - version "7.23.5" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.23.5.tgz#ffb878728bb6bdcb6f4510aa51b1be9afb8cfd98" - integrity sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw== +"@babel/compat-data@^7.28.6": + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.28.6.tgz#103f466803fa0f059e82ccac271475470570d74c" + integrity sha512-2lfu57JtzctfIrcGMz992hyLlByuzgIk58+hhGCxjKZ3rWI82NnVLjXcaTqkI2NvlcvOskZaiZ5kjUALo3Lpxg== "@babel/core@^7.11.6", "@babel/core@^7.12.3": - version "7.23.6" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.23.6.tgz#8be77cd77c55baadcc1eae1c33df90ab6d2151d4" - integrity sha512-FxpRyGjrMJXh7X3wGLGhNDCRiwpWEF74sKjTLDJSG5Kyvow3QZaG0Adbqzi9ZrVjTWpsX+2cxWXD71NMg93kdw== - dependencies: - "@ampproject/remapping" "^2.2.0" - "@babel/code-frame" "^7.23.5" - "@babel/generator" "^7.23.6" - "@babel/helper-compilation-targets" "^7.23.6" - "@babel/helper-module-transforms" "^7.23.3" - "@babel/helpers" "^7.23.6" - "@babel/parser" "^7.23.6" - "@babel/template" "^7.22.15" - "@babel/traverse" "^7.23.6" - "@babel/types" "^7.23.6" + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.28.6.tgz#531bf883a1126e53501ba46eb3bb414047af507f" + integrity sha512-H3mcG6ZDLTlYfaSNi0iOKkigqMFvkTKlGUYlD8GW7nNOYRrevuA46iTypPyv+06V3fEmvvazfntkBU34L0azAw== + dependencies: + "@babel/code-frame" "^7.28.6" + "@babel/generator" "^7.28.6" + "@babel/helper-compilation-targets" "^7.28.6" + "@babel/helper-module-transforms" "^7.28.6" + "@babel/helpers" "^7.28.6" + "@babel/parser" "^7.28.6" + "@babel/template" "^7.28.6" + "@babel/traverse" "^7.28.6" + "@babel/types" "^7.28.6" + "@jridgewell/remapping" "^2.3.5" convert-source-map "^2.0.0" debug "^4.1.0" gensync "^1.0.0-beta.2" json5 "^2.2.3" semver "^6.3.1" -"@babel/generator@^7.23.6", "@babel/generator@^7.7.2": - version "7.23.6" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.23.6.tgz#9e1fca4811c77a10580d17d26b57b036133f3c2e" - integrity sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw== +"@babel/generator@^7.28.6", "@babel/generator@^7.7.2": + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.28.6.tgz#48dcc65d98fcc8626a48f72b62e263d25fc3c3f1" + integrity sha512-lOoVRwADj8hjf7al89tvQ2a1lf53Z+7tiXMgpZJL3maQPDxh0DgLMN62B2MKUOFcoodBHLMbDM6WAbKgNy5Suw== + dependencies: + "@babel/parser" "^7.28.6" + "@babel/types" "^7.28.6" + "@jridgewell/gen-mapping" "^0.3.12" + "@jridgewell/trace-mapping" "^0.3.28" + jsesc "^3.0.2" + +"@babel/helper-compilation-targets@^7.28.6": + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz#32c4a3f41f12ed1532179b108a4d746e105c2b25" + integrity sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA== + dependencies: + "@babel/compat-data" "^7.28.6" + "@babel/helper-validator-option" "^7.27.1" + browserslist "^4.24.0" + lru-cache "^5.1.1" + semver "^6.3.1" + +"@babel/helper-globals@^7.28.0": + version "7.28.0" + resolved "https://registry.yarnpkg.com/@babel/helper-globals/-/helper-globals-7.28.0.tgz#b9430df2aa4e17bc28665eadeae8aa1d985e6674" + integrity sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw== + +"@babel/helper-module-imports@^7.28.6": + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz#60632cbd6ffb70b22823187201116762a03e2d5c" + integrity sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw== dependencies: - "@babel/types" "^7.23.6" - "@jridgewell/gen-mapping" "^0.3.2" - "@jridgewell/trace-mapping" "^0.3.17" - jsesc "^2.5.1" + "@babel/traverse" "^7.28.6" + "@babel/types" "^7.28.6" -"@babel/helper-compilation-targets@^7.23.6": - version "7.23.6" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz#4d79069b16cbcf1461289eccfbbd81501ae39991" - integrity sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ== +"@babel/helper-module-transforms@^7.28.6": + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz#9312d9d9e56edc35aeb6e95c25d4106b50b9eb1e" + integrity sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA== dependencies: - "@babel/compat-data" "^7.23.5" - "@babel/helper-validator-option" "^7.23.5" - browserslist "^4.22.2" - lru-cache "^5.1.1" - semver "^6.3.1" + "@babel/helper-module-imports" "^7.28.6" + "@babel/helper-validator-identifier" "^7.28.5" + "@babel/traverse" "^7.28.6" -"@babel/helper-environment-visitor@^7.22.20": - version "7.22.20" - resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz#96159db61d34a29dba454c959f5ae4a649ba9167" - integrity sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA== - -"@babel/helper-function-name@^7.23.0": - version "7.23.0" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz#1f9a3cdbd5b2698a670c30d2735f9af95ed52759" - integrity sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw== - dependencies: - "@babel/template" "^7.22.15" - "@babel/types" "^7.23.0" - -"@babel/helper-hoist-variables@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz#c01a007dac05c085914e8fb652b339db50d823bb" - integrity sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw== - dependencies: - "@babel/types" "^7.22.5" - -"@babel/helper-module-imports@^7.22.15": - version "7.22.15" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz#16146307acdc40cc00c3b2c647713076464bdbf0" - integrity sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w== - dependencies: - "@babel/types" "^7.22.15" - -"@babel/helper-module-transforms@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz#d7d12c3c5d30af5b3c0fcab2a6d5217773e2d0f1" - integrity sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ== - dependencies: - "@babel/helper-environment-visitor" "^7.22.20" - "@babel/helper-module-imports" "^7.22.15" - "@babel/helper-simple-access" "^7.22.5" - "@babel/helper-split-export-declaration" "^7.22.6" - "@babel/helper-validator-identifier" "^7.22.20" - -"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.22.5", "@babel/helper-plugin-utils@^7.8.0": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz#dd7ee3735e8a313b9f7b05a773d892e88e6d7295" - integrity sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg== - -"@babel/helper-simple-access@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz#4938357dc7d782b80ed6dbb03a0fba3d22b1d5de" - integrity sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w== - dependencies: - "@babel/types" "^7.22.5" - -"@babel/helper-split-export-declaration@^7.22.6": - version "7.22.6" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz#322c61b7310c0997fe4c323955667f18fcefb91c" - integrity sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g== - dependencies: - "@babel/types" "^7.22.5" - -"@babel/helper-string-parser@^7.23.4": - version "7.23.4" - resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz#9478c707febcbbe1ddb38a3d91a2e054ae622d83" - integrity sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ== - -"@babel/helper-validator-identifier@^7.22.20": - version "7.22.20" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0" - integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A== - -"@babel/helper-validator-option@^7.23.5": - version "7.23.5" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz#907a3fbd4523426285365d1206c423c4c5520307" - integrity sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw== - -"@babel/helpers@^7.23.6": - version "7.23.6" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.23.6.tgz#d03af2ee5fb34691eec0cda90f5ecbb4d4da145a" - integrity sha512-wCfsbN4nBidDRhpDhvcKlzHWCTlgJYUUdSJfzXb2NuBssDSIjc3xcb+znA7l+zYsFljAcGM0aFkN40cR3lXiGA== - dependencies: - "@babel/template" "^7.22.15" - "@babel/traverse" "^7.23.6" - "@babel/types" "^7.23.6" - -"@babel/highlight@^7.23.4": - version "7.23.4" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.23.4.tgz#edaadf4d8232e1a961432db785091207ead0621b" - integrity sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A== - dependencies: - "@babel/helper-validator-identifier" "^7.22.20" - chalk "^2.4.2" - js-tokens "^4.0.0" +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.28.6", "@babel/helper-plugin-utils@^7.8.0": + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz#6f13ea251b68c8532e985fd532f28741a8af9ac8" + integrity sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug== + +"@babel/helper-string-parser@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz#54da796097ab19ce67ed9f88b47bb2ec49367687" + integrity sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA== + +"@babel/helper-validator-identifier@^7.28.5": + version "7.28.5" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz#010b6938fab7cb7df74aa2bbc06aa503b8fe5fb4" + integrity sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q== + +"@babel/helper-validator-option@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz#fa52f5b1e7db1ab049445b421c4471303897702f" + integrity sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg== + +"@babel/helpers@^7.28.6": + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.28.6.tgz#fca903a313ae675617936e8998b814c415cbf5d7" + integrity sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw== + dependencies: + "@babel/template" "^7.28.6" + "@babel/types" "^7.28.6" -"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7", "@babel/parser@^7.22.15", "@babel/parser@^7.23.6": - version "7.23.6" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.23.6.tgz#ba1c9e512bda72a47e285ae42aff9d2a635a9e3b" - integrity sha512-Z2uID7YJ7oNvAI20O9X0bblw7Qqs8Q2hFy0R9tAfnfLkp5MW0UH9eUvnDSnFwKZ0AvgS1ucqR4KzvVHgnke1VQ== +"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7", "@babel/parser@^7.28.6": + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.28.6.tgz#f01a8885b7fa1e56dd8a155130226cd698ef13fd" + integrity sha512-TeR9zWR18BvbfPmGbLampPMW+uW1NZnJlRuuHso8i87QZNq2JRF9i6RgxRqtEq+wQGsS19NNTWr2duhnE49mfQ== + dependencies: + "@babel/types" "^7.28.6" "@babel/plugin-syntax-async-generators@^7.8.4": version "7.8.4" @@ -210,14 +166,28 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-class-properties@^7.8.3": +"@babel/plugin-syntax-class-properties@^7.12.13": version "7.12.13" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10" integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA== dependencies: "@babel/helper-plugin-utils" "^7.12.13" -"@babel/plugin-syntax-import-meta@^7.8.3": +"@babel/plugin-syntax-class-static-block@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz#195df89b146b4b78b3bf897fd7a257c84659d406" + integrity sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + +"@babel/plugin-syntax-import-attributes@^7.24.7": + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.28.6.tgz#b71d5914665f60124e133696f17cd7669062c503" + integrity sha512-jiLC0ma9XkQT3TKJ9uYvlakm66Pamywo+qwL+oL8HJOvc6TWdZXVfhqJr8CCzbSGUAbDOzlGHJC1U+vRfLQDvw== + dependencies: + "@babel/helper-plugin-utils" "^7.28.6" + +"@babel/plugin-syntax-import-meta@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51" integrity sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g== @@ -232,13 +202,13 @@ "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-jsx@^7.7.2": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.23.3.tgz#8f2e4f8a9b5f9aa16067e142c1ac9cd9f810f473" - integrity sha512-EB2MELswq55OHUoRZLGg/zC7QWUKfNLpE57m/S2yr1uEneIgsTgrSzXP3NXEsMkVn76OlaVVnzN+ugObuYGwhg== + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.28.6.tgz#f8ca28bbd84883b5fea0e447c635b81ba73997ee" + integrity sha512-wgEmr06G6sIpqr8YDwA2dSRTE3bJ+V0IfpzfSY3Lfgd7YWOaAdlykvJi13ZKBt8cZHfgH1IXN+CL656W3uUa4w== dependencies: - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.28.6" -"@babel/plugin-syntax-logical-assignment-operators@^7.8.3": +"@babel/plugin-syntax-logical-assignment-operators@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== @@ -252,7 +222,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-numeric-separator@^7.8.3": +"@babel/plugin-syntax-numeric-separator@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== @@ -280,7 +250,14 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-top-level-await@^7.8.3": +"@babel/plugin-syntax-private-property-in-object@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz#0dc6671ec0ea22b6e94a1114f857970cd39de1ad" + integrity sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + +"@babel/plugin-syntax-top-level-await@^7.14.5": version "7.14.5" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz#c1cfdadc35a646240001f06138247b741c34d94c" integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw== @@ -288,45 +265,41 @@ "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-typescript@^7.7.2": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.23.3.tgz#24f460c85dbbc983cd2b9c4994178bcc01df958f" - integrity sha512-9EiNjVJOMwCO+43TqoTrgQ8jMwcAd0sWyXi9RPfIsLTj4R2MADDDQXELhffaUx/uJv2AYcxBgPwH6j4TIA4ytQ== - dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - -"@babel/template@^7.22.15", "@babel/template@^7.3.3": - version "7.22.15" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.15.tgz#09576efc3830f0430f4548ef971dde1350ef2f38" - integrity sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w== - dependencies: - "@babel/code-frame" "^7.22.13" - "@babel/parser" "^7.22.15" - "@babel/types" "^7.22.15" - -"@babel/traverse@^7.23.6": - version "7.23.6" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.23.6.tgz#b53526a2367a0dd6edc423637f3d2d0f2521abc5" - integrity sha512-czastdK1e8YByZqezMPFiZ8ahwVMh/ESl9vPgvgdB9AmFMGP5jfpFax74AQgl5zj4XHzqeYAg2l8PuUeRS1MgQ== - dependencies: - "@babel/code-frame" "^7.23.5" - "@babel/generator" "^7.23.6" - "@babel/helper-environment-visitor" "^7.22.20" - "@babel/helper-function-name" "^7.23.0" - "@babel/helper-hoist-variables" "^7.22.5" - "@babel/helper-split-export-declaration" "^7.22.6" - "@babel/parser" "^7.23.6" - "@babel/types" "^7.23.6" + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.28.6.tgz#c7b2ddf1d0a811145b1de800d1abd146af92e3a2" + integrity sha512-+nDNmQye7nlnuuHDboPbGm00Vqg3oO8niRRL27/4LYHUsHYh0zJ1xWOz0uRwNFmM1Avzk8wZbc6rdiYhomzv/A== + dependencies: + "@babel/helper-plugin-utils" "^7.28.6" + +"@babel/template@^7.28.6", "@babel/template@^7.3.3": + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.28.6.tgz#0e7e56ecedb78aeef66ce7972b082fce76a23e57" + integrity sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ== + dependencies: + "@babel/code-frame" "^7.28.6" + "@babel/parser" "^7.28.6" + "@babel/types" "^7.28.6" + +"@babel/traverse@^7.28.6": + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.28.6.tgz#871ddc79a80599a5030c53b1cc48cbe3a5583c2e" + integrity sha512-fgWX62k02qtjqdSNTAGxmKYY/7FSL9WAS1o2Hu5+I5m9T0yxZzr4cnrfXQ/MX0rIifthCSs6FKTlzYbJcPtMNg== + dependencies: + "@babel/code-frame" "^7.28.6" + "@babel/generator" "^7.28.6" + "@babel/helper-globals" "^7.28.0" + "@babel/parser" "^7.28.6" + "@babel/template" "^7.28.6" + "@babel/types" "^7.28.6" debug "^4.3.1" - globals "^11.1.0" -"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.22.15", "@babel/types@^7.22.5", "@babel/types@^7.23.0", "@babel/types@^7.23.6", "@babel/types@^7.3.3": - version "7.23.6" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.23.6.tgz#be33fdb151e1f5a56877d704492c240fc71c7ccd" - integrity sha512-+uarb83brBzPKN38NX1MkB6vb6+mwvR6amUulqAE7ccQw1pEl+bCia9TbdG1lsnFP7lZySvUn37CHyXQdfTwzg== +"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.28.6", "@babel/types@^7.3.3": + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.28.6.tgz#c3e9377f1b155005bcc4c46020e7e394e13089df" + integrity sha512-0ZrskXVEHSWIqZM/sQZ4EV3jZJXRkio/WCxaqKZP1g//CEWEPSfeZFcms4XeKBCHU0ZKnIkdJeU/kF+eRp5lBg== dependencies: - "@babel/helper-string-parser" "^7.23.4" - "@babel/helper-validator-identifier" "^7.22.20" - to-fast-properties "^2.0.0" + "@babel/helper-string-parser" "^7.27.1" + "@babel/helper-validator-identifier" "^7.28.5" "@bcoe/v8-coverage@^0.2.3": version "0.2.3" @@ -668,31 +641,38 @@ "@types/yargs" "^17.0.8" chalk "^4.0.0" -"@jridgewell/gen-mapping@^0.3.0", "@jridgewell/gen-mapping@^0.3.2": - version "0.3.3" - resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz#7e02e6eb5df901aaedb08514203b096614024098" - integrity sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ== +"@jridgewell/gen-mapping@^0.3.12", "@jridgewell/gen-mapping@^0.3.5": + version "0.3.13" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz#6342a19f44347518c93e43b1ac69deb3c4656a1f" + integrity sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA== + dependencies: + "@jridgewell/sourcemap-codec" "^1.5.0" + "@jridgewell/trace-mapping" "^0.3.24" + +"@jridgewell/remapping@^2.3.5": + version "2.3.5" + resolved "https://registry.yarnpkg.com/@jridgewell/remapping/-/remapping-2.3.5.tgz#375c476d1972947851ba1e15ae8f123047445aa1" + integrity sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ== dependencies: - "@jridgewell/set-array" "^1.0.1" - "@jridgewell/sourcemap-codec" "^1.4.10" - "@jridgewell/trace-mapping" "^0.3.9" + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.24" "@jridgewell/resolve-uri@^3.1.0": version "3.1.1" resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz#c08679063f279615a3326583ba3a90d1d82cc721" integrity sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA== -"@jridgewell/set-array@^1.0.1": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" - integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== - -"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14": +"@jridgewell/sourcemap-codec@^1.4.14": version "1.4.15" resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== -"@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.18", "@jridgewell/trace-mapping@^0.3.9": +"@jridgewell/sourcemap-codec@^1.5.0": + version "1.5.5" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz#6912b00d2c631c0d15ce1a7ab57cd657f2a8f8ba" + integrity sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og== + +"@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.18": version "0.3.20" resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz#72e45707cf240fa6b081d0366f8265b0cd10197f" integrity sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q== @@ -700,6 +680,14 @@ "@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" +"@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.28": + version "0.3.31" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz#db15d6781c931f3a251a3dac39501c98a6082fd0" + integrity sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw== + dependencies: + "@jridgewell/resolve-uri" "^3.1.0" + "@jridgewell/sourcemap-codec" "^1.4.14" + "@nodelib/fs.scandir@2.1.5": version "2.1.5" resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" @@ -1116,13 +1104,6 @@ ansi-regex@^6.1.0: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.1.0.tgz#95ec409c69619d6cb1b8b34f14b660ef28ebd654" integrity sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA== -ansi-styles@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" - integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== - dependencies: - color-convert "^1.9.0" - ansi-styles@^4.0.0, ansi-styles@^4.1.0: version "4.3.0" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" @@ -1200,22 +1181,25 @@ babel-plugin-jest-hoist@^29.6.3: "@types/babel__traverse" "^7.0.6" babel-preset-current-node-syntax@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz#b4399239b89b2a011f9ddbe3e4f401fc40cff73b" - integrity sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ== + version "1.2.0" + resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.2.0.tgz#20730d6cdc7dda5d89401cab10ac6a32067acde6" + integrity sha512-E/VlAEzRrsLEb2+dv8yp3bo4scof3l9nR4lrld+Iy5NyVqgVYUJnDAmunkhPMisRI32Qc4iRiz425d8vM++2fg== dependencies: "@babel/plugin-syntax-async-generators" "^7.8.4" "@babel/plugin-syntax-bigint" "^7.8.3" - "@babel/plugin-syntax-class-properties" "^7.8.3" - "@babel/plugin-syntax-import-meta" "^7.8.3" + "@babel/plugin-syntax-class-properties" "^7.12.13" + "@babel/plugin-syntax-class-static-block" "^7.14.5" + "@babel/plugin-syntax-import-attributes" "^7.24.7" + "@babel/plugin-syntax-import-meta" "^7.10.4" "@babel/plugin-syntax-json-strings" "^7.8.3" - "@babel/plugin-syntax-logical-assignment-operators" "^7.8.3" + "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" - "@babel/plugin-syntax-numeric-separator" "^7.8.3" + "@babel/plugin-syntax-numeric-separator" "^7.10.4" "@babel/plugin-syntax-object-rest-spread" "^7.8.3" "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" "@babel/plugin-syntax-optional-chaining" "^7.8.3" - "@babel/plugin-syntax-top-level-await" "^7.8.3" + "@babel/plugin-syntax-private-property-in-object" "^7.14.5" + "@babel/plugin-syntax-top-level-await" "^7.14.5" babel-preset-jest@^29.6.3: version "29.6.3" @@ -1230,18 +1214,23 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== +baseline-browser-mapping@^2.9.0: + version "2.9.14" + resolved "https://registry.yarnpkg.com/baseline-browser-mapping/-/baseline-browser-mapping-2.9.14.tgz#3b6af0bc032445bca04de58caa9a87cfe921cbb3" + integrity sha512-B0xUquLkiGLgHhpPBqvl7GWegWBUNuujQ6kXd/r1U38ElPT6Ok8KZ8e+FpUGEc2ZoRQUzq/aUnaKFc/svWUGSg== + brace-expansion@^1.1.7: - version "1.1.11" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + version "1.1.12" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.12.tgz#ab9b454466e5a8cc3a187beaad580412a9c5b843" + integrity sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg== dependencies: balanced-match "^1.0.0" concat-map "0.0.1" brace-expansion@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" - integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== + version "2.0.2" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.2.tgz#54fc53237a613d854c7bd37463aad17df87214e7" + integrity sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ== dependencies: balanced-match "^1.0.0" @@ -1252,15 +1241,16 @@ braces@^3.0.3: dependencies: fill-range "^7.1.1" -browserslist@^4.22.2: - version "4.22.2" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.22.2.tgz#704c4943072bd81ea18997f3bd2180e89c77874b" - integrity sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A== +browserslist@^4.24.0: + version "4.28.1" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.28.1.tgz#7f534594628c53c63101079e27e40de490456a95" + integrity sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA== dependencies: - caniuse-lite "^1.0.30001565" - electron-to-chromium "^1.4.601" - node-releases "^2.0.14" - update-browserslist-db "^1.0.13" + baseline-browser-mapping "^2.9.0" + caniuse-lite "^1.0.30001759" + electron-to-chromium "^1.5.263" + node-releases "^2.0.27" + update-browserslist-db "^1.2.0" bs-logger@0.x: version "0.2.6" @@ -1296,19 +1286,10 @@ camelcase@^6.2.0: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== -caniuse-lite@^1.0.30001565: - version "1.0.30001570" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001570.tgz#b4e5c1fa786f733ab78fc70f592df6b3f23244ca" - integrity sha512-+3e0ASu4sw1SWaoCtvPeyXp+5PsjigkSt8OXZbF9StH5pQWbxEjLAZE3n8Aup5udop1uRiKA7a4utUk/uoSpUw== - -chalk@^2.4.2: - version "2.4.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" - integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== - dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" +caniuse-lite@^1.0.30001759: + version "1.0.30001764" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001764.tgz#03206c56469f236103b90f9ae10bcb8b9e1f6005" + integrity sha512-9JGuzl2M+vPL+pz70gtMF9sHdMFbY9FJaQBi186cHKH3pSzDvzoUJUPV6fqiKIMyXbud9ZLg4F3Yza1vJ1+93g== chalk@^4.0.0, chalk@^4.1.2: version "4.1.2" @@ -1397,13 +1378,6 @@ collect-v8-coverage@^1.0.0: resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz#c0b29bcd33bcd0779a1344c2136051e6afd3d9e9" integrity sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q== -color-convert@^1.9.0: - version "1.9.3" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" - integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== - dependencies: - color-name "1.1.3" - color-convert@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" @@ -1411,11 +1385,6 @@ color-convert@^2.0.1: dependencies: color-name "~1.1.4" -color-name@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== - color-name@~1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" @@ -1507,10 +1476,10 @@ diff@^4.0.1: resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== -electron-to-chromium@^1.4.601: - version "1.4.614" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.614.tgz#2fe789d61fa09cb875569f37c309d0c2701f91c0" - integrity sha512-X4ze/9Sc3QWs6h92yerwqv7aB/uU8vCjZcrMjA8N9R1pjMFRe44dLsck5FzLilOYvcXuDn93B+bpGYyufc70gQ== +electron-to-chromium@^1.5.263: + version "1.5.267" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.267.tgz#5d84f2df8cdb6bfe7e873706bb21bd4bfb574dc7" + integrity sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw== emittery@^0.13.1: version "0.13.1" @@ -1544,10 +1513,10 @@ escalade@^3.1.1: resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== -escape-string-regexp@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== +escalade@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5" + integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA== escape-string-regexp@^2.0.0: version "2.0.0" @@ -1883,11 +1852,6 @@ glob@^8.0.1: minimatch "^5.0.1" once "^1.3.0" -globals@^11.1.0: - version "11.12.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" - integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== - globals@^14.0.0: version "14.0.0" resolved "https://registry.yarnpkg.com/globals/-/globals-14.0.0.tgz#898d7413c29babcf6bafe56fcadded858ada724e" @@ -1903,11 +1867,6 @@ graphemer@^1.4.0: resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== -has-flag@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== - has-flag@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" @@ -2459,9 +2418,9 @@ js-tokens@^4.0.0: integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== js-yaml@^3.13.1: - version "3.14.1" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" - integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== + version "3.14.2" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.2.tgz#77485ce1dd7f33c061fd1b16ecea23b55fcb04b0" + integrity sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg== dependencies: argparse "^1.0.7" esprima "^4.0.0" @@ -2473,10 +2432,10 @@ js-yaml@^4.1.1: dependencies: argparse "^2.0.1" -jsesc@^2.5.1: - version "2.5.2" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" - integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== +jsesc@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-3.1.0.tgz#74d335a234f67ed19907fdadfac7ccf9d409825d" + integrity sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA== json-buffer@3.0.1: version "3.0.1" @@ -2711,10 +2670,10 @@ node-int64@^0.4.0: resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" integrity sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw== -node-releases@^2.0.14: - version "2.0.14" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.14.tgz#2ffb053bceb8b2be8495ece1ab6ce600c4461b0b" - integrity sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw== +node-releases@^2.0.27: + version "2.0.27" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.27.tgz#eedca519205cf20f650f61d56b070db111231e4e" + integrity sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA== normalize-path@^3.0.0: version "3.0.0" @@ -2882,11 +2841,6 @@ path-parse@^1.0.7: resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== -picocolors@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" - integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== - picocolors@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" @@ -3190,13 +3144,6 @@ superstruct@^1.0.4: resolved "https://registry.yarnpkg.com/superstruct/-/superstruct-1.0.4.tgz#0adb99a7578bd2f1c526220da6571b2d485d91ca" integrity sha512-7JpaAoX2NGyoFlI9NBh66BQXGONc+uE+MRS5i2iOBKuS4e+ccgMDjATgZldkah+33DakBxDHiss9kvUcGAO8UQ== -supports-color@^5.3.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" - integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== - dependencies: - has-flag "^3.0.0" - supports-color@^7.0.0, supports-color@^7.1.0: version "7.2.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" @@ -3259,11 +3206,6 @@ tmpl@1.0.5: resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw== -to-fast-properties@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" - integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== - to-regex-range@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" @@ -3389,13 +3331,13 @@ unicode-emoji-modifier-base@^1.0.0: resolved "https://registry.yarnpkg.com/unicode-emoji-modifier-base/-/unicode-emoji-modifier-base-1.0.0.tgz#dbbd5b54ba30f287e2a8d5a249da6c0cef369459" integrity sha512-yLSH4py7oFH3oG/9K+XWrz1pSi3dfUrWEnInbxMfArOfc1+33BlGPQtLsOYwvdMy11AwUBetYuaRxSPqgkq+8g== -update-browserslist-db@^1.0.13: - version "1.0.13" - resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz#3c5e4f5c083661bd38ef64b6328c26ed6c8248c4" - integrity sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg== +update-browserslist-db@^1.2.0: + version "1.2.3" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz#64d76db58713136acbeb4c49114366cc6cc2e80d" + integrity sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w== dependencies: - escalade "^3.1.1" - picocolors "^1.0.0" + escalade "^3.2.0" + picocolors "^1.1.1" uri-js@^4.2.2: version "4.4.1" From b477052fa566c9bcbc386df0dd9fd5eea355c2a5 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 15 Jan 2026 20:05:59 +0000 Subject: [PATCH 246/551] feat(api): add IP address logging for residential and custom proxies --- .stats.yml | 6 ++--- CONTRIBUTING.md | 4 ++-- README.md | 24 +++++++++---------- eslint.config.mjs | 2 +- jest.config.ts | 4 ++-- package.json | 2 +- scripts/build | 6 ++--- src/client.ts | 6 ++--- src/resources/proxies.ts | 20 ++++++++++++++++ tests/api-resources/agents/auth/auth.test.ts | 2 +- .../agents/auth/invocations.test.ts | 2 +- tests/api-resources/apps.test.ts | 2 +- tests/api-resources/browser-pools.test.ts | 2 +- tests/api-resources/browsers/browsers.test.ts | 2 +- tests/api-resources/browsers/computer.test.ts | 2 +- tests/api-resources/browsers/fs/fs.test.ts | 2 +- tests/api-resources/browsers/fs/watch.test.ts | 2 +- tests/api-resources/browsers/logs.test.ts | 2 +- .../api-resources/browsers/playwright.test.ts | 2 +- tests/api-resources/browsers/process.test.ts | 2 +- tests/api-resources/browsers/replays.test.ts | 2 +- tests/api-resources/credentials.test.ts | 2 +- tests/api-resources/deployments.test.ts | 2 +- tests/api-resources/extensions.test.ts | 2 +- tests/api-resources/invocations.test.ts | 2 +- tests/api-resources/profiles.test.ts | 2 +- tests/api-resources/proxies.test.ts | 2 +- tests/base64.test.ts | 2 +- tests/buildHeaders.test.ts | 2 +- tests/form.test.ts | 4 ++-- tests/index.test.ts | 12 +++++----- tests/internal/decoders/line.test.ts | 2 +- tests/path.test.ts | 2 +- tests/streaming.test.ts | 4 ++-- tests/stringifyQuery.test.ts | 2 +- tests/uploads.test.ts | 6 ++--- tsconfig.build.json | 4 ++-- tsconfig.json | 4 ++-- 38 files changed, 87 insertions(+), 67 deletions(-) diff --git a/.stats.yml b/.stats.yml index e7a094fa..f0310d3b 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 90 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-6a44c851ec955b997558a8524eb641355ff3097474f40772b8ea2fef5bee4134.yml -openapi_spec_hash: 155ee005a1b43e1c11e843de91e9f509 -config_hash: 6cbbf855a29bc675f35ddb1106ea9083 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-cc60c65c6bb0b8a8ea662cf758806e641790870ded35f6ffdb9f4801f3d29b15.yml +openapi_spec_hash: a1074e1bba578bcd5912512166ada0dc +config_hash: 7868d3397406c2974b6f058488aeefd6 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 30dc1266..6434ec2b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -55,12 +55,12 @@ $ cd kernel-node-sdk # With yarn $ yarn link $ cd ../my-package -$ yarn link @onkernel/sdk +$ yarn link @kernel/sdk # With pnpm $ pnpm link --global $ cd ../my-package -$ pnpm link -—global @onkernel/sdk +$ pnpm link -—global @kernel/sdk ``` ## Running tests diff --git a/README.md b/README.md index 21f35245..17efd10f 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Kernel TypeScript API Library -[![NPM version]()](https://npmjs.org/package/@onkernel/sdk) ![npm bundle size](https://img.shields.io/bundlephobia/minzip/@onkernel/sdk) +[![NPM version]()](https://npmjs.org/package/@kernel/sdk) ![npm bundle size](https://img.shields.io/bundlephobia/minzip/@kernel/sdk) This library provides convenient access to the Kernel REST API from server-side TypeScript or JavaScript. @@ -11,7 +11,7 @@ It is generated with [Stainless](https://www.stainless.com/). ## Installation ```sh -npm install @onkernel/sdk +npm install @kernel/sdk ``` ## Usage @@ -20,7 +20,7 @@ The full API of this library can be found in [api.md](api.md). ```js -import Kernel from '@onkernel/sdk'; +import Kernel from '@kernel/sdk'; const client = new Kernel({ apiKey: process.env['KERNEL_API_KEY'], // This is the default and can be omitted @@ -38,7 +38,7 @@ This library includes TypeScript definitions for all request params and response ```ts -import Kernel from '@onkernel/sdk'; +import Kernel from '@kernel/sdk'; const client = new Kernel({ apiKey: process.env['KERNEL_API_KEY'], // This is the default and can be omitted @@ -62,7 +62,7 @@ Request parameters that correspond to file uploads can be passed in many differe ```ts import fs from 'fs'; -import Kernel, { toFile } from '@onkernel/sdk'; +import Kernel, { toFile } from '@kernel/sdk'; const client = new Kernel(); @@ -227,7 +227,7 @@ The log level can be configured in two ways: 2. Using the `logLevel` client option (overrides the environment variable if set) ```ts -import Kernel from '@onkernel/sdk'; +import Kernel from '@kernel/sdk'; const client = new Kernel({ logLevel: 'debug', // Show all log messages @@ -255,7 +255,7 @@ When providing a custom logger, the `logLevel` option still controls which messa below the configured level will not be sent to your logger. ```ts -import Kernel from '@onkernel/sdk'; +import Kernel from '@kernel/sdk'; import pino from 'pino'; const logger = pino(); @@ -324,7 +324,7 @@ globalThis.fetch = fetch; Or pass it to the client: ```ts -import Kernel from '@onkernel/sdk'; +import Kernel from '@kernel/sdk'; import fetch from 'my-fetch'; const client = new Kernel({ fetch }); @@ -335,7 +335,7 @@ const client = new Kernel({ fetch }); If you want to set custom `fetch` options without overriding the `fetch` function, you can provide a `fetchOptions` object when instantiating the client or making a request. (Request-specific options override client options.) ```ts -import Kernel from '@onkernel/sdk'; +import Kernel from '@kernel/sdk'; const client = new Kernel({ fetchOptions: { @@ -352,7 +352,7 @@ options to requests: **Node** [[docs](https://github.com/nodejs/undici/blob/main/docs/docs/api/ProxyAgent.md#example---proxyagent-with-fetch)] ```ts -import Kernel from '@onkernel/sdk'; +import Kernel from '@kernel/sdk'; import * as undici from 'undici'; const proxyAgent = new undici.ProxyAgent('http://localhost:8888'); @@ -366,7 +366,7 @@ const client = new Kernel({ **Bun** [[docs](https://bun.sh/guides/http/proxy)] ```ts -import Kernel from '@onkernel/sdk'; +import Kernel from '@kernel/sdk'; const client = new Kernel({ fetchOptions: { @@ -378,7 +378,7 @@ const client = new Kernel({ **Deno** [[docs](https://docs.deno.com/api/deno/~/Deno.createHttpClient)] ```ts -import Kernel from 'npm:@onkernel/sdk'; +import Kernel from 'npm:@kernel/sdk'; const httpClient = Deno.createHttpClient({ proxy: { url: 'http://localhost:8888' } }); const client = new Kernel({ diff --git a/eslint.config.mjs b/eslint.config.mjs index 341aac52..b9c449d2 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -25,7 +25,7 @@ export default tseslint.config( { patterns: [ { - regex: '^@onkernel/sdk(/.*)?', + regex: '^@kernel/sdk(/.*)?', message: 'Use a relative import, not a package import.', }, ], diff --git a/jest.config.ts b/jest.config.ts index f21115cf..091bd928 100644 --- a/jest.config.ts +++ b/jest.config.ts @@ -7,8 +7,8 @@ const config: JestConfigWithTsJest = { '^.+\\.(t|j)sx?$': ['@swc/jest', { sourceMaps: 'inline' }], }, moduleNameMapper: { - '^@onkernel/sdk$': '/src/index.ts', - '^@onkernel/sdk/(.*)$': '/src/$1', + '^@kernel/sdk$': '/src/index.ts', + '^@kernel/sdk/(.*)$': '/src/$1', }, modulePathIgnorePatterns: [ '/ecosystem-tests/', diff --git a/package.json b/package.json index a270b0ae..3628a29f 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "@onkernel/sdk", + "name": "@kernel/sdk", "version": "0.24.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", diff --git a/scripts/build b/scripts/build index a008cb00..c92df216 100755 --- a/scripts/build +++ b/scripts/build @@ -8,7 +8,7 @@ node scripts/utils/check-version.cjs # Build into dist and will publish the package from there, # so that src/resources/foo.ts becomes /resources/foo.js -# This way importing from `"@onkernel/sdk/resources/foo"` works +# This way importing from `"@kernel/sdk/resources/foo"` works # even with `"moduleResolution": "node"` rm -rf dist; mkdir dist @@ -42,8 +42,8 @@ node scripts/utils/postprocess-files.cjs # make sure that nothing crashes when we require the output CJS or # import the output ESM -(cd dist && node -e 'require("@onkernel/sdk")') -(cd dist && node -e 'import("@onkernel/sdk")' --input-type=module) +(cd dist && node -e 'require("@kernel/sdk")') +(cd dist && node -e 'import("@kernel/sdk")' --input-type=module) if [ -e ./scripts/build-deno ] then diff --git a/src/client.ts b/src/client.ts index 050b24ee..7a2c9431 100644 --- a/src/client.ts +++ b/src/client.ts @@ -111,7 +111,7 @@ import { import { isEmptyObj } from './internal/utils/values'; const environments = { - production: 'https://api.onkernel.com/', + production: 'https://api.kernel.com/', development: 'https://localhost:3001/', }; type Environment = keyof typeof environments; @@ -126,7 +126,7 @@ export interface ClientOptions { * Specifies the environment to use for the API. * * Each environment maps to a different base URL: - * - `production` corresponds to `https://api.onkernel.com/` + * - `production` corresponds to `https://api.kernel.com/` * - `development` corresponds to `https://localhost:3001/` */ environment?: Environment | undefined; @@ -223,7 +223,7 @@ export class Kernel { * * @param {string | undefined} [opts.apiKey=process.env['KERNEL_API_KEY'] ?? undefined] * @param {Environment} [opts.environment=production] - Specifies the environment URL to use for the API. - * @param {string} [opts.baseURL=process.env['KERNEL_BASE_URL'] ?? https://api.onkernel.com/] - Override the default base URL for the API. + * @param {string} [opts.baseURL=process.env['KERNEL_BASE_URL'] ?? https://api.kernel.com/] - Override the default base URL for the API. * @param {number} [opts.timeout=1 minute] - The maximum amount of time (in milliseconds) the client will wait for a response before timing out. * @param {MergedRequestInit} [opts.fetchOptions] - Additional `RequestInit` options to be passed to `fetch` calls. * @param {Fetch} [opts.fetch] - Specify a custom `fetch` function implementation. diff --git a/src/resources/proxies.ts b/src/resources/proxies.ts index a8040b1f..f30203fb 100644 --- a/src/resources/proxies.ts +++ b/src/resources/proxies.ts @@ -68,6 +68,11 @@ export interface ProxyCreateResponse { | ProxyCreateResponse.MobileProxyConfig | ProxyCreateResponse.CustomProxyConfig; + /** + * IP address that the proxy uses when making requests. + */ + ip_address?: string; + /** * Timestamp of the last health check performed on this proxy. */ @@ -288,6 +293,11 @@ export interface ProxyRetrieveResponse { | ProxyRetrieveResponse.MobileProxyConfig | ProxyRetrieveResponse.CustomProxyConfig; + /** + * IP address that the proxy uses when making requests. + */ + ip_address?: string; + /** * Timestamp of the last health check performed on this proxy. */ @@ -511,6 +521,11 @@ export namespace ProxyListResponse { | ProxyListResponseItem.MobileProxyConfig | ProxyListResponseItem.CustomProxyConfig; + /** + * IP address that the proxy uses when making requests. + */ + ip_address?: string; + /** * Timestamp of the last health check performed on this proxy. */ @@ -732,6 +747,11 @@ export interface ProxyCheckResponse { | ProxyCheckResponse.MobileProxyConfig | ProxyCheckResponse.CustomProxyConfig; + /** + * IP address that the proxy uses when making requests. + */ + ip_address?: string; + /** * Timestamp of the last health check performed on this proxy. */ diff --git a/tests/api-resources/agents/auth/auth.test.ts b/tests/api-resources/agents/auth/auth.test.ts index 1f8a9237..ea592ca2 100644 --- a/tests/api-resources/agents/auth/auth.test.ts +++ b/tests/api-resources/agents/auth/auth.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Kernel from '@onkernel/sdk'; +import Kernel from '@kernel/sdk'; const client = new Kernel({ apiKey: 'My API Key', diff --git a/tests/api-resources/agents/auth/invocations.test.ts b/tests/api-resources/agents/auth/invocations.test.ts index b30496c8..de72d35b 100644 --- a/tests/api-resources/agents/auth/invocations.test.ts +++ b/tests/api-resources/agents/auth/invocations.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Kernel from '@onkernel/sdk'; +import Kernel from '@kernel/sdk'; const client = new Kernel({ apiKey: 'My API Key', diff --git a/tests/api-resources/apps.test.ts b/tests/api-resources/apps.test.ts index d1a35f28..68cc9661 100644 --- a/tests/api-resources/apps.test.ts +++ b/tests/api-resources/apps.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Kernel from '@onkernel/sdk'; +import Kernel from '@kernel/sdk'; const client = new Kernel({ apiKey: 'My API Key', diff --git a/tests/api-resources/browser-pools.test.ts b/tests/api-resources/browser-pools.test.ts index 97737bbb..148b4395 100644 --- a/tests/api-resources/browser-pools.test.ts +++ b/tests/api-resources/browser-pools.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Kernel from '@onkernel/sdk'; +import Kernel from '@kernel/sdk'; const client = new Kernel({ apiKey: 'My API Key', diff --git a/tests/api-resources/browsers/browsers.test.ts b/tests/api-resources/browsers/browsers.test.ts index 5b315b4e..a9bc8254 100644 --- a/tests/api-resources/browsers/browsers.test.ts +++ b/tests/api-resources/browsers/browsers.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Kernel, { toFile } from '@onkernel/sdk'; +import Kernel, { toFile } from '@kernel/sdk'; const client = new Kernel({ apiKey: 'My API Key', diff --git a/tests/api-resources/browsers/computer.test.ts b/tests/api-resources/browsers/computer.test.ts index b95f0fa7..acdc93dc 100644 --- a/tests/api-resources/browsers/computer.test.ts +++ b/tests/api-resources/browsers/computer.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Kernel from '@onkernel/sdk'; +import Kernel from '@kernel/sdk'; const client = new Kernel({ apiKey: 'My API Key', diff --git a/tests/api-resources/browsers/fs/fs.test.ts b/tests/api-resources/browsers/fs/fs.test.ts index 92a0c9ce..ebb6d481 100644 --- a/tests/api-resources/browsers/fs/fs.test.ts +++ b/tests/api-resources/browsers/fs/fs.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Kernel, { toFile } from '@onkernel/sdk'; +import Kernel, { toFile } from '@kernel/sdk'; const client = new Kernel({ apiKey: 'My API Key', diff --git a/tests/api-resources/browsers/fs/watch.test.ts b/tests/api-resources/browsers/fs/watch.test.ts index 47ddfb80..0e4e3a6c 100644 --- a/tests/api-resources/browsers/fs/watch.test.ts +++ b/tests/api-resources/browsers/fs/watch.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Kernel from '@onkernel/sdk'; +import Kernel from '@kernel/sdk'; const client = new Kernel({ apiKey: 'My API Key', diff --git a/tests/api-resources/browsers/logs.test.ts b/tests/api-resources/browsers/logs.test.ts index 0fa405ec..3fb0227d 100644 --- a/tests/api-resources/browsers/logs.test.ts +++ b/tests/api-resources/browsers/logs.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Kernel from '@onkernel/sdk'; +import Kernel from '@kernel/sdk'; const client = new Kernel({ apiKey: 'My API Key', diff --git a/tests/api-resources/browsers/playwright.test.ts b/tests/api-resources/browsers/playwright.test.ts index 5c45947d..b2a6fe55 100644 --- a/tests/api-resources/browsers/playwright.test.ts +++ b/tests/api-resources/browsers/playwright.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Kernel from '@onkernel/sdk'; +import Kernel from '@kernel/sdk'; const client = new Kernel({ apiKey: 'My API Key', diff --git a/tests/api-resources/browsers/process.test.ts b/tests/api-resources/browsers/process.test.ts index c608e246..c428741a 100644 --- a/tests/api-resources/browsers/process.test.ts +++ b/tests/api-resources/browsers/process.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Kernel from '@onkernel/sdk'; +import Kernel from '@kernel/sdk'; const client = new Kernel({ apiKey: 'My API Key', diff --git a/tests/api-resources/browsers/replays.test.ts b/tests/api-resources/browsers/replays.test.ts index d0ee498b..3484b8c6 100644 --- a/tests/api-resources/browsers/replays.test.ts +++ b/tests/api-resources/browsers/replays.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Kernel from '@onkernel/sdk'; +import Kernel from '@kernel/sdk'; const client = new Kernel({ apiKey: 'My API Key', diff --git a/tests/api-resources/credentials.test.ts b/tests/api-resources/credentials.test.ts index d825b4e0..f0e11b65 100644 --- a/tests/api-resources/credentials.test.ts +++ b/tests/api-resources/credentials.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Kernel from '@onkernel/sdk'; +import Kernel from '@kernel/sdk'; const client = new Kernel({ apiKey: 'My API Key', diff --git a/tests/api-resources/deployments.test.ts b/tests/api-resources/deployments.test.ts index b3f0c201..bbc3793e 100644 --- a/tests/api-resources/deployments.test.ts +++ b/tests/api-resources/deployments.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Kernel from '@onkernel/sdk'; +import Kernel from '@kernel/sdk'; const client = new Kernel({ apiKey: 'My API Key', diff --git a/tests/api-resources/extensions.test.ts b/tests/api-resources/extensions.test.ts index 515415fe..eaeb5879 100644 --- a/tests/api-resources/extensions.test.ts +++ b/tests/api-resources/extensions.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Kernel, { toFile } from '@onkernel/sdk'; +import Kernel, { toFile } from '@kernel/sdk'; const client = new Kernel({ apiKey: 'My API Key', diff --git a/tests/api-resources/invocations.test.ts b/tests/api-resources/invocations.test.ts index b8c80247..d8f4e5df 100644 --- a/tests/api-resources/invocations.test.ts +++ b/tests/api-resources/invocations.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Kernel from '@onkernel/sdk'; +import Kernel from '@kernel/sdk'; const client = new Kernel({ apiKey: 'My API Key', diff --git a/tests/api-resources/profiles.test.ts b/tests/api-resources/profiles.test.ts index 9fe686a5..51a2925d 100644 --- a/tests/api-resources/profiles.test.ts +++ b/tests/api-resources/profiles.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Kernel from '@onkernel/sdk'; +import Kernel from '@kernel/sdk'; const client = new Kernel({ apiKey: 'My API Key', diff --git a/tests/api-resources/proxies.test.ts b/tests/api-resources/proxies.test.ts index 1086c4fe..afe5fcef 100644 --- a/tests/api-resources/proxies.test.ts +++ b/tests/api-resources/proxies.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Kernel from '@onkernel/sdk'; +import Kernel from '@kernel/sdk'; const client = new Kernel({ apiKey: 'My API Key', diff --git a/tests/base64.test.ts b/tests/base64.test.ts index 2e2538eb..9b722466 100644 --- a/tests/base64.test.ts +++ b/tests/base64.test.ts @@ -1,4 +1,4 @@ -import { fromBase64, toBase64 } from '@onkernel/sdk/internal/utils/base64'; +import { fromBase64, toBase64 } from '@kernel/sdk/internal/utils/base64'; describe.each(['Buffer', 'atob'])('with %s', (mode) => { let originalBuffer: BufferConstructor; diff --git a/tests/buildHeaders.test.ts b/tests/buildHeaders.test.ts index 039a8008..ec9447af 100644 --- a/tests/buildHeaders.test.ts +++ b/tests/buildHeaders.test.ts @@ -1,5 +1,5 @@ import { inspect } from 'node:util'; -import { buildHeaders, type HeadersLike, type NullableHeaders } from '@onkernel/sdk/internal/headers'; +import { buildHeaders, type HeadersLike, type NullableHeaders } from '@kernel/sdk/internal/headers'; function inspectNullableHeaders(headers: NullableHeaders) { return `NullableHeaders {${[ diff --git a/tests/form.test.ts b/tests/form.test.ts index 56981ca7..68fda151 100644 --- a/tests/form.test.ts +++ b/tests/form.test.ts @@ -1,5 +1,5 @@ -import { multipartFormRequestOptions, createForm } from '@onkernel/sdk/internal/uploads'; -import { toFile } from '@onkernel/sdk/core/uploads'; +import { multipartFormRequestOptions, createForm } from '@kernel/sdk/internal/uploads'; +import { toFile } from '@kernel/sdk/core/uploads'; describe('form data validation', () => { test('valid values do not error', async () => { diff --git a/tests/index.test.ts b/tests/index.test.ts index 90d04c42..39fcf67a 100644 --- a/tests/index.test.ts +++ b/tests/index.test.ts @@ -1,10 +1,10 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { APIPromise } from '@onkernel/sdk/core/api-promise'; +import { APIPromise } from '@kernel/sdk/core/api-promise'; import util from 'node:util'; -import Kernel from '@onkernel/sdk'; -import { APIUserAbortError } from '@onkernel/sdk'; +import Kernel from '@kernel/sdk'; +import { APIUserAbortError } from '@kernel/sdk'; const defaultFetch = fetch; describe('instantiate client', () => { @@ -322,13 +322,13 @@ describe('instantiate client', () => { test('empty env variable', () => { process.env['KERNEL_BASE_URL'] = ''; // empty const client = new Kernel({ apiKey: 'My API Key' }); - expect(client.baseURL).toEqual('https://api.onkernel.com/'); + expect(client.baseURL).toEqual('https://api.kernel.com/'); }); test('blank env variable', () => { process.env['KERNEL_BASE_URL'] = ' '; // blank const client = new Kernel({ apiKey: 'My API Key' }); - expect(client.baseURL).toEqual('https://api.onkernel.com/'); + expect(client.baseURL).toEqual('https://api.kernel.com/'); }); test('env variable with environment', () => { @@ -345,7 +345,7 @@ describe('instantiate client', () => { baseURL: null, environment: 'production', }); - expect(client.baseURL).toEqual('https://api.onkernel.com/'); + expect(client.baseURL).toEqual('https://api.kernel.com/'); }); test('in request options', () => { diff --git a/tests/internal/decoders/line.test.ts b/tests/internal/decoders/line.test.ts index 11466788..9f835645 100644 --- a/tests/internal/decoders/line.test.ts +++ b/tests/internal/decoders/line.test.ts @@ -1,4 +1,4 @@ -import { findDoubleNewlineIndex, LineDecoder } from '@onkernel/sdk/internal/decoders/line'; +import { findDoubleNewlineIndex, LineDecoder } from '@kernel/sdk/internal/decoders/line'; function decodeChunks(chunks: string[], { flush }: { flush: boolean } = { flush: false }): string[] { const decoder = new LineDecoder(); diff --git a/tests/path.test.ts b/tests/path.test.ts index b209e96f..247f0c8f 100644 --- a/tests/path.test.ts +++ b/tests/path.test.ts @@ -1,4 +1,4 @@ -import { createPathTagFunction, encodeURIPath } from '@onkernel/sdk/internal/utils/path'; +import { createPathTagFunction, encodeURIPath } from '@kernel/sdk/internal/utils/path'; import { inspect } from 'node:util'; import { runInNewContext } from 'node:vm'; diff --git a/tests/streaming.test.ts b/tests/streaming.test.ts index 0124e210..ac5aa48f 100644 --- a/tests/streaming.test.ts +++ b/tests/streaming.test.ts @@ -1,6 +1,6 @@ import assert from 'assert'; -import { _iterSSEMessages } from '@onkernel/sdk/core/streaming'; -import { ReadableStreamFrom } from '@onkernel/sdk/internal/shims'; +import { _iterSSEMessages } from '@kernel/sdk/core/streaming'; +import { ReadableStreamFrom } from '@kernel/sdk/internal/shims'; describe('streaming decoding', () => { test('basic', async () => { diff --git a/tests/stringifyQuery.test.ts b/tests/stringifyQuery.test.ts index 1170f010..05e5cc3c 100644 --- a/tests/stringifyQuery.test.ts +++ b/tests/stringifyQuery.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { Kernel } from '@onkernel/sdk'; +import { Kernel } from '@kernel/sdk'; const { stringifyQuery } = Kernel.prototype as any; diff --git a/tests/uploads.test.ts b/tests/uploads.test.ts index ba84b0c1..df09f708 100644 --- a/tests/uploads.test.ts +++ b/tests/uploads.test.ts @@ -1,6 +1,6 @@ import fs from 'fs'; -import type { ResponseLike } from '@onkernel/sdk/internal/to-file'; -import { toFile } from '@onkernel/sdk/core/uploads'; +import type { ResponseLike } from '@kernel/sdk/internal/to-file'; +import { toFile } from '@kernel/sdk/core/uploads'; import { File } from 'node:buffer'; class MyClass { @@ -97,7 +97,7 @@ describe('missing File error message', () => { }); test('is thrown', async () => { - const uploads = await import('@onkernel/sdk/core/uploads'); + const uploads = await import('@kernel/sdk/core/uploads'); await expect( uploads.toFile(mockResponse({ url: 'https://example.com/my/audio.mp3' })), ).rejects.toMatchInlineSnapshot( diff --git a/tsconfig.build.json b/tsconfig.build.json index 762269d0..f161b5d3 100644 --- a/tsconfig.build.json +++ b/tsconfig.build.json @@ -5,8 +5,8 @@ "compilerOptions": { "rootDir": "./dist/src", "paths": { - "@onkernel/sdk/*": ["./dist/src/*"], - "@onkernel/sdk": ["./dist/src/index.ts"] + "@kernel/sdk/*": ["./dist/src/*"], + "@kernel/sdk": ["./dist/src/index.ts"] }, "noEmit": false, "declaration": true, diff --git a/tsconfig.json b/tsconfig.json index 73ce2185..57fc9d66 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -8,8 +8,8 @@ "moduleResolution": "node", "esModuleInterop": true, "paths": { - "@onkernel/sdk/*": ["./src/*"], - "@onkernel/sdk": ["./src/index.ts"] + "@kernel/sdk/*": ["./src/*"], + "@kernel/sdk": ["./src/index.ts"] }, "noEmit": true, From bfc88e838ec30a50bc42cb6fb7577751190dfb48 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 16 Jan 2026 16:15:43 +0000 Subject: [PATCH 247/551] feat: Support hot swap proxy on a session --- .stats.yml | 8 +- api.md | 2 + src/client.ts | 4 + src/resources/browsers/browsers.ts | 100 ++++++++++++++++++ src/resources/browsers/index.ts | 2 + src/resources/index.ts | 2 + tests/api-resources/browsers/browsers.test.ts | 12 +++ 7 files changed, 126 insertions(+), 4 deletions(-) diff --git a/.stats.yml b/.stats.yml index f0310d3b..330b531e 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 90 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-cc60c65c6bb0b8a8ea662cf758806e641790870ded35f6ffdb9f4801f3d29b15.yml -openapi_spec_hash: a1074e1bba578bcd5912512166ada0dc -config_hash: 7868d3397406c2974b6f058488aeefd6 +configured_endpoints: 91 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-4f5307643555b7917e8681b1966ae0b99f770cf59805e2f917ec7528edf11ba8.yml +openapi_spec_hash: 873a9aa3a88b6cec1ad94f848eeb1c45 +config_hash: 20337f7888852c165d099faa7589c90a diff --git a/api.md b/api.md index 48dff70b..45e2b0dd 100644 --- a/api.md +++ b/api.md @@ -67,12 +67,14 @@ Types: - Profile - BrowserCreateResponse - BrowserRetrieveResponse +- BrowserUpdateResponse - BrowserListResponse Methods: - client.browsers.create({ ...params }) -> BrowserCreateResponse - client.browsers.retrieve(id) -> BrowserRetrieveResponse +- client.browsers.update(id, { ...params }) -> BrowserUpdateResponse - client.browsers.list({ ...params }) -> BrowserListResponsesOffsetPagination - client.browsers.delete({ ...params }) -> void - client.browsers.deleteByID(id) -> void diff --git a/src/client.ts b/src/client.ts index 7a2c9431..6ba2b044 100644 --- a/src/client.ts +++ b/src/client.ts @@ -94,6 +94,8 @@ import { BrowserLoadExtensionsParams, BrowserPersistence, BrowserRetrieveResponse, + BrowserUpdateParams, + BrowserUpdateResponse, Browsers, Profile, } from './resources/browsers/browsers'; @@ -910,9 +912,11 @@ export declare namespace Kernel { type Profile as Profile, type BrowserCreateResponse as BrowserCreateResponse, type BrowserRetrieveResponse as BrowserRetrieveResponse, + type BrowserUpdateResponse as BrowserUpdateResponse, type BrowserListResponse as BrowserListResponse, type BrowserListResponsesOffsetPagination as BrowserListResponsesOffsetPagination, type BrowserCreateParams as BrowserCreateParams, + type BrowserUpdateParams as BrowserUpdateParams, type BrowserListParams as BrowserListParams, type BrowserDeleteParams as BrowserDeleteParams, type BrowserLoadExtensionsParams as BrowserLoadExtensionsParams, diff --git a/src/resources/browsers/browsers.ts b/src/resources/browsers/browsers.ts index c12665d0..a7453802 100644 --- a/src/resources/browsers/browsers.ts +++ b/src/resources/browsers/browsers.ts @@ -109,6 +109,20 @@ export class Browsers extends APIResource { return this._client.get(path`/browsers/${id}`, options); } + /** + * Update a browser session. + * + * @example + * ```ts + * const browser = await client.browsers.update( + * 'htzv5orfit78e1m2biiifpbv', + * ); + * ``` + */ + update(id: string, body: BrowserUpdateParams, options?: RequestOptions): APIPromise { + return this._client.patch(path`/browsers/${id}`, { body, ...options }); + } + /** * List all browser sessions with pagination support. Use include_deleted=true to * include soft-deleted sessions in the results. @@ -382,6 +396,82 @@ export interface BrowserRetrieveResponse { viewport?: Shared.BrowserViewport; } +export interface BrowserUpdateResponse { + /** + * Websocket URL for Chrome DevTools Protocol connections to the browser session + */ + cdp_ws_url: string; + + /** + * When the browser session was created. + */ + created_at: string; + + /** + * Whether the browser session is running in headless mode. + */ + headless: boolean; + + /** + * Unique identifier for the browser session + */ + session_id: string; + + /** + * Whether the browser session is running in stealth mode. + */ + stealth: boolean; + + /** + * The number of seconds of inactivity before the browser session is terminated. + */ + timeout_seconds: number; + + /** + * Remote URL for live viewing the browser session. Only available for non-headless + * browsers. + */ + browser_live_view_url?: string; + + /** + * When the browser session was soft-deleted. Only present for deleted sessions. + */ + deleted_at?: string; + + /** + * Whether the browser session is running in kiosk mode. + */ + kiosk_mode?: boolean; + + /** + * @deprecated DEPRECATED: Use timeout_seconds (up to 72 hours) and Profiles + * instead. + */ + persistence?: BrowserPersistence; + + /** + * Browser profile metadata. + */ + profile?: Profile; + + /** + * ID of the proxy associated with this browser session, if any. + */ + proxy_id?: string; + + /** + * Initial browser window size in pixels with optional refresh rate. If omitted, + * image defaults apply (1920x1080@25). Only specific viewport configurations are + * supported. The server will reject unsupported combinations. Supported + * resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25, 1440x900@25, + * 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will be + * automatically determined from the width and height if they match a supported + * configuration exactly. Note: Higher resolutions may affect the responsiveness of + * live view browser + */ + viewport?: Shared.BrowserViewport; +} + export interface BrowserListResponse { /** * Websocket URL for Chrome DevTools Protocol connections to the browser session @@ -528,6 +618,14 @@ export interface BrowserCreateParams { viewport?: Shared.BrowserViewport; } +export interface BrowserUpdateParams { + /** + * ID of the proxy to use. Omit to leave unchanged, set to empty string to remove + * proxy. + */ + proxy_id?: string | null; +} + export interface BrowserListParams extends OffsetPaginationParams { /** * When true, includes soft-deleted browser sessions in the results alongside @@ -578,9 +676,11 @@ export declare namespace Browsers { type Profile as Profile, type BrowserCreateResponse as BrowserCreateResponse, type BrowserRetrieveResponse as BrowserRetrieveResponse, + type BrowserUpdateResponse as BrowserUpdateResponse, type BrowserListResponse as BrowserListResponse, type BrowserListResponsesOffsetPagination as BrowserListResponsesOffsetPagination, type BrowserCreateParams as BrowserCreateParams, + type BrowserUpdateParams as BrowserUpdateParams, type BrowserListParams as BrowserListParams, type BrowserDeleteParams as BrowserDeleteParams, type BrowserLoadExtensionsParams as BrowserLoadExtensionsParams, diff --git a/src/resources/browsers/index.ts b/src/resources/browsers/index.ts index fc8f7c57..d00c32c5 100644 --- a/src/resources/browsers/index.ts +++ b/src/resources/browsers/index.ts @@ -6,8 +6,10 @@ export { type Profile, type BrowserCreateResponse, type BrowserRetrieveResponse, + type BrowserUpdateResponse, type BrowserListResponse, type BrowserCreateParams, + type BrowserUpdateParams, type BrowserListParams, type BrowserDeleteParams, type BrowserLoadExtensionsParams, diff --git a/src/resources/index.ts b/src/resources/index.ts index f4877266..e95e4ae8 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -25,8 +25,10 @@ export { type Profile, type BrowserCreateResponse, type BrowserRetrieveResponse, + type BrowserUpdateResponse, type BrowserListResponse, type BrowserCreateParams, + type BrowserUpdateParams, type BrowserListParams, type BrowserDeleteParams, type BrowserLoadExtensionsParams, diff --git a/tests/api-resources/browsers/browsers.test.ts b/tests/api-resources/browsers/browsers.test.ts index a9bc8254..97035144 100644 --- a/tests/api-resources/browsers/browsers.test.ts +++ b/tests/api-resources/browsers/browsers.test.ts @@ -62,6 +62,18 @@ describe('resource browsers', () => { expect(dataAndResponse.response).toBe(rawResponse); }); + // Prism tests are disabled + test.skip('update', async () => { + const responsePromise = client.browsers.update('htzv5orfit78e1m2biiifpbv', {}); + 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); + }); + // Prism tests are disabled test.skip('list', async () => { const responsePromise = client.browsers.list(); From 4ac557d3398ea1aa8cdef22ad5cf791c7d317390 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 16 Jan 2026 17:06:11 +0000 Subject: [PATCH 248/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index fc5553b0..c84411f5 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.24.0" + ".": "0.26.0" } diff --git a/package.json b/package.json index 3628a29f..56082e45 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@kernel/sdk", - "version": "0.24.0", + "version": "0.26.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 7434729b..aa25151e 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.24.0'; // x-release-please-version +export const VERSION = '0.26.0'; // x-release-please-version From 66ec32cb9bafec58940435091f02538753a915c1 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 16 Jan 2026 20:10:30 +0000 Subject: [PATCH 249/551] feat: Auth agents auth check URL --- .stats.yml | 4 ++-- src/resources/agents/auth/auth.ts | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 330b531e..b78a34d4 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 91 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-4f5307643555b7917e8681b1966ae0b99f770cf59805e2f917ec7528edf11ba8.yml -openapi_spec_hash: 873a9aa3a88b6cec1ad94f848eeb1c45 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-fc2c80b398a8dd511010ae7cda5e21c353e388ee130aa288974b47af4208b5b8.yml +openapi_spec_hash: 5e06586dbbb9fce12b907f4e32497006 config_hash: 20337f7888852c165d099faa7589c90a diff --git a/src/resources/agents/auth/auth.ts b/src/resources/agents/auth/auth.ts index a02a64f8..ac693566 100644 --- a/src/resources/agents/auth/auth.ts +++ b/src/resources/agents/auth/auth.ts @@ -286,6 +286,12 @@ export interface AuthAgent { * When the last authentication check was performed */ last_auth_check_at?: string; + + /** + * URL where the browser landed after successful login. Query parameters and + * fragments are stripped for privacy. + */ + post_login_url?: string; } /** From f0619e46ba2d856c82ea0cf9281b3305754a621a Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 17 Jan 2026 04:33:58 +0000 Subject: [PATCH 250/551] chore(internal): update `actions/checkout` version --- .github/workflows/ci.yml | 6 +++--- .github/workflows/publish-npm.yml | 2 +- .github/workflows/release-doctor.yml | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cc341d93..f79a4b25 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,7 +19,7 @@ jobs: runs-on: ${{ github.repository == 'stainless-sdks/kernel-typescript' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} if: github.event_name == 'push' || github.event.pull_request.head.repo.fork steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Set up Node uses: actions/setup-node@v4 @@ -41,7 +41,7 @@ jobs: contents: read id-token: write steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Set up Node uses: actions/setup-node@v4 @@ -74,7 +74,7 @@ jobs: runs-on: ${{ github.repository == 'stainless-sdks/kernel-typescript' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} if: github.event_name == 'push' || github.event.pull_request.head.repo.fork steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Set up Node uses: actions/setup-node@v4 diff --git a/.github/workflows/publish-npm.yml b/.github/workflows/publish-npm.yml index 9032e71c..a6604782 100644 --- a/.github/workflows/publish-npm.yml +++ b/.github/workflows/publish-npm.yml @@ -14,7 +14,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Set up Node uses: actions/setup-node@v3 diff --git a/.github/workflows/release-doctor.yml b/.github/workflows/release-doctor.yml index 8e587753..588ae1bc 100644 --- a/.github/workflows/release-doctor.yml +++ b/.github/workflows/release-doctor.yml @@ -12,7 +12,7 @@ jobs: if: github.repository == 'kernel/kernel-node-sdk' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch' || startsWith(github.head_ref, 'release-please') || github.head_ref == 'next') steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Check release environment run: | From 4069634b476ad8343e3523b91f076df0a8f47471 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 17 Jan 2026 19:28:54 +0000 Subject: [PATCH 251/551] fix(stainless): use @onkernel/sdk package name for TypeScript SDK --- .stats.yml | 2 +- CONTRIBUTING.md | 4 +-- README.md | 26 +++++++++---------- eslint.config.mjs | 2 +- jest.config.ts | 4 +-- package.json | 2 +- scripts/build | 6 ++--- src/client.ts | 6 ++--- tests/api-resources/agents/auth/auth.test.ts | 2 +- .../agents/auth/invocations.test.ts | 2 +- tests/api-resources/apps.test.ts | 2 +- tests/api-resources/browser-pools.test.ts | 2 +- tests/api-resources/browsers/browsers.test.ts | 2 +- tests/api-resources/browsers/computer.test.ts | 2 +- tests/api-resources/browsers/fs/fs.test.ts | 2 +- tests/api-resources/browsers/fs/watch.test.ts | 2 +- tests/api-resources/browsers/logs.test.ts | 2 +- .../api-resources/browsers/playwright.test.ts | 2 +- tests/api-resources/browsers/process.test.ts | 2 +- tests/api-resources/browsers/replays.test.ts | 2 +- tests/api-resources/credentials.test.ts | 2 +- tests/api-resources/deployments.test.ts | 2 +- tests/api-resources/extensions.test.ts | 2 +- tests/api-resources/invocations.test.ts | 2 +- tests/api-resources/profiles.test.ts | 2 +- tests/api-resources/proxies.test.ts | 2 +- tests/base64.test.ts | 2 +- tests/buildHeaders.test.ts | 2 +- tests/form.test.ts | 4 +-- tests/index.test.ts | 12 ++++----- tests/internal/decoders/line.test.ts | 2 +- tests/path.test.ts | 2 +- tests/streaming.test.ts | 4 +-- tests/stringifyQuery.test.ts | 2 +- tests/uploads.test.ts | 6 ++--- tsconfig.build.json | 4 +-- tsconfig.json | 4 +-- 37 files changed, 66 insertions(+), 66 deletions(-) diff --git a/.stats.yml b/.stats.yml index b78a34d4..2857ba88 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 91 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-fc2c80b398a8dd511010ae7cda5e21c353e388ee130aa288974b47af4208b5b8.yml openapi_spec_hash: 5e06586dbbb9fce12b907f4e32497006 -config_hash: 20337f7888852c165d099faa7589c90a +config_hash: cc7fdd701d995d4b3456d77041c604cf diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6434ec2b..30dc1266 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -55,12 +55,12 @@ $ cd kernel-node-sdk # With yarn $ yarn link $ cd ../my-package -$ yarn link @kernel/sdk +$ yarn link @onkernel/sdk # With pnpm $ pnpm link --global $ cd ../my-package -$ pnpm link -—global @kernel/sdk +$ pnpm link -—global @onkernel/sdk ``` ## Running tests diff --git a/README.md b/README.md index 17efd10f..6e156a27 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,17 @@ # Kernel TypeScript API Library -[![NPM version]()](https://npmjs.org/package/@kernel/sdk) ![npm bundle size](https://img.shields.io/bundlephobia/minzip/@kernel/sdk) +[![NPM version]()](https://npmjs.org/package/@onkernel/sdk) ![npm bundle size](https://img.shields.io/bundlephobia/minzip/@onkernel/sdk) This library provides convenient access to the Kernel REST API from server-side TypeScript or JavaScript. -The REST API documentation can be found on [docs.kernel.com](https://docs.kernel.com). The full API of this library can be found in [api.md](api.md). +The REST API documentation can be found on [kernel.sh](https://kernel.sh/docs). The full API of this library can be found in [api.md](api.md). It is generated with [Stainless](https://www.stainless.com/). ## Installation ```sh -npm install @kernel/sdk +npm install @onkernel/sdk ``` ## Usage @@ -20,7 +20,7 @@ The full API of this library can be found in [api.md](api.md). ```js -import Kernel from '@kernel/sdk'; +import Kernel from '@onkernel/sdk'; const client = new Kernel({ apiKey: process.env['KERNEL_API_KEY'], // This is the default and can be omitted @@ -38,7 +38,7 @@ This library includes TypeScript definitions for all request params and response ```ts -import Kernel from '@kernel/sdk'; +import Kernel from '@onkernel/sdk'; const client = new Kernel({ apiKey: process.env['KERNEL_API_KEY'], // This is the default and can be omitted @@ -62,7 +62,7 @@ Request parameters that correspond to file uploads can be passed in many differe ```ts import fs from 'fs'; -import Kernel, { toFile } from '@kernel/sdk'; +import Kernel, { toFile } from '@onkernel/sdk'; const client = new Kernel(); @@ -227,7 +227,7 @@ The log level can be configured in two ways: 2. Using the `logLevel` client option (overrides the environment variable if set) ```ts -import Kernel from '@kernel/sdk'; +import Kernel from '@onkernel/sdk'; const client = new Kernel({ logLevel: 'debug', // Show all log messages @@ -255,7 +255,7 @@ When providing a custom logger, the `logLevel` option still controls which messa below the configured level will not be sent to your logger. ```ts -import Kernel from '@kernel/sdk'; +import Kernel from '@onkernel/sdk'; import pino from 'pino'; const logger = pino(); @@ -324,7 +324,7 @@ globalThis.fetch = fetch; Or pass it to the client: ```ts -import Kernel from '@kernel/sdk'; +import Kernel from '@onkernel/sdk'; import fetch from 'my-fetch'; const client = new Kernel({ fetch }); @@ -335,7 +335,7 @@ const client = new Kernel({ fetch }); If you want to set custom `fetch` options without overriding the `fetch` function, you can provide a `fetchOptions` object when instantiating the client or making a request. (Request-specific options override client options.) ```ts -import Kernel from '@kernel/sdk'; +import Kernel from '@onkernel/sdk'; const client = new Kernel({ fetchOptions: { @@ -352,7 +352,7 @@ options to requests: **Node** [[docs](https://github.com/nodejs/undici/blob/main/docs/docs/api/ProxyAgent.md#example---proxyagent-with-fetch)] ```ts -import Kernel from '@kernel/sdk'; +import Kernel from '@onkernel/sdk'; import * as undici from 'undici'; const proxyAgent = new undici.ProxyAgent('http://localhost:8888'); @@ -366,7 +366,7 @@ const client = new Kernel({ **Bun** [[docs](https://bun.sh/guides/http/proxy)] ```ts -import Kernel from '@kernel/sdk'; +import Kernel from '@onkernel/sdk'; const client = new Kernel({ fetchOptions: { @@ -378,7 +378,7 @@ const client = new Kernel({ **Deno** [[docs](https://docs.deno.com/api/deno/~/Deno.createHttpClient)] ```ts -import Kernel from 'npm:@kernel/sdk'; +import Kernel from 'npm:@onkernel/sdk'; const httpClient = Deno.createHttpClient({ proxy: { url: 'http://localhost:8888' } }); const client = new Kernel({ diff --git a/eslint.config.mjs b/eslint.config.mjs index b9c449d2..341aac52 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -25,7 +25,7 @@ export default tseslint.config( { patterns: [ { - regex: '^@kernel/sdk(/.*)?', + regex: '^@onkernel/sdk(/.*)?', message: 'Use a relative import, not a package import.', }, ], diff --git a/jest.config.ts b/jest.config.ts index 091bd928..f21115cf 100644 --- a/jest.config.ts +++ b/jest.config.ts @@ -7,8 +7,8 @@ const config: JestConfigWithTsJest = { '^.+\\.(t|j)sx?$': ['@swc/jest', { sourceMaps: 'inline' }], }, moduleNameMapper: { - '^@kernel/sdk$': '/src/index.ts', - '^@kernel/sdk/(.*)$': '/src/$1', + '^@onkernel/sdk$': '/src/index.ts', + '^@onkernel/sdk/(.*)$': '/src/$1', }, modulePathIgnorePatterns: [ '/ecosystem-tests/', diff --git a/package.json b/package.json index 56082e45..76168f14 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "@kernel/sdk", + "name": "@onkernel/sdk", "version": "0.26.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", diff --git a/scripts/build b/scripts/build index c92df216..a008cb00 100755 --- a/scripts/build +++ b/scripts/build @@ -8,7 +8,7 @@ node scripts/utils/check-version.cjs # Build into dist and will publish the package from there, # so that src/resources/foo.ts becomes /resources/foo.js -# This way importing from `"@kernel/sdk/resources/foo"` works +# This way importing from `"@onkernel/sdk/resources/foo"` works # even with `"moduleResolution": "node"` rm -rf dist; mkdir dist @@ -42,8 +42,8 @@ node scripts/utils/postprocess-files.cjs # make sure that nothing crashes when we require the output CJS or # import the output ESM -(cd dist && node -e 'require("@kernel/sdk")') -(cd dist && node -e 'import("@kernel/sdk")' --input-type=module) +(cd dist && node -e 'require("@onkernel/sdk")') +(cd dist && node -e 'import("@onkernel/sdk")' --input-type=module) if [ -e ./scripts/build-deno ] then diff --git a/src/client.ts b/src/client.ts index 6ba2b044..0ea23f5b 100644 --- a/src/client.ts +++ b/src/client.ts @@ -113,7 +113,7 @@ import { import { isEmptyObj } from './internal/utils/values'; const environments = { - production: 'https://api.kernel.com/', + production: 'https://api.onkernel.com/', development: 'https://localhost:3001/', }; type Environment = keyof typeof environments; @@ -128,7 +128,7 @@ export interface ClientOptions { * Specifies the environment to use for the API. * * Each environment maps to a different base URL: - * - `production` corresponds to `https://api.kernel.com/` + * - `production` corresponds to `https://api.onkernel.com/` * - `development` corresponds to `https://localhost:3001/` */ environment?: Environment | undefined; @@ -225,7 +225,7 @@ export class Kernel { * * @param {string | undefined} [opts.apiKey=process.env['KERNEL_API_KEY'] ?? undefined] * @param {Environment} [opts.environment=production] - Specifies the environment URL to use for the API. - * @param {string} [opts.baseURL=process.env['KERNEL_BASE_URL'] ?? https://api.kernel.com/] - Override the default base URL for the API. + * @param {string} [opts.baseURL=process.env['KERNEL_BASE_URL'] ?? https://api.onkernel.com/] - Override the default base URL for the API. * @param {number} [opts.timeout=1 minute] - The maximum amount of time (in milliseconds) the client will wait for a response before timing out. * @param {MergedRequestInit} [opts.fetchOptions] - Additional `RequestInit` options to be passed to `fetch` calls. * @param {Fetch} [opts.fetch] - Specify a custom `fetch` function implementation. diff --git a/tests/api-resources/agents/auth/auth.test.ts b/tests/api-resources/agents/auth/auth.test.ts index ea592ca2..1f8a9237 100644 --- a/tests/api-resources/agents/auth/auth.test.ts +++ b/tests/api-resources/agents/auth/auth.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Kernel from '@kernel/sdk'; +import Kernel from '@onkernel/sdk'; const client = new Kernel({ apiKey: 'My API Key', diff --git a/tests/api-resources/agents/auth/invocations.test.ts b/tests/api-resources/agents/auth/invocations.test.ts index de72d35b..b30496c8 100644 --- a/tests/api-resources/agents/auth/invocations.test.ts +++ b/tests/api-resources/agents/auth/invocations.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Kernel from '@kernel/sdk'; +import Kernel from '@onkernel/sdk'; const client = new Kernel({ apiKey: 'My API Key', diff --git a/tests/api-resources/apps.test.ts b/tests/api-resources/apps.test.ts index 68cc9661..d1a35f28 100644 --- a/tests/api-resources/apps.test.ts +++ b/tests/api-resources/apps.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Kernel from '@kernel/sdk'; +import Kernel from '@onkernel/sdk'; const client = new Kernel({ apiKey: 'My API Key', diff --git a/tests/api-resources/browser-pools.test.ts b/tests/api-resources/browser-pools.test.ts index 148b4395..97737bbb 100644 --- a/tests/api-resources/browser-pools.test.ts +++ b/tests/api-resources/browser-pools.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Kernel from '@kernel/sdk'; +import Kernel from '@onkernel/sdk'; const client = new Kernel({ apiKey: 'My API Key', diff --git a/tests/api-resources/browsers/browsers.test.ts b/tests/api-resources/browsers/browsers.test.ts index 97035144..f6d629de 100644 --- a/tests/api-resources/browsers/browsers.test.ts +++ b/tests/api-resources/browsers/browsers.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Kernel, { toFile } from '@kernel/sdk'; +import Kernel, { toFile } from '@onkernel/sdk'; const client = new Kernel({ apiKey: 'My API Key', diff --git a/tests/api-resources/browsers/computer.test.ts b/tests/api-resources/browsers/computer.test.ts index acdc93dc..b95f0fa7 100644 --- a/tests/api-resources/browsers/computer.test.ts +++ b/tests/api-resources/browsers/computer.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Kernel from '@kernel/sdk'; +import Kernel from '@onkernel/sdk'; const client = new Kernel({ apiKey: 'My API Key', diff --git a/tests/api-resources/browsers/fs/fs.test.ts b/tests/api-resources/browsers/fs/fs.test.ts index ebb6d481..92a0c9ce 100644 --- a/tests/api-resources/browsers/fs/fs.test.ts +++ b/tests/api-resources/browsers/fs/fs.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Kernel, { toFile } from '@kernel/sdk'; +import Kernel, { toFile } from '@onkernel/sdk'; const client = new Kernel({ apiKey: 'My API Key', diff --git a/tests/api-resources/browsers/fs/watch.test.ts b/tests/api-resources/browsers/fs/watch.test.ts index 0e4e3a6c..47ddfb80 100644 --- a/tests/api-resources/browsers/fs/watch.test.ts +++ b/tests/api-resources/browsers/fs/watch.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Kernel from '@kernel/sdk'; +import Kernel from '@onkernel/sdk'; const client = new Kernel({ apiKey: 'My API Key', diff --git a/tests/api-resources/browsers/logs.test.ts b/tests/api-resources/browsers/logs.test.ts index 3fb0227d..0fa405ec 100644 --- a/tests/api-resources/browsers/logs.test.ts +++ b/tests/api-resources/browsers/logs.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Kernel from '@kernel/sdk'; +import Kernel from '@onkernel/sdk'; const client = new Kernel({ apiKey: 'My API Key', diff --git a/tests/api-resources/browsers/playwright.test.ts b/tests/api-resources/browsers/playwright.test.ts index b2a6fe55..5c45947d 100644 --- a/tests/api-resources/browsers/playwright.test.ts +++ b/tests/api-resources/browsers/playwright.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Kernel from '@kernel/sdk'; +import Kernel from '@onkernel/sdk'; const client = new Kernel({ apiKey: 'My API Key', diff --git a/tests/api-resources/browsers/process.test.ts b/tests/api-resources/browsers/process.test.ts index c428741a..c608e246 100644 --- a/tests/api-resources/browsers/process.test.ts +++ b/tests/api-resources/browsers/process.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Kernel from '@kernel/sdk'; +import Kernel from '@onkernel/sdk'; const client = new Kernel({ apiKey: 'My API Key', diff --git a/tests/api-resources/browsers/replays.test.ts b/tests/api-resources/browsers/replays.test.ts index 3484b8c6..d0ee498b 100644 --- a/tests/api-resources/browsers/replays.test.ts +++ b/tests/api-resources/browsers/replays.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Kernel from '@kernel/sdk'; +import Kernel from '@onkernel/sdk'; const client = new Kernel({ apiKey: 'My API Key', diff --git a/tests/api-resources/credentials.test.ts b/tests/api-resources/credentials.test.ts index f0e11b65..d825b4e0 100644 --- a/tests/api-resources/credentials.test.ts +++ b/tests/api-resources/credentials.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Kernel from '@kernel/sdk'; +import Kernel from '@onkernel/sdk'; const client = new Kernel({ apiKey: 'My API Key', diff --git a/tests/api-resources/deployments.test.ts b/tests/api-resources/deployments.test.ts index bbc3793e..b3f0c201 100644 --- a/tests/api-resources/deployments.test.ts +++ b/tests/api-resources/deployments.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Kernel from '@kernel/sdk'; +import Kernel from '@onkernel/sdk'; const client = new Kernel({ apiKey: 'My API Key', diff --git a/tests/api-resources/extensions.test.ts b/tests/api-resources/extensions.test.ts index eaeb5879..515415fe 100644 --- a/tests/api-resources/extensions.test.ts +++ b/tests/api-resources/extensions.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Kernel, { toFile } from '@kernel/sdk'; +import Kernel, { toFile } from '@onkernel/sdk'; const client = new Kernel({ apiKey: 'My API Key', diff --git a/tests/api-resources/invocations.test.ts b/tests/api-resources/invocations.test.ts index d8f4e5df..b8c80247 100644 --- a/tests/api-resources/invocations.test.ts +++ b/tests/api-resources/invocations.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Kernel from '@kernel/sdk'; +import Kernel from '@onkernel/sdk'; const client = new Kernel({ apiKey: 'My API Key', diff --git a/tests/api-resources/profiles.test.ts b/tests/api-resources/profiles.test.ts index 51a2925d..9fe686a5 100644 --- a/tests/api-resources/profiles.test.ts +++ b/tests/api-resources/profiles.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Kernel from '@kernel/sdk'; +import Kernel from '@onkernel/sdk'; const client = new Kernel({ apiKey: 'My API Key', diff --git a/tests/api-resources/proxies.test.ts b/tests/api-resources/proxies.test.ts index afe5fcef..1086c4fe 100644 --- a/tests/api-resources/proxies.test.ts +++ b/tests/api-resources/proxies.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import Kernel from '@kernel/sdk'; +import Kernel from '@onkernel/sdk'; const client = new Kernel({ apiKey: 'My API Key', diff --git a/tests/base64.test.ts b/tests/base64.test.ts index 9b722466..2e2538eb 100644 --- a/tests/base64.test.ts +++ b/tests/base64.test.ts @@ -1,4 +1,4 @@ -import { fromBase64, toBase64 } from '@kernel/sdk/internal/utils/base64'; +import { fromBase64, toBase64 } from '@onkernel/sdk/internal/utils/base64'; describe.each(['Buffer', 'atob'])('with %s', (mode) => { let originalBuffer: BufferConstructor; diff --git a/tests/buildHeaders.test.ts b/tests/buildHeaders.test.ts index ec9447af..039a8008 100644 --- a/tests/buildHeaders.test.ts +++ b/tests/buildHeaders.test.ts @@ -1,5 +1,5 @@ import { inspect } from 'node:util'; -import { buildHeaders, type HeadersLike, type NullableHeaders } from '@kernel/sdk/internal/headers'; +import { buildHeaders, type HeadersLike, type NullableHeaders } from '@onkernel/sdk/internal/headers'; function inspectNullableHeaders(headers: NullableHeaders) { return `NullableHeaders {${[ diff --git a/tests/form.test.ts b/tests/form.test.ts index 68fda151..56981ca7 100644 --- a/tests/form.test.ts +++ b/tests/form.test.ts @@ -1,5 +1,5 @@ -import { multipartFormRequestOptions, createForm } from '@kernel/sdk/internal/uploads'; -import { toFile } from '@kernel/sdk/core/uploads'; +import { multipartFormRequestOptions, createForm } from '@onkernel/sdk/internal/uploads'; +import { toFile } from '@onkernel/sdk/core/uploads'; describe('form data validation', () => { test('valid values do not error', async () => { diff --git a/tests/index.test.ts b/tests/index.test.ts index 39fcf67a..90d04c42 100644 --- a/tests/index.test.ts +++ b/tests/index.test.ts @@ -1,10 +1,10 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { APIPromise } from '@kernel/sdk/core/api-promise'; +import { APIPromise } from '@onkernel/sdk/core/api-promise'; import util from 'node:util'; -import Kernel from '@kernel/sdk'; -import { APIUserAbortError } from '@kernel/sdk'; +import Kernel from '@onkernel/sdk'; +import { APIUserAbortError } from '@onkernel/sdk'; const defaultFetch = fetch; describe('instantiate client', () => { @@ -322,13 +322,13 @@ describe('instantiate client', () => { test('empty env variable', () => { process.env['KERNEL_BASE_URL'] = ''; // empty const client = new Kernel({ apiKey: 'My API Key' }); - expect(client.baseURL).toEqual('https://api.kernel.com/'); + expect(client.baseURL).toEqual('https://api.onkernel.com/'); }); test('blank env variable', () => { process.env['KERNEL_BASE_URL'] = ' '; // blank const client = new Kernel({ apiKey: 'My API Key' }); - expect(client.baseURL).toEqual('https://api.kernel.com/'); + expect(client.baseURL).toEqual('https://api.onkernel.com/'); }); test('env variable with environment', () => { @@ -345,7 +345,7 @@ describe('instantiate client', () => { baseURL: null, environment: 'production', }); - expect(client.baseURL).toEqual('https://api.kernel.com/'); + expect(client.baseURL).toEqual('https://api.onkernel.com/'); }); test('in request options', () => { diff --git a/tests/internal/decoders/line.test.ts b/tests/internal/decoders/line.test.ts index 9f835645..11466788 100644 --- a/tests/internal/decoders/line.test.ts +++ b/tests/internal/decoders/line.test.ts @@ -1,4 +1,4 @@ -import { findDoubleNewlineIndex, LineDecoder } from '@kernel/sdk/internal/decoders/line'; +import { findDoubleNewlineIndex, LineDecoder } from '@onkernel/sdk/internal/decoders/line'; function decodeChunks(chunks: string[], { flush }: { flush: boolean } = { flush: false }): string[] { const decoder = new LineDecoder(); diff --git a/tests/path.test.ts b/tests/path.test.ts index 247f0c8f..b209e96f 100644 --- a/tests/path.test.ts +++ b/tests/path.test.ts @@ -1,4 +1,4 @@ -import { createPathTagFunction, encodeURIPath } from '@kernel/sdk/internal/utils/path'; +import { createPathTagFunction, encodeURIPath } from '@onkernel/sdk/internal/utils/path'; import { inspect } from 'node:util'; import { runInNewContext } from 'node:vm'; diff --git a/tests/streaming.test.ts b/tests/streaming.test.ts index ac5aa48f..0124e210 100644 --- a/tests/streaming.test.ts +++ b/tests/streaming.test.ts @@ -1,6 +1,6 @@ import assert from 'assert'; -import { _iterSSEMessages } from '@kernel/sdk/core/streaming'; -import { ReadableStreamFrom } from '@kernel/sdk/internal/shims'; +import { _iterSSEMessages } from '@onkernel/sdk/core/streaming'; +import { ReadableStreamFrom } from '@onkernel/sdk/internal/shims'; describe('streaming decoding', () => { test('basic', async () => { diff --git a/tests/stringifyQuery.test.ts b/tests/stringifyQuery.test.ts index 05e5cc3c..1170f010 100644 --- a/tests/stringifyQuery.test.ts +++ b/tests/stringifyQuery.test.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { Kernel } from '@kernel/sdk'; +import { Kernel } from '@onkernel/sdk'; const { stringifyQuery } = Kernel.prototype as any; diff --git a/tests/uploads.test.ts b/tests/uploads.test.ts index df09f708..ba84b0c1 100644 --- a/tests/uploads.test.ts +++ b/tests/uploads.test.ts @@ -1,6 +1,6 @@ import fs from 'fs'; -import type { ResponseLike } from '@kernel/sdk/internal/to-file'; -import { toFile } from '@kernel/sdk/core/uploads'; +import type { ResponseLike } from '@onkernel/sdk/internal/to-file'; +import { toFile } from '@onkernel/sdk/core/uploads'; import { File } from 'node:buffer'; class MyClass { @@ -97,7 +97,7 @@ describe('missing File error message', () => { }); test('is thrown', async () => { - const uploads = await import('@kernel/sdk/core/uploads'); + const uploads = await import('@onkernel/sdk/core/uploads'); await expect( uploads.toFile(mockResponse({ url: 'https://example.com/my/audio.mp3' })), ).rejects.toMatchInlineSnapshot( diff --git a/tsconfig.build.json b/tsconfig.build.json index f161b5d3..762269d0 100644 --- a/tsconfig.build.json +++ b/tsconfig.build.json @@ -5,8 +5,8 @@ "compilerOptions": { "rootDir": "./dist/src", "paths": { - "@kernel/sdk/*": ["./dist/src/*"], - "@kernel/sdk": ["./dist/src/index.ts"] + "@onkernel/sdk/*": ["./dist/src/*"], + "@onkernel/sdk": ["./dist/src/index.ts"] }, "noEmit": false, "declaration": true, diff --git a/tsconfig.json b/tsconfig.json index 57fc9d66..73ce2185 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -8,8 +8,8 @@ "moduleResolution": "node", "esModuleInterop": true, "paths": { - "@kernel/sdk/*": ["./src/*"], - "@kernel/sdk": ["./src/index.ts"] + "@onkernel/sdk/*": ["./src/*"], + "@onkernel/sdk": ["./src/index.ts"] }, "noEmit": true, From 08b8d27df598e1b67b5140c5b3ae42c0d5c3710c Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 17 Jan 2026 21:34:41 +0000 Subject: [PATCH 252/551] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 2857ba88..8e09c0a1 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 91 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-fc2c80b398a8dd511010ae7cda5e21c353e388ee130aa288974b47af4208b5b8.yml -openapi_spec_hash: 5e06586dbbb9fce12b907f4e32497006 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-1e490dbef30dfa53ccba72524fcba4079f244f2530a4f770c00f8fee707eaa72.yml +openapi_spec_hash: 1fd15429610959f19aed6d3cb170ab9e config_hash: cc7fdd701d995d4b3456d77041c604cf From 8b23b2b7e5a3af406f80c9c99a55232138262942 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sun, 18 Jan 2026 22:57:05 +0000 Subject: [PATCH 253/551] feat(dashboard): add browser replays support for past browsers --- .stats.yml | 4 +-- api.md | 2 +- src/client.ts | 2 ++ src/resources/browsers/browsers.ts | 30 +++++++++++++++---- src/resources/browsers/index.ts | 1 + src/resources/index.ts | 1 + tests/api-resources/browsers/browsers.test.ts | 13 ++++++++ 7 files changed, 44 insertions(+), 9 deletions(-) diff --git a/.stats.yml b/.stats.yml index 8e09c0a1..37fa5b76 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 91 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-1e490dbef30dfa53ccba72524fcba4079f244f2530a4f770c00f8fee707eaa72.yml -openapi_spec_hash: 1fd15429610959f19aed6d3cb170ab9e +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-68729f2ff40476377ead9019c18ea140fc4efbc2e68d7c4fc323bd61ae81f768.yml +openapi_spec_hash: 9eec61481f9059b5fedc13abc3e39338 config_hash: cc7fdd701d995d4b3456d77041c604cf diff --git a/api.md b/api.md index 45e2b0dd..d86a8802 100644 --- a/api.md +++ b/api.md @@ -73,7 +73,7 @@ Types: Methods: - client.browsers.create({ ...params }) -> BrowserCreateResponse -- client.browsers.retrieve(id) -> BrowserRetrieveResponse +- client.browsers.retrieve(id, { ...params }) -> BrowserRetrieveResponse - client.browsers.update(id, { ...params }) -> BrowserUpdateResponse - client.browsers.list({ ...params }) -> BrowserListResponsesOffsetPagination - client.browsers.delete({ ...params }) -> void diff --git a/src/client.ts b/src/client.ts index 0ea23f5b..36b42f10 100644 --- a/src/client.ts +++ b/src/client.ts @@ -93,6 +93,7 @@ import { BrowserListResponsesOffsetPagination, BrowserLoadExtensionsParams, BrowserPersistence, + BrowserRetrieveParams, BrowserRetrieveResponse, BrowserUpdateParams, BrowserUpdateResponse, @@ -916,6 +917,7 @@ export declare namespace Kernel { type BrowserListResponse as BrowserListResponse, type BrowserListResponsesOffsetPagination as BrowserListResponsesOffsetPagination, type BrowserCreateParams as BrowserCreateParams, + type BrowserRetrieveParams as BrowserRetrieveParams, type BrowserUpdateParams as BrowserUpdateParams, type BrowserListParams as BrowserListParams, type BrowserDeleteParams as BrowserDeleteParams, diff --git a/src/resources/browsers/browsers.ts b/src/resources/browsers/browsers.ts index a7453802..040c783a 100644 --- a/src/resources/browsers/browsers.ts +++ b/src/resources/browsers/browsers.ts @@ -105,8 +105,12 @@ export class Browsers extends APIResource { * ); * ``` */ - retrieve(id: string, options?: RequestOptions): APIPromise { - return this._client.get(path`/browsers/${id}`, options); + retrieve( + id: string, + query: BrowserRetrieveParams | null | undefined = {}, + options?: RequestOptions, + ): APIPromise { + return this._client.get(path`/browsers/${id}`, { query, ...options }); } /** @@ -124,8 +128,8 @@ export class Browsers extends APIResource { } /** - * List all browser sessions with pagination support. Use include_deleted=true to - * include soft-deleted sessions in the results. + * List all browser sessions with pagination support. Use status parameter to + * filter by session state. * * @example * ```ts @@ -618,6 +622,13 @@ export interface BrowserCreateParams { viewport?: Shared.BrowserViewport; } +export interface BrowserRetrieveParams { + /** + * When true, includes soft-deleted browser sessions in the lookup. + */ + include_deleted?: boolean; +} + export interface BrowserUpdateParams { /** * ID of the proxy to use. Omit to leave unchanged, set to empty string to remove @@ -628,10 +639,16 @@ export interface BrowserUpdateParams { export interface BrowserListParams extends OffsetPaginationParams { /** - * When true, includes soft-deleted browser sessions in the results alongside - * active sessions. + * Deprecated: Use status=all instead. When true, includes soft-deleted browser + * sessions in the results alongside active sessions. */ include_deleted?: boolean; + + /** + * Filter sessions by status. "active" returns only active sessions (default), + * "deleted" returns only soft-deleted sessions, "all" returns both. + */ + status?: 'active' | 'deleted' | 'all'; } export interface BrowserDeleteParams { @@ -680,6 +697,7 @@ export declare namespace Browsers { type BrowserListResponse as BrowserListResponse, type BrowserListResponsesOffsetPagination as BrowserListResponsesOffsetPagination, type BrowserCreateParams as BrowserCreateParams, + type BrowserRetrieveParams as BrowserRetrieveParams, type BrowserUpdateParams as BrowserUpdateParams, type BrowserListParams as BrowserListParams, type BrowserDeleteParams as BrowserDeleteParams, diff --git a/src/resources/browsers/index.ts b/src/resources/browsers/index.ts index d00c32c5..046c1b24 100644 --- a/src/resources/browsers/index.ts +++ b/src/resources/browsers/index.ts @@ -9,6 +9,7 @@ export { type BrowserUpdateResponse, type BrowserListResponse, type BrowserCreateParams, + type BrowserRetrieveParams, type BrowserUpdateParams, type BrowserListParams, type BrowserDeleteParams, diff --git a/src/resources/index.ts b/src/resources/index.ts index e95e4ae8..1b7282a6 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -28,6 +28,7 @@ export { type BrowserUpdateResponse, type BrowserListResponse, type BrowserCreateParams, + type BrowserRetrieveParams, type BrowserUpdateParams, type BrowserListParams, type BrowserDeleteParams, diff --git a/tests/api-resources/browsers/browsers.test.ts b/tests/api-resources/browsers/browsers.test.ts index f6d629de..51fecec7 100644 --- a/tests/api-resources/browsers/browsers.test.ts +++ b/tests/api-resources/browsers/browsers.test.ts @@ -62,6 +62,18 @@ describe('resource browsers', () => { expect(dataAndResponse.response).toBe(rawResponse); }); + // Prism tests are disabled + test.skip('retrieve: 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.retrieve( + 'htzv5orfit78e1m2biiifpbv', + { include_deleted: true }, + { path: '/_stainless_unknown_path' }, + ), + ).rejects.toThrow(Kernel.NotFoundError); + }); + // Prism tests are disabled test.skip('update', async () => { const responsePromise = client.browsers.update('htzv5orfit78e1m2biiifpbv', {}); @@ -95,6 +107,7 @@ describe('resource browsers', () => { include_deleted: true, limit: 1, offset: 0, + status: 'active', }, { path: '/_stainless_unknown_path' }, ), From 92c1c0b09fe893370d9687595c7589bfa1a42e60 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 19 Jan 2026 18:47:35 +0000 Subject: [PATCH 254/551] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 37fa5b76..9ec6fcc6 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 91 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-68729f2ff40476377ead9019c18ea140fc4efbc2e68d7c4fc323bd61ae81f768.yml -openapi_spec_hash: 9eec61481f9059b5fedc13abc3e39338 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-59d2925a3cb93809cc762a3ac350691b365898e284f2c66a5999b9a6a37a35e5.yml +openapi_spec_hash: dfcb0a49e657426d0c0f44cfa3e89430 config_hash: cc7fdd701d995d4b3456d77041c604cf From 3b8d8fd7d5ccaf187f6d4782b4b1cfc1289fb2be Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 21 Jan 2026 01:00:05 +0000 Subject: [PATCH 255/551] feat: Update browser pool org limits --- .stats.yml | 4 ++-- src/resources/browser-pools.ts | 12 +++++++++--- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/.stats.yml b/.stats.yml index 9ec6fcc6..996826a1 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 91 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-59d2925a3cb93809cc762a3ac350691b365898e284f2c66a5999b9a6a37a35e5.yml -openapi_spec_hash: dfcb0a49e657426d0c0f44cfa3e89430 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-97558c7b5f2714e629041ff892cdabef76c4ab214b5f908ba8b36d507eac5260.yml +openapi_spec_hash: 3464d532154863ca17b82082451b9faf config_hash: cc7fdd701d995d4b3456d77041c604cf diff --git a/src/resources/browser-pools.ts b/src/resources/browser-pools.ts index 9e67f7c8..b05ad661 100644 --- a/src/resources/browser-pools.ts +++ b/src/resources/browser-pools.ts @@ -181,7 +181,9 @@ export namespace BrowserPool { */ export interface BrowserPoolConfig { /** - * Number of browsers to create in the pool + * Number of browsers to maintain in the pool. The maximum size is determined by + * your organization's pooled sessions limit (the sum of all pool sizes cannot + * exceed your limit). */ size: number; @@ -330,7 +332,9 @@ export interface BrowserPoolAcquireResponse { export interface BrowserPoolCreateParams { /** - * Number of browsers to create in the pool + * Number of browsers to maintain in the pool. The maximum size is determined by + * your organization's pooled sessions limit (the sum of all pool sizes cannot + * exceed your limit). */ size: number; @@ -400,7 +404,9 @@ export interface BrowserPoolCreateParams { export interface BrowserPoolUpdateParams { /** - * Number of browsers to create in the pool + * Number of browsers to maintain in the pool. The maximum size is determined by + * your organization's pooled sessions limit (the sum of all pool sizes cannot + * exceed your limit). */ size: number; From 0f3afdca985fd19bcc116b505c0b378205e9de34 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 21 Jan 2026 03:29:52 +0000 Subject: [PATCH 256/551] =?UTF-8?q?refactor(agentauth):=20enhance=20discov?= =?UTF-8?q?er=20and=20submit=20modules=20with=20improve=E2=80=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .stats.yml | 4 ++-- src/resources/agents/auth/auth.ts | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 996826a1..480b78b8 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 91 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-97558c7b5f2714e629041ff892cdabef76c4ab214b5f908ba8b36d507eac5260.yml -openapi_spec_hash: 3464d532154863ca17b82082451b9faf +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-714affeb2859c03a71d35708b6704b1750a1712738a130f3363ae67b20d751d9.yml +openapi_spec_hash: 9d2b9358f0f640ecd1eacd15b70dd361 config_hash: cc7fdd701d995d4b3456d77041c604cf diff --git a/src/resources/agents/auth/auth.ts b/src/resources/agents/auth/auth.ts index ac693566..570308e8 100644 --- a/src/resources/agents/auth/auth.ts +++ b/src/resources/agents/auth/auth.ts @@ -166,6 +166,11 @@ export interface AgentAuthInvocationResponse { */ pending_sso_buttons?: Array | null; + /** + * SSO provider being used for authentication (e.g., google, github, microsoft) + */ + sso_provider?: string | null; + /** * Names of fields that have been submitted (present when step=submitting or later) */ From f2e167f2b85314812d37aef7d6115ce59bfc2dc0 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 21 Jan 2026 04:39:11 +0000 Subject: [PATCH 257/551] feat(agent-auth): add 1Password integration for credential providers --- .stats.yml | 8 +- api.md | 19 ++ src/client.ts | 23 ++ src/resources/credential-providers.ts | 265 ++++++++++++++++++ src/resources/index.ts | 10 + .../credential-providers.test.ts | 94 +++++++ 6 files changed, 415 insertions(+), 4 deletions(-) create mode 100644 src/resources/credential-providers.ts create mode 100644 tests/api-resources/credential-providers.test.ts diff --git a/.stats.yml b/.stats.yml index 480b78b8..50043a40 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 91 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-714affeb2859c03a71d35708b6704b1750a1712738a130f3363ae67b20d751d9.yml -openapi_spec_hash: 9d2b9358f0f640ecd1eacd15b70dd361 -config_hash: cc7fdd701d995d4b3456d77041c604cf +configured_endpoints: 97 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-7427d4bcaba5cad07910da7a222bdd2650b5280e6b889132ed38d230adafb8a5.yml +openapi_spec_hash: e8e3dc1ae54666d544d1fc848b25e7cf +config_hash: b470456b217bb9502f5212311d395a6f diff --git a/api.md b/api.md index d86a8802..3b123d3c 100644 --- a/api.md +++ b/api.md @@ -300,3 +300,22 @@ Methods: - client.credentials.list({ ...params }) -> CredentialsOffsetPagination - client.credentials.delete(idOrName) -> void - client.credentials.totpCode(idOrName) -> CredentialTotpCodeResponse + +# CredentialProviders + +Types: + +- CreateCredentialProviderRequest +- CredentialProvider +- CredentialProviderTestResult +- UpdateCredentialProviderRequest +- CredentialProviderListResponse + +Methods: + +- client.credentialProviders.create({ ...params }) -> CredentialProvider +- client.credentialProviders.retrieve(id) -> CredentialProvider +- client.credentialProviders.update(id, { ...params }) -> CredentialProvider +- client.credentialProviders.list() -> CredentialProviderListResponse +- client.credentialProviders.delete(id) -> void +- client.credentialProviders.test(id) -> CredentialProviderTestResult diff --git a/src/client.ts b/src/client.ts index 36b42f10..b3220890 100644 --- a/src/client.ts +++ b/src/client.ts @@ -30,6 +30,16 @@ import { BrowserPoolUpdateParams, BrowserPools, } from './resources/browser-pools'; +import { + CreateCredentialProviderRequest, + CredentialProvider, + CredentialProviderCreateParams, + CredentialProviderListResponse, + CredentialProviderTestResult, + CredentialProviderUpdateParams, + CredentialProviders, + UpdateCredentialProviderRequest, +} from './resources/credential-providers'; import { CreateCredentialRequest, Credential, @@ -850,6 +860,7 @@ export class Kernel { browserPools: API.BrowserPools = new API.BrowserPools(this); agents: API.Agents = new API.Agents(this); credentials: API.Credentials = new API.Credentials(this); + credentialProviders: API.CredentialProviders = new API.CredentialProviders(this); } Kernel.Deployments = Deployments; @@ -862,6 +873,7 @@ Kernel.Extensions = Extensions; Kernel.BrowserPools = BrowserPools; Kernel.Agents = Agents; Kernel.Credentials = Credentials; +Kernel.CredentialProviders = CredentialProviders; export declare namespace Kernel { export type RequestOptions = Opts.RequestOptions; @@ -973,6 +985,17 @@ export declare namespace Kernel { type CredentialListParams as CredentialListParams, }; + export { + CredentialProviders as CredentialProviders, + type CreateCredentialProviderRequest as CreateCredentialProviderRequest, + type CredentialProvider as CredentialProvider, + type CredentialProviderTestResult as CredentialProviderTestResult, + type UpdateCredentialProviderRequest as UpdateCredentialProviderRequest, + type CredentialProviderListResponse as CredentialProviderListResponse, + type CredentialProviderCreateParams as CredentialProviderCreateParams, + type CredentialProviderUpdateParams as CredentialProviderUpdateParams, + }; + export type AppAction = API.AppAction; export type BrowserExtension = API.BrowserExtension; export type BrowserProfile = API.BrowserProfile; diff --git a/src/resources/credential-providers.ts b/src/resources/credential-providers.ts new file mode 100644 index 00000000..596e9e52 --- /dev/null +++ b/src/resources/credential-providers.ts @@ -0,0 +1,265 @@ +// 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 CredentialProviders extends APIResource { + /** + * Configure an external credential provider (e.g., 1Password) for automatic + * credential lookup. + * + * @example + * ```ts + * const credentialProvider = + * await client.credentialProviders.create({ + * token: 'ops_eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...', + * provider_type: 'onepassword', + * }); + * ``` + */ + create(body: CredentialProviderCreateParams, options?: RequestOptions): APIPromise { + return this._client.post('/org/credential-providers', { body, ...options }); + } + + /** + * Retrieve a credential provider by its ID. + * + * @example + * ```ts + * const credentialProvider = + * await client.credentialProviders.retrieve('id'); + * ``` + */ + retrieve(id: string, options?: RequestOptions): APIPromise { + return this._client.get(path`/org/credential-providers/${id}`, options); + } + + /** + * Update a credential provider's configuration. + * + * @example + * ```ts + * const credentialProvider = + * await client.credentialProviders.update('id'); + * ``` + */ + update( + id: string, + body: CredentialProviderUpdateParams, + options?: RequestOptions, + ): APIPromise { + return this._client.patch(path`/org/credential-providers/${id}`, { body, ...options }); + } + + /** + * List external credential providers configured for the organization. + * + * @example + * ```ts + * const credentialProviders = + * await client.credentialProviders.list(); + * ``` + */ + list(options?: RequestOptions): APIPromise { + return this._client.get('/org/credential-providers', options); + } + + /** + * Delete a credential provider by its ID. + * + * @example + * ```ts + * await client.credentialProviders.delete('id'); + * ``` + */ + delete(id: string, options?: RequestOptions): APIPromise { + return this._client.delete(path`/org/credential-providers/${id}`, { + ...options, + headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), + }); + } + + /** + * Validate the credential provider's token and list accessible vaults. + * + * @example + * ```ts + * const credentialProviderTestResult = + * await client.credentialProviders.test('id'); + * ``` + */ + test(id: string, options?: RequestOptions): APIPromise { + return this._client.post(path`/org/credential-providers/${id}/test`, options); + } +} + +/** + * Request to create an external credential provider + */ +export interface CreateCredentialProviderRequest { + /** + * Service account token for the provider (e.g., 1Password service account token) + */ + token: string; + + /** + * Type of credential provider + */ + provider_type: 'onepassword'; + + /** + * How long to cache credential lists (default 300 seconds) + */ + cache_ttl_seconds?: number; +} + +/** + * An external credential provider (e.g., 1Password) for automatic credential + * lookup + */ +export interface CredentialProvider { + /** + * Unique identifier for the credential provider + */ + id: string; + + /** + * When the credential provider was created + */ + created_at: string; + + /** + * Whether the provider is enabled for credential lookups + */ + enabled: boolean; + + /** + * Priority order for credential lookups (lower numbers are checked first) + */ + priority: number; + + /** + * Type of credential provider + */ + provider_type: 'onepassword'; + + /** + * When the credential provider was last updated + */ + updated_at: string; +} + +/** + * Result of testing a credential provider connection + */ +export interface CredentialProviderTestResult { + /** + * Whether the connection test was successful + */ + success: boolean; + + /** + * List of vaults accessible by the service account + */ + vaults: Array; + + /** + * Error message if the test failed + */ + error?: string; +} + +export namespace CredentialProviderTestResult { + export interface Vault { + /** + * Vault ID + */ + id: string; + + /** + * Vault name + */ + name: string; + } +} + +/** + * Request to update a credential provider + */ +export interface UpdateCredentialProviderRequest { + /** + * New service account token (to rotate credentials) + */ + token?: string; + + /** + * How long to cache credential lists + */ + cache_ttl_seconds?: number; + + /** + * Whether the provider is enabled for credential lookups + */ + enabled?: boolean; + + /** + * Priority order for credential lookups (lower numbers are checked first) + */ + priority?: number; +} + +export type CredentialProviderListResponse = Array; + +export interface CredentialProviderCreateParams { + /** + * Service account token for the provider (e.g., 1Password service account token) + */ + token: string; + + /** + * Type of credential provider + */ + provider_type: 'onepassword'; + + /** + * How long to cache credential lists (default 300 seconds) + */ + cache_ttl_seconds?: number; +} + +export interface CredentialProviderUpdateParams { + /** + * New service account token (to rotate credentials) + */ + token?: string; + + /** + * How long to cache credential lists + */ + cache_ttl_seconds?: number; + + /** + * Whether the provider is enabled for credential lookups + */ + enabled?: boolean; + + /** + * Priority order for credential lookups (lower numbers are checked first) + */ + priority?: number; +} + +export declare namespace CredentialProviders { + export { + type CreateCredentialProviderRequest as CreateCredentialProviderRequest, + type CredentialProvider as CredentialProvider, + type CredentialProviderTestResult as CredentialProviderTestResult, + type UpdateCredentialProviderRequest as UpdateCredentialProviderRequest, + type CredentialProviderListResponse as CredentialProviderListResponse, + type CredentialProviderCreateParams as CredentialProviderCreateParams, + type CredentialProviderUpdateParams as CredentialProviderUpdateParams, + }; +} diff --git a/src/resources/index.ts b/src/resources/index.ts index 1b7282a6..a3475dd5 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -35,6 +35,16 @@ export { type BrowserLoadExtensionsParams, type BrowserListResponsesOffsetPagination, } from './browsers/browsers'; +export { + CredentialProviders, + type CreateCredentialProviderRequest, + type CredentialProvider, + type CredentialProviderTestResult, + type UpdateCredentialProviderRequest, + type CredentialProviderListResponse, + type CredentialProviderCreateParams, + type CredentialProviderUpdateParams, +} from './credential-providers'; export { Credentials, type CreateCredentialRequest, diff --git a/tests/api-resources/credential-providers.test.ts b/tests/api-resources/credential-providers.test.ts new file mode 100644 index 00000000..5a20da8b --- /dev/null +++ b/tests/api-resources/credential-providers.test.ts @@ -0,0 +1,94 @@ +// 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 credentialProviders', () => { + // Prism tests are disabled + test.skip('create: only required params', async () => { + const responsePromise = client.credentialProviders.create({ + token: 'ops_eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...', + provider_type: 'onepassword', + }); + 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); + }); + + // Prism tests are disabled + test.skip('create: required and optional params', async () => { + const response = await client.credentialProviders.create({ + token: 'ops_eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...', + provider_type: 'onepassword', + cache_ttl_seconds: 300, + }); + }); + + // Prism tests are disabled + test.skip('retrieve', async () => { + const responsePromise = client.credentialProviders.retrieve('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); + }); + + // Prism tests are disabled + test.skip('update', async () => { + const responsePromise = client.credentialProviders.update('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); + }); + + // Prism tests are disabled + test.skip('list', async () => { + const responsePromise = client.credentialProviders.list(); + 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); + }); + + // Prism tests are disabled + test.skip('delete', async () => { + const responsePromise = client.credentialProviders.delete('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); + }); + + // Prism tests are disabled + test.skip('test', async () => { + const responsePromise = client.credentialProviders.test('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); + }); +}); From 2114a604e9d703d61dbbd42ec1cd5d1410d900ea Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 21 Jan 2026 05:24:01 +0000 Subject: [PATCH 258/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index c84411f5..2b114496 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.26.0" + ".": "0.27.0" } diff --git a/package.json b/package.json index 76168f14..5eb7b3b4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.26.0", + "version": "0.27.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index aa25151e..288031cf 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.26.0'; // x-release-please-version +export const VERSION = '0.27.0'; // x-release-please-version From ec058bfebd514bcb38b421cd98ceb5eb74eca0e0 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 22 Jan 2026 19:03:18 +0000 Subject: [PATCH 259/551] feat: Allow hot loading profiles into sessions --- .stats.yml | 4 ++-- src/resources/browsers/browsers.ts | 11 +++++++++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 50043a40..bcbec15d 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 97 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-7427d4bcaba5cad07910da7a222bdd2650b5280e6b889132ed38d230adafb8a5.yml -openapi_spec_hash: e8e3dc1ae54666d544d1fc848b25e7cf +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-d430a8e3407ceb608d912cabadbcb016b4fcf057ca56b3bbd179ea3b3121b484.yml +openapi_spec_hash: 8adbf013baf77abacaf04ed067749397 config_hash: b470456b217bb9502f5212311d395a6f diff --git a/src/resources/browsers/browsers.ts b/src/resources/browsers/browsers.ts index 040c783a..8d7c1e88 100644 --- a/src/resources/browsers/browsers.ts +++ b/src/resources/browsers/browsers.ts @@ -630,11 +630,22 @@ export interface BrowserRetrieveParams { } export interface BrowserUpdateParams { + /** + * Profile to load into the browser session. Only allowed if the session does not + * already have a profile loaded. + */ + profile?: Shared.BrowserProfile; + /** * ID of the proxy to use. Omit to leave unchanged, set to empty string to remove * proxy. */ proxy_id?: string | null; + + /** + * Viewport configuration to apply to the browser session. + */ + viewport?: Shared.BrowserViewport; } export interface BrowserListParams extends OffsetPaginationParams { From b5af3ab40c18e95be0aa50d0bab7c24222fd0478 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 22 Jan 2026 19:08:48 +0000 Subject: [PATCH 260/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 2b114496..98004448 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.27.0" + ".": "0.28.0" } diff --git a/package.json b/package.json index 5eb7b3b4..d8a1dfdc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.27.0", + "version": "0.28.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 288031cf..3e76cc42 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.27.0'; // x-release-please-version +export const VERSION = '0.28.0'; // x-release-please-version From 1df72f479ce05a5431d7008b9372771b8bd4029d Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 24 Jan 2026 04:16:31 +0000 Subject: [PATCH 261/551] chore(ci): upgrade `actions/github-script` --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f79a4b25..230c4adf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -57,7 +57,7 @@ jobs: - name: Get GitHub OIDC Token if: github.repository == 'stainless-sdks/kernel-typescript' id: github-oidc - uses: actions/github-script@v6 + uses: actions/github-script@v8 with: script: core.setOutput('github_token', await core.getIDToken()); From 097b32d6c2287fe72554cfd6a0806fc60b429ba7 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 26 Jan 2026 20:10:44 +0000 Subject: [PATCH 262/551] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index bcbec15d..48f30f8e 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 97 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-d430a8e3407ceb608d912cabadbcb016b4fcf057ca56b3bbd179ea3b3121b484.yml -openapi_spec_hash: 8adbf013baf77abacaf04ed067749397 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-6c4fc624f12ead2f790c0f12148bc78f25d0b720080cae878b8a0fc0b5e5cd93.yml +openapi_spec_hash: ab25e882fbeeb782507576a442c1e15b config_hash: b470456b217bb9502f5212311d395a6f From 9966844d9003c6d5feaa81933b5389e0897b364c Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 29 Jan 2026 18:53:42 +0000 Subject: [PATCH 263/551] feat: add support for 1280x800@60 viewport --- .stats.yml | 4 ++-- src/resources/browser-pools.ts | 16 ++++++++-------- src/resources/browsers/browsers.ts | 20 ++++++++++---------- src/resources/shared.ts | 4 ++-- 4 files changed, 22 insertions(+), 22 deletions(-) diff --git a/.stats.yml b/.stats.yml index 48f30f8e..470e4983 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 97 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-6c4fc624f12ead2f790c0f12148bc78f25d0b720080cae878b8a0fc0b5e5cd93.yml -openapi_spec_hash: ab25e882fbeeb782507576a442c1e15b +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-46c8320dcd9f8fc596f469ef0dd1aafaca591ab36cf2a6f8a7297dc9136bdc71.yml +openapi_spec_hash: 1be1e6589cd94c581b241720e01a65bc config_hash: b470456b217bb9502f5212311d395a6f diff --git a/src/resources/browser-pools.ts b/src/resources/browser-pools.ts index b05ad661..ac2a128b 100644 --- a/src/resources/browser-pools.ts +++ b/src/resources/browser-pools.ts @@ -243,8 +243,8 @@ export namespace BrowserPool { * image defaults apply (1920x1080@25). Only specific viewport configurations are * supported. The server will reject unsupported combinations. Supported * resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25, 1440x900@25, - * 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will be - * automatically determined from the width and height if they match a supported + * 1280x800@60, 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will + * be automatically determined from the width and height if they match a supported * configuration exactly. Note: Higher resolutions may affect the responsiveness of * live view browser */ @@ -322,8 +322,8 @@ export interface BrowserPoolAcquireResponse { * image defaults apply (1920x1080@25). Only specific viewport configurations are * supported. The server will reject unsupported combinations. Supported * resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25, 1440x900@25, - * 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will be - * automatically determined from the width and height if they match a supported + * 1280x800@60, 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will + * be automatically determined from the width and height if they match a supported * configuration exactly. Note: Higher resolutions may affect the responsiveness of * live view browser */ @@ -394,8 +394,8 @@ export interface BrowserPoolCreateParams { * image defaults apply (1920x1080@25). Only specific viewport configurations are * supported. The server will reject unsupported combinations. Supported * resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25, 1440x900@25, - * 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will be - * automatically determined from the width and height if they match a supported + * 1280x800@60, 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will + * be automatically determined from the width and height if they match a supported * configuration exactly. Note: Higher resolutions may affect the responsiveness of * live view browser */ @@ -472,8 +472,8 @@ export interface BrowserPoolUpdateParams { * image defaults apply (1920x1080@25). Only specific viewport configurations are * supported. The server will reject unsupported combinations. Supported * resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25, 1440x900@25, - * 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will be - * automatically determined from the width and height if they match a supported + * 1280x800@60, 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will + * be automatically determined from the width and height if they match a supported * configuration exactly. Note: Higher resolutions may affect the responsiveness of * live view browser */ diff --git a/src/resources/browsers/browsers.ts b/src/resources/browsers/browsers.ts index 8d7c1e88..f9b244f3 100644 --- a/src/resources/browsers/browsers.ts +++ b/src/resources/browsers/browsers.ts @@ -316,8 +316,8 @@ export interface BrowserCreateResponse { * image defaults apply (1920x1080@25). Only specific viewport configurations are * supported. The server will reject unsupported combinations. Supported * resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25, 1440x900@25, - * 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will be - * automatically determined from the width and height if they match a supported + * 1280x800@60, 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will + * be automatically determined from the width and height if they match a supported * configuration exactly. Note: Higher resolutions may affect the responsiveness of * live view browser */ @@ -392,8 +392,8 @@ export interface BrowserRetrieveResponse { * image defaults apply (1920x1080@25). Only specific viewport configurations are * supported. The server will reject unsupported combinations. Supported * resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25, 1440x900@25, - * 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will be - * automatically determined from the width and height if they match a supported + * 1280x800@60, 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will + * be automatically determined from the width and height if they match a supported * configuration exactly. Note: Higher resolutions may affect the responsiveness of * live view browser */ @@ -468,8 +468,8 @@ export interface BrowserUpdateResponse { * image defaults apply (1920x1080@25). Only specific viewport configurations are * supported. The server will reject unsupported combinations. Supported * resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25, 1440x900@25, - * 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will be - * automatically determined from the width and height if they match a supported + * 1280x800@60, 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will + * be automatically determined from the width and height if they match a supported * configuration exactly. Note: Higher resolutions may affect the responsiveness of * live view browser */ @@ -544,8 +544,8 @@ export interface BrowserListResponse { * image defaults apply (1920x1080@25). Only specific viewport configurations are * supported. The server will reject unsupported combinations. Supported * resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25, 1440x900@25, - * 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will be - * automatically determined from the width and height if they match a supported + * 1280x800@60, 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will + * be automatically determined from the width and height if they match a supported * configuration exactly. Note: Higher resolutions may affect the responsiveness of * live view browser */ @@ -614,8 +614,8 @@ export interface BrowserCreateParams { * image defaults apply (1920x1080@25). Only specific viewport configurations are * supported. The server will reject unsupported combinations. Supported * resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25, 1440x900@25, - * 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will be - * automatically determined from the width and height if they match a supported + * 1280x800@60, 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will + * be automatically determined from the width and height if they match a supported * configuration exactly. Note: Higher resolutions may affect the responsiveness of * live view browser */ diff --git a/src/resources/shared.ts b/src/resources/shared.ts index 3a3112b7..600b53dd 100644 --- a/src/resources/shared.ts +++ b/src/resources/shared.ts @@ -56,8 +56,8 @@ export interface BrowserProfile { * image defaults apply (1920x1080@25). Only specific viewport configurations are * supported. The server will reject unsupported combinations. Supported * resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25, 1440x900@25, - * 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will be - * automatically determined from the width and height if they match a supported + * 1280x800@60, 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will + * be automatically determined from the width and height if they match a supported * configuration exactly. Note: Higher resolutions may affect the responsiveness of * live view browser */ From 5e4244884a80706e9b1ab76d4c96320006c2a6e7 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 30 Jan 2026 05:06:02 +0000 Subject: [PATCH 264/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 98004448..8316a6de 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.28.0" + ".": "0.29.0" } diff --git a/package.json b/package.json index d8a1dfdc..605cedd1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.28.0", + "version": "0.29.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 3e76cc42..bef2b64d 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.28.0'; // x-release-please-version +export const VERSION = '0.29.0'; // x-release-please-version From 16f8889f9def7937fe23667a1c9652b26c9759ee Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 30 Jan 2026 18:02:38 +0000 Subject: [PATCH 265/551] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 470e4983..67f01853 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 97 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-46c8320dcd9f8fc596f469ef0dd1aafaca591ab36cf2a6f8a7297dc9136bdc71.yml -openapi_spec_hash: 1be1e6589cd94c581b241720e01a65bc +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-c955031ac0bb644c0aa1d1120e288f703168abeb0e44a166f55119295f737cc5.yml +openapi_spec_hash: 9fbc24cdaccdd21264e995df40b52d3f config_hash: b470456b217bb9502f5212311d395a6f From d1d3cb1e9ae128d50d5de2713d0f86d7121a382a Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 3 Feb 2026 04:42:29 +0000 Subject: [PATCH 266/551] fix(client): avoid memory leak with abort signals --- src/client.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/client.ts b/src/client.ts index b3220890..f241e7de 100644 --- a/src/client.ts +++ b/src/client.ts @@ -625,9 +625,10 @@ export class Kernel { controller: AbortController, ): Promise { const { signal, method, ...options } = init || {}; - if (signal) signal.addEventListener('abort', () => controller.abort()); + const abort = controller.abort.bind(controller); + if (signal) signal.addEventListener('abort', abort, { once: true }); - const timeout = setTimeout(() => controller.abort(), ms); + const timeout = setTimeout(abort, ms); const isReadableBody = ((globalThis as any).ReadableStream && options.body instanceof (globalThis as any).ReadableStream) || From 1ab9a19bf9938f5fe7a0a6b6e7f0156da441a707 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 3 Feb 2026 04:44:59 +0000 Subject: [PATCH 267/551] chore(client): do not parse responses with empty content-length --- src/internal/parse.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/internal/parse.ts b/src/internal/parse.ts index 7fe9be43..4796f69b 100644 --- a/src/internal/parse.ts +++ b/src/internal/parse.ts @@ -43,6 +43,12 @@ export async function defaultParseResponse(client: Kernel, props: APIResponse const mediaType = contentType?.split(';')[0]?.trim(); const isJSON = mediaType?.includes('application/json') || mediaType?.endsWith('+json'); if (isJSON) { + const contentLength = response.headers.get('content-length'); + if (contentLength === '0') { + // if there is no content we can't do anything + return undefined as T; + } + const json = await response.json(); return json as T; } From 7a7911b6b10c25c908561be51e8a185ead15abb4 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 3 Feb 2026 14:58:45 +0000 Subject: [PATCH 268/551] feat: Neil/kernel 872 templates v3 --- .stats.yml | 8 +- api.md | 2 + src/client.ts | 2 + src/resources/index.ts | 1 + src/resources/invocations.ts | 98 +++++++++++++++++++++++++ tests/api-resources/invocations.test.ts | 12 +++ 6 files changed, 119 insertions(+), 4 deletions(-) diff --git a/.stats.yml b/.stats.yml index 67f01853..710d8bda 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 97 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-c955031ac0bb644c0aa1d1120e288f703168abeb0e44a166f55119295f737cc5.yml -openapi_spec_hash: 9fbc24cdaccdd21264e995df40b52d3f -config_hash: b470456b217bb9502f5212311d395a6f +configured_endpoints: 98 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-ccbe854895eb34a9562e33979f5f43cd6ad1f529d5924ee56e56f0c94dcf0454.yml +openapi_spec_hash: 2fa4ecbe742fc46fdde481188c1d885e +config_hash: dd218aae3f852dff79e77febc2077b8e diff --git a/api.md b/api.md index 3b123d3c..dc172c87 100644 --- a/api.md +++ b/api.md @@ -49,6 +49,7 @@ Types: - InvocationUpdateResponse - InvocationListResponse - InvocationFollowResponse +- InvocationListBrowsersResponse Methods: @@ -58,6 +59,7 @@ Methods: - client.invocations.list({ ...params }) -> InvocationListResponsesOffsetPagination - client.invocations.deleteBrowsers(id) -> void - client.invocations.follow(id, { ...params }) -> InvocationFollowResponse +- client.invocations.listBrowsers(id) -> InvocationListBrowsersResponse # Browsers diff --git a/src/client.ts b/src/client.ts index f241e7de..95986154 100644 --- a/src/client.ts +++ b/src/client.ts @@ -75,6 +75,7 @@ import { InvocationCreateResponse, InvocationFollowParams, InvocationFollowResponse, + InvocationListBrowsersResponse, InvocationListParams, InvocationListResponse, InvocationListResponsesOffsetPagination, @@ -913,6 +914,7 @@ export declare namespace Kernel { type InvocationUpdateResponse as InvocationUpdateResponse, type InvocationListResponse as InvocationListResponse, type InvocationFollowResponse as InvocationFollowResponse, + type InvocationListBrowsersResponse as InvocationListBrowsersResponse, type InvocationListResponsesOffsetPagination as InvocationListResponsesOffsetPagination, type InvocationCreateParams as InvocationCreateParams, type InvocationUpdateParams as InvocationUpdateParams, diff --git a/src/resources/index.ts b/src/resources/index.ts index a3475dd5..a2d913f7 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -83,6 +83,7 @@ export { type InvocationUpdateResponse, type InvocationListResponse, type InvocationFollowResponse, + type InvocationListBrowsersResponse, type InvocationCreateParams, type InvocationUpdateParams, type InvocationListParams, diff --git a/src/resources/invocations.ts b/src/resources/invocations.ts index 5b9106d2..d8883bb6 100644 --- a/src/resources/invocations.ts +++ b/src/resources/invocations.ts @@ -2,6 +2,7 @@ import { APIResource } from '../core/resource'; import * as Shared from './shared'; +import * as BrowsersAPI from './browsers/browsers'; import { APIPromise } from '../core/api-promise'; import { OffsetPagination, type OffsetPaginationParams, PagePromise } from '../core/pagination'; import { Stream } from '../core/streaming'; @@ -118,6 +119,20 @@ export class Invocations extends APIResource { stream: true, }) as APIPromise>; } + + /** + * Returns all active browser sessions created within the specified invocation. + * + * @example + * ```ts + * const response = await client.invocations.listBrowsers( + * 'id', + * ); + * ``` + */ + listBrowsers(id: string, options?: RequestOptions): APIPromise { + return this._client.get(path`/invocations/${id}/browsers`, options); + } } export type InvocationListResponsesOffsetPagination = OffsetPagination; @@ -394,6 +409,88 @@ export type InvocationFollowResponse = | Shared.ErrorEvent | Shared.HeartbeatEvent; +export interface InvocationListBrowsersResponse { + browsers: Array; +} + +export namespace InvocationListBrowsersResponse { + export interface Browser { + /** + * Websocket URL for Chrome DevTools Protocol connections to the browser session + */ + cdp_ws_url: string; + + /** + * When the browser session was created. + */ + created_at: string; + + /** + * Whether the browser session is running in headless mode. + */ + headless: boolean; + + /** + * Unique identifier for the browser session + */ + session_id: string; + + /** + * Whether the browser session is running in stealth mode. + */ + stealth: boolean; + + /** + * The number of seconds of inactivity before the browser session is terminated. + */ + timeout_seconds: number; + + /** + * Remote URL for live viewing the browser session. Only available for non-headless + * browsers. + */ + browser_live_view_url?: string; + + /** + * When the browser session was soft-deleted. Only present for deleted sessions. + */ + deleted_at?: string; + + /** + * Whether the browser session is running in kiosk mode. + */ + kiosk_mode?: boolean; + + /** + * @deprecated DEPRECATED: Use timeout_seconds (up to 72 hours) and Profiles + * instead. + */ + persistence?: BrowsersAPI.BrowserPersistence; + + /** + * Browser profile metadata. + */ + profile?: BrowsersAPI.Profile; + + /** + * ID of the proxy associated with this browser session, if any. + */ + proxy_id?: string; + + /** + * Initial browser window size in pixels with optional refresh rate. If omitted, + * image defaults apply (1920x1080@25). Only specific viewport configurations are + * supported. The server will reject unsupported combinations. Supported + * resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25, 1440x900@25, + * 1280x800@60, 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will + * be automatically determined from the width and height if they match a supported + * configuration exactly. Note: Higher resolutions may affect the responsiveness of + * live view browser + */ + viewport?: Shared.BrowserViewport; + } +} + export interface InvocationCreateParams { /** * Name of the action to invoke @@ -488,6 +585,7 @@ export declare namespace Invocations { type InvocationUpdateResponse as InvocationUpdateResponse, type InvocationListResponse as InvocationListResponse, type InvocationFollowResponse as InvocationFollowResponse, + type InvocationListBrowsersResponse as InvocationListBrowsersResponse, type InvocationListResponsesOffsetPagination as InvocationListResponsesOffsetPagination, type InvocationCreateParams as InvocationCreateParams, type InvocationUpdateParams as InvocationUpdateParams, diff --git a/tests/api-resources/invocations.test.ts b/tests/api-resources/invocations.test.ts index b8c80247..cb7750a2 100644 --- a/tests/api-resources/invocations.test.ts +++ b/tests/api-resources/invocations.test.ts @@ -132,4 +132,16 @@ describe('resource invocations', () => { ), ).rejects.toThrow(Kernel.NotFoundError); }); + + // Prism tests are disabled + test.skip('listBrowsers', async () => { + const responsePromise = client.invocations.listBrowsers('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); + }); }); From a5aaedf4c73e89e8bc43809bacdb24063e007cbc Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 3 Feb 2026 16:59:36 +0000 Subject: [PATCH 269/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 8316a6de..716d0046 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.29.0" + ".": "0.30.0" } diff --git a/package.json b/package.json index 605cedd1..13178cd2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.29.0", + "version": "0.30.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index bef2b64d..91a9bb6d 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.29.0'; // x-release-please-version +export const VERSION = '0.30.0'; // x-release-please-version From 3d121541fded83f8a8c9022f4a3fcf0801026ce6 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 5 Feb 2026 03:52:51 +0000 Subject: [PATCH 270/551] chore(client): restructure abort controller binding --- src/client.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/client.ts b/src/client.ts index 95986154..b6845af3 100644 --- a/src/client.ts +++ b/src/client.ts @@ -626,7 +626,7 @@ export class Kernel { controller: AbortController, ): Promise { const { signal, method, ...options } = init || {}; - const abort = controller.abort.bind(controller); + const abort = this._makeAbort(controller); if (signal) signal.addEventListener('abort', abort, { once: true }); const timeout = setTimeout(abort, ms); @@ -652,6 +652,7 @@ export class Kernel { return await this.fetch.call(undefined, url, fetchOptions); } finally { clearTimeout(timeout); + if (signal) signal.removeEventListener('abort', abort); } } @@ -796,6 +797,12 @@ export class Kernel { return headers.values; } + private _makeAbort(controller: AbortController) { + // note: we can't just inline this method inside `fetchWithTimeout()` because then the closure + // would capture all request options, and cause a memory leak. + return () => controller.abort(); + } + private buildBody({ options: { body, headers: rawHeaders } }: { options: FinalRequestOptions }): { bodyHeaders: HeadersLike; body: BodyInit | undefined; From 27f64da151c512698d606c503747bd6e42ce5d1f Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 6 Feb 2026 04:40:41 +0000 Subject: [PATCH 271/551] fix(client): avoid removing abort listener too early --- src/client.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/client.ts b/src/client.ts index b6845af3..f4a77889 100644 --- a/src/client.ts +++ b/src/client.ts @@ -652,7 +652,6 @@ export class Kernel { return await this.fetch.call(undefined, url, fetchOptions); } finally { clearTimeout(timeout); - if (signal) signal.removeEventListener('abort', abort); } } From 22cca4d8dda3fddfad473ee21cf1e2c68ebadd3d Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 6 Feb 2026 04:41:13 +0000 Subject: [PATCH 272/551] chore(internal): fix pagination internals not accepting option promises --- src/client.ts | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/client.ts b/src/client.ts index f4a77889..d332e123 100644 --- a/src/client.ts +++ b/src/client.ts @@ -603,9 +603,14 @@ export class Kernel { getAPIList = Pagination.AbstractPage>( path: string, Page: new (...args: any[]) => PageClass, - opts?: RequestOptions, + opts?: PromiseOrValue, ): Pagination.PagePromise { - return this.requestAPIList(Page, { method: 'get', path, ...opts }); + return this.requestAPIList( + Page, + opts && 'then' in opts ? + opts.then((opts) => ({ method: 'get', path, ...opts })) + : { method: 'get', path, ...opts }, + ); } requestAPIList< @@ -613,7 +618,7 @@ export class Kernel { PageClass extends Pagination.AbstractPage = Pagination.AbstractPage, >( Page: new (...args: ConstructorParameters) => PageClass, - options: FinalRequestOptions, + options: PromiseOrValue, ): Pagination.PagePromise { const request = this.makeRequest(options, null, undefined); return new Pagination.PagePromise(this as any as Kernel, request, Page); From bd47552cc53696ac7c45b5e17b2178192963fe6f Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 6 Feb 2026 12:38:43 +0000 Subject: [PATCH 273/551] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 710d8bda..28bf5610 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 98 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-ccbe854895eb34a9562e33979f5f43cd6ad1f529d5924ee56e56f0c94dcf0454.yml -openapi_spec_hash: 2fa4ecbe742fc46fdde481188c1d885e +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-652441005cba60f2ada5328d8dfc60165f6ab0bb271d6b64feca250fe73dc197.yml +openapi_spec_hash: f50a08ba2578efd8b756bdd920510c50 config_hash: dd218aae3f852dff79e77febc2077b8e From 52440c7e980ea0e0fc0a1cab5b704b882e8c4380 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 6 Feb 2026 18:44:50 +0000 Subject: [PATCH 274/551] feat: add batch computer action proxy endpoint --- .stats.yml | 8 +- api.md | 3 + src/resources/browsers/browsers.ts | 4 + src/resources/browsers/computer.ts | 257 ++++++++++++++++++ src/resources/browsers/index.ts | 2 + tests/api-resources/browsers/computer.test.ts | 74 +++++ 6 files changed, 344 insertions(+), 4 deletions(-) diff --git a/.stats.yml b/.stats.yml index 28bf5610..91fd3b68 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 98 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-652441005cba60f2ada5328d8dfc60165f6ab0bb271d6b64feca250fe73dc197.yml -openapi_spec_hash: f50a08ba2578efd8b756bdd920510c50 -config_hash: dd218aae3f852dff79e77febc2077b8e +configured_endpoints: 100 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-a6d93dc291278035c96add38bb6150ec2b9ba8bbabb4676e3dbbb8444cf3b1e4.yml +openapi_spec_hash: 694bcc56d94fd0ff0d1f7b0fc1dae8ba +config_hash: 62e33cf2ed8fe0b4ceebba63367481ad diff --git a/api.md b/api.md index dc172c87..1f780388 100644 --- a/api.md +++ b/api.md @@ -163,13 +163,16 @@ Methods: Types: +- ComputerGetMousePositionResponse - ComputerSetCursorVisibilityResponse Methods: +- client.browsers.computer.batch(id, { ...params }) -> void - client.browsers.computer.captureScreenshot(id, { ...params }) -> Response - client.browsers.computer.clickMouse(id, { ...params }) -> void - client.browsers.computer.dragMouse(id, { ...params }) -> void +- client.browsers.computer.getMousePosition(id) -> ComputerGetMousePositionResponse - client.browsers.computer.moveMouse(id, { ...params }) -> void - client.browsers.computer.pressKey(id, { ...params }) -> void - client.browsers.computer.scroll(id, { ...params }) -> void diff --git a/src/resources/browsers/browsers.ts b/src/resources/browsers/browsers.ts index f9b244f3..c335cac0 100644 --- a/src/resources/browsers/browsers.ts +++ b/src/resources/browsers/browsers.ts @@ -5,9 +5,11 @@ import * as Shared from '../shared'; import * as ComputerAPI from './computer'; import { Computer, + ComputerBatchParams, ComputerCaptureScreenshotParams, ComputerClickMouseParams, ComputerDragMouseParams, + ComputerGetMousePositionResponse, ComputerMoveMouseParams, ComputerPressKeyParams, ComputerScrollParams, @@ -764,7 +766,9 @@ export declare namespace Browsers { export { Computer as Computer, + type ComputerGetMousePositionResponse as ComputerGetMousePositionResponse, type ComputerSetCursorVisibilityResponse as ComputerSetCursorVisibilityResponse, + type ComputerBatchParams as ComputerBatchParams, type ComputerCaptureScreenshotParams as ComputerCaptureScreenshotParams, type ComputerClickMouseParams as ComputerClickMouseParams, type ComputerDragMouseParams as ComputerDragMouseParams, diff --git a/src/resources/browsers/computer.ts b/src/resources/browsers/computer.ts index 575cfadb..6b15782d 100644 --- a/src/resources/browsers/computer.ts +++ b/src/resources/browsers/computer.ts @@ -7,6 +7,26 @@ import { RequestOptions } from '../../internal/request-options'; import { path } from '../../internal/utils/path'; export class Computer extends APIResource { + /** + * Send an array of computer actions to execute in order on the browser instance. + * Execution stops on the first error. This reduces network latency compared to + * sending individual action requests. + * + * @example + * ```ts + * await client.browsers.computer.batch('id', { + * actions: [{ type: 'click_mouse' }], + * }); + * ``` + */ + batch(id: string, body: ComputerBatchParams, options?: RequestOptions): APIPromise { + return this._client.post(path`/browsers/${id}/computer/batch`, { + body, + ...options, + headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), + }); + } + /** * Capture a screenshot of the browser instance * @@ -72,6 +92,19 @@ export class Computer extends APIResource { }); } + /** + * Get the current mouse cursor position on the browser instance + * + * @example + * ```ts + * const response = + * await client.browsers.computer.getMousePosition('id'); + * ``` + */ + getMousePosition(id: string, options?: RequestOptions): APIPromise { + return this._client.post(path`/browsers/${id}/computer/get_mouse_position`, options); + } + /** * Move the mouse cursor to the specified coordinates on the browser instance * @@ -163,6 +196,18 @@ export class Computer extends APIResource { } } +export interface ComputerGetMousePositionResponse { + /** + * X coordinate of the cursor + */ + x: number; + + /** + * Y coordinate of the cursor + */ + y: number; +} + /** * Generic OK response. */ @@ -173,6 +218,216 @@ export interface ComputerSetCursorVisibilityResponse { ok: boolean; } +export interface ComputerBatchParams { + /** + * Ordered list of actions to execute. Execution stops on the first error. + */ + actions: Array; +} + +export namespace ComputerBatchParams { + /** + * A single computer action to execute as part of a batch. The `type` field selects + * which action to perform, and the corresponding field contains the action + * parameters. Exactly one action field matching the type must be provided. + */ + export interface Action { + /** + * The type of action to perform. + */ + type: + | 'click_mouse' + | 'move_mouse' + | 'type_text' + | 'press_key' + | 'scroll' + | 'drag_mouse' + | 'set_cursor' + | 'sleep'; + + click_mouse?: Action.ClickMouse; + + drag_mouse?: Action.DragMouse; + + move_mouse?: Action.MoveMouse; + + press_key?: Action.PressKey; + + scroll?: Action.Scroll; + + set_cursor?: Action.SetCursor; + + /** + * Pause execution for a specified duration. + */ + sleep?: Action.Sleep; + + type_text?: Action.TypeText; + } + + export namespace Action { + export interface ClickMouse { + /** + * X coordinate of the click position + */ + x: number; + + /** + * Y coordinate of the click position + */ + y: number; + + /** + * Mouse button to interact with + */ + button?: 'left' | 'right' | 'middle' | 'back' | 'forward'; + + /** + * Type of click action + */ + click_type?: 'down' | 'up' | 'click'; + + /** + * Modifier keys to hold during the click + */ + hold_keys?: Array; + + /** + * Number of times to repeat the click + */ + num_clicks?: number; + } + + export interface DragMouse { + /** + * Ordered list of [x, y] coordinate pairs to move through while dragging. Must + * contain at least 2 points. + */ + path: Array>; + + /** + * Mouse button to drag with + */ + button?: 'left' | 'middle' | 'right'; + + /** + * Delay in milliseconds between button down and starting to move along the path. + */ + delay?: number; + + /** + * Modifier keys to hold during the drag + */ + hold_keys?: Array; + + /** + * Delay in milliseconds between relative steps while dragging (not the initial + * delay). + */ + step_delay_ms?: number; + + /** + * Number of relative move steps per segment in the path. Minimum 1. + */ + steps_per_segment?: number; + } + + export interface MoveMouse { + /** + * X coordinate to move the cursor to + */ + x: number; + + /** + * Y coordinate to move the cursor to + */ + y: number; + + /** + * Modifier keys to hold during the move + */ + hold_keys?: Array; + } + + export interface PressKey { + /** + * List of key symbols to press. Each item should be a key symbol supported by + * xdotool (see X11 keysym definitions). Examples include "Return", "Shift", + * "Ctrl", "Alt", "F5". Items in this list could also be combinations, e.g. + * "Ctrl+t" or "Ctrl+Shift+Tab". + */ + keys: Array; + + /** + * Duration to hold the keys down in milliseconds. If omitted or 0, keys are + * tapped. + */ + duration?: number; + + /** + * Optional modifier keys to hold during the key press sequence. + */ + hold_keys?: Array; + } + + export interface Scroll { + /** + * X coordinate at which to perform the scroll + */ + x: number; + + /** + * Y coordinate at which to perform the scroll + */ + y: number; + + /** + * Horizontal scroll amount. Positive scrolls right, negative scrolls left. + */ + delta_x?: number; + + /** + * Vertical scroll amount. Positive scrolls down, negative scrolls up. + */ + delta_y?: number; + + /** + * Modifier keys to hold during the scroll + */ + hold_keys?: Array; + } + + export interface SetCursor { + /** + * Whether the cursor should be hidden or visible + */ + hidden: boolean; + } + + /** + * Pause execution for a specified duration. + */ + export interface Sleep { + /** + * Duration to sleep in milliseconds. + */ + duration_ms: number; + } + + export interface TypeText { + /** + * Text to type on the browser instance + */ + text: string; + + /** + * Delay in milliseconds between keystrokes + */ + delay?: number; + } + } +} + export interface ComputerCaptureScreenshotParams { region?: ComputerCaptureScreenshotParams.Region; } @@ -353,7 +608,9 @@ export interface ComputerTypeTextParams { export declare namespace Computer { export { + type ComputerGetMousePositionResponse as ComputerGetMousePositionResponse, type ComputerSetCursorVisibilityResponse as ComputerSetCursorVisibilityResponse, + type ComputerBatchParams as ComputerBatchParams, type ComputerCaptureScreenshotParams as ComputerCaptureScreenshotParams, type ComputerClickMouseParams as ComputerClickMouseParams, type ComputerDragMouseParams as ComputerDragMouseParams, diff --git a/src/resources/browsers/index.ts b/src/resources/browsers/index.ts index 046c1b24..178d54f5 100644 --- a/src/resources/browsers/index.ts +++ b/src/resources/browsers/index.ts @@ -18,7 +18,9 @@ export { } from './browsers'; export { Computer, + type ComputerGetMousePositionResponse, type ComputerSetCursorVisibilityResponse, + type ComputerBatchParams, type ComputerCaptureScreenshotParams, type ComputerClickMouseParams, type ComputerDragMouseParams, diff --git a/tests/api-resources/browsers/computer.test.ts b/tests/api-resources/browsers/computer.test.ts index b95f0fa7..dbc78316 100644 --- a/tests/api-resources/browsers/computer.test.ts +++ b/tests/api-resources/browsers/computer.test.ts @@ -8,6 +8,68 @@ const client = new Kernel({ }); describe('resource computer', () => { + // Prism tests are disabled + test.skip('batch: only required params', async () => { + const responsePromise = client.browsers.computer.batch('id', { actions: [{ type: 'click_mouse' }] }); + 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); + }); + + // Prism tests are disabled + test.skip('batch: required and optional params', async () => { + const response = await client.browsers.computer.batch('id', { + actions: [ + { + type: 'click_mouse', + click_mouse: { + x: 0, + y: 0, + button: 'left', + click_type: 'down', + hold_keys: ['string'], + num_clicks: 0, + }, + drag_mouse: { + path: [ + [0, 0], + [0, 0], + ], + button: 'left', + delay: 0, + hold_keys: ['string'], + step_delay_ms: 0, + steps_per_segment: 1, + }, + move_mouse: { + x: 0, + y: 0, + hold_keys: ['string'], + }, + press_key: { + keys: ['string'], + duration: 0, + hold_keys: ['string'], + }, + scroll: { + x: 0, + y: 0, + delta_x: 0, + delta_y: 0, + hold_keys: ['string'], + }, + set_cursor: { hidden: true }, + sleep: { duration_ms: 0 }, + type_text: { text: 'text', delay: 0 }, + }, + ], + }); + }); + test('captureScreenshot: 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( @@ -82,6 +144,18 @@ describe('resource computer', () => { }); }); + // Prism tests are disabled + test.skip('getMousePosition', async () => { + const responsePromise = client.browsers.computer.getMousePosition('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); + }); + // Prism tests are disabled test.skip('moveMouse: only required params', async () => { const responsePromise = client.browsers.computer.moveMouse('id', { x: 0, y: 0 }); From b77ca00d43257b9d86219c1171df8c7925e72a30 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 6 Feb 2026 19:08:07 +0000 Subject: [PATCH 275/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 716d0046..8e3d9554 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.30.0" + ".": "0.31.0" } diff --git a/package.json b/package.json index 13178cd2..53f4cbd2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.30.0", + "version": "0.31.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 91a9bb6d..b6314c28 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.30.0'; // x-release-please-version +export const VERSION = '0.31.0'; // x-release-please-version From 0d720e1c5ee7edd6734150f07ed04f4f19887f64 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 6 Feb 2026 20:32:35 +0000 Subject: [PATCH 276/551] chore: add Managed Auth API planning doc --- .stats.yml | 8 +- api.md | 39 +- src/client.ts | 9 + src/resources/agents/auth/auth.ts | 162 +++- src/resources/agents/auth/invocations.ts | 65 +- src/resources/auth.ts | 3 + src/resources/auth/auth.ts | 43 + src/resources/auth/connections.ts | 843 ++++++++++++++++++ src/resources/auth/index.ts | 18 + src/resources/credential-providers.ts | 94 +- src/resources/index.ts | 3 + tests/api-resources/auth/connections.test.ts | 154 ++++ .../credential-providers.test.ts | 14 + 13 files changed, 1346 insertions(+), 109 deletions(-) create mode 100644 src/resources/auth.ts create mode 100644 src/resources/auth/auth.ts create mode 100644 src/resources/auth/connections.ts create mode 100644 src/resources/auth/index.ts create mode 100644 tests/api-resources/auth/connections.test.ts diff --git a/.stats.yml b/.stats.yml index 91fd3b68..29643219 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 100 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-a6d93dc291278035c96add38bb6150ec2b9ba8bbabb4676e3dbbb8444cf3b1e4.yml -openapi_spec_hash: 694bcc56d94fd0ff0d1f7b0fc1dae8ba -config_hash: 62e33cf2ed8fe0b4ceebba63367481ad +configured_endpoints: 108 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-3fbe762c99e8a120c426ac22bc1fa257c9127d631b12a38a6440a37f52935543.yml +openapi_spec_hash: 5a190df210ed90b20a71c5061ff43917 +config_hash: 38c9b3b355025daf9bb643040e4af94e diff --git a/api.md b/api.md index 1f780388..8037ef03 100644 --- a/api.md +++ b/api.md @@ -203,6 +203,30 @@ Methods: - client.profiles.delete(idOrName) -> void - client.profiles.download(idOrName) -> Response +# Auth + +## Connections + +Types: + +- LoginRequest +- LoginResponse +- ManagedAuth +- ManagedAuthCreateRequest +- SubmitFieldsRequest +- SubmitFieldsResponse +- ConnectionFollowResponse + +Methods: + +- client.auth.connections.create({ ...params }) -> ManagedAuth +- client.auth.connections.retrieve(id) -> ManagedAuth +- client.auth.connections.list({ ...params }) -> ManagedAuthsOffsetPagination +- client.auth.connections.delete(id) -> void +- client.auth.connections.follow(id) -> ConnectionFollowResponse +- client.auth.connections.login(id, { ...params }) -> LoginResponse +- client.auth.connections.submit(id, { ...params }) -> SubmitFieldsResponse + # Proxies Types: @@ -312,15 +336,18 @@ Types: - CreateCredentialProviderRequest - CredentialProvider +- CredentialProviderItem - CredentialProviderTestResult - UpdateCredentialProviderRequest - CredentialProviderListResponse +- CredentialProviderListItemsResponse Methods: -- client.credentialProviders.create({ ...params }) -> CredentialProvider -- client.credentialProviders.retrieve(id) -> CredentialProvider -- client.credentialProviders.update(id, { ...params }) -> CredentialProvider -- client.credentialProviders.list() -> CredentialProviderListResponse -- client.credentialProviders.delete(id) -> void -- client.credentialProviders.test(id) -> CredentialProviderTestResult +- client.credentialProviders.create({ ...params }) -> CredentialProvider +- client.credentialProviders.retrieve(id) -> CredentialProvider +- client.credentialProviders.update(id, { ...params }) -> CredentialProvider +- client.credentialProviders.list() -> CredentialProviderListResponse +- client.credentialProviders.delete(id) -> void +- client.credentialProviders.listItems(id) -> CredentialProviderListItemsResponse +- client.credentialProviders.test(id) -> CredentialProviderTestResult diff --git a/src/client.ts b/src/client.ts index d332e123..d191bb5d 100644 --- a/src/client.ts +++ b/src/client.ts @@ -34,6 +34,8 @@ import { CreateCredentialProviderRequest, CredentialProvider, CredentialProviderCreateParams, + CredentialProviderItem, + CredentialProviderListItemsResponse, CredentialProviderListResponse, CredentialProviderTestResult, CredentialProviderUpdateParams, @@ -95,6 +97,7 @@ import { ProxyRetrieveResponse, } from './resources/proxies'; import { Agents } from './resources/agents/agents'; +import { Auth } from './resources/auth/auth'; import { BrowserCreateParams, BrowserCreateResponse, @@ -868,6 +871,7 @@ export class Kernel { invocations: API.Invocations = new API.Invocations(this); browsers: API.Browsers = new API.Browsers(this); profiles: API.Profiles = new API.Profiles(this); + auth: API.Auth = new API.Auth(this); proxies: API.Proxies = new API.Proxies(this); extensions: API.Extensions = new API.Extensions(this); browserPools: API.BrowserPools = new API.BrowserPools(this); @@ -881,6 +885,7 @@ Kernel.Apps = Apps; Kernel.Invocations = Invocations; Kernel.Browsers = Browsers; Kernel.Profiles = Profiles; +Kernel.Auth = Auth; Kernel.Proxies = Proxies; Kernel.Extensions = Extensions; Kernel.BrowserPools = BrowserPools; @@ -956,6 +961,8 @@ export declare namespace Kernel { type ProfileCreateParams as ProfileCreateParams, }; + export { Auth as Auth }; + export { Proxies as Proxies, type ProxyCreateResponse as ProxyCreateResponse, @@ -1003,9 +1010,11 @@ export declare namespace Kernel { CredentialProviders as CredentialProviders, type CreateCredentialProviderRequest as CreateCredentialProviderRequest, type CredentialProvider as CredentialProvider, + type CredentialProviderItem as CredentialProviderItem, type CredentialProviderTestResult as CredentialProviderTestResult, type UpdateCredentialProviderRequest as UpdateCredentialProviderRequest, type CredentialProviderListResponse as CredentialProviderListResponse, + type CredentialProviderListItemsResponse as CredentialProviderListItemsResponse, type CredentialProviderCreateParams as CredentialProviderCreateParams, type CredentialProviderUpdateParams as CredentialProviderUpdateParams, }; diff --git a/src/resources/agents/auth/auth.ts b/src/resources/agents/auth/auth.ts index 570308e8..e4de6ba6 100644 --- a/src/resources/agents/auth/auth.ts +++ b/src/resources/agents/auth/auth.ts @@ -19,46 +19,33 @@ export class Auth extends APIResource { invocations: InvocationsAPI.Invocations = new InvocationsAPI.Invocations(this._client); /** - * Creates a new auth agent for the specified domain and profile combination, or - * returns an existing one if it already exists. This is idempotent - calling with - * the same domain and profile will return the same agent. Does NOT start an - * invocation - use POST /agents/auth/invocations to start an auth flow. + * **Deprecated: Use POST /auth/connections instead.** Creates a new auth agent for + * the specified domain and profile combination, or returns an existing one if it + * already exists. This is idempotent - calling with the same domain and profile + * will return the same agent. Does NOT start an invocation - use POST + * /agents/auth/invocations to start an auth flow. * - * @example - * ```ts - * const authAgent = await client.agents.auth.create({ - * domain: 'netflix.com', - * profile_name: 'user-123', - * }); - * ``` + * @deprecated */ create(body: AuthCreateParams, options?: RequestOptions): APIPromise { return this._client.post('/agents/auth', { body, ...options }); } /** - * Retrieve an auth agent by its ID. Returns the current authentication status of - * the managed profile. + * **Deprecated: Use GET /auth/connections/{id} instead.** Retrieve an auth agent + * by its ID. Returns the current authentication status of the managed profile. * - * @example - * ```ts - * const authAgent = await client.agents.auth.retrieve('id'); - * ``` + * @deprecated */ retrieve(id: string, options?: RequestOptions): APIPromise { return this._client.get(path`/agents/auth/${id}`, options); } /** - * List auth agents with optional filters for profile_name and domain. + * **Deprecated: Use GET /auth/connections instead.** List auth agents with + * optional filters for profile_name and domain. * - * @example - * ```ts - * // Automatically fetches more pages as needed. - * for await (const authAgent of client.agents.auth.list()) { - * // ... - * } - * ``` + * @deprecated */ list( query: AuthListParams | null | undefined = {}, @@ -68,16 +55,14 @@ export class Auth extends APIResource { } /** - * Deletes an auth agent and terminates its workflow. This will: + * **Deprecated: Use DELETE /auth/connections/{id} instead.** Deletes an auth agent + * and terminates its workflow. This will: * * - Soft delete the auth agent record * - Gracefully terminate the agent's Temporal workflow * - Cancel any in-progress invocations * - * @example - * ```ts - * await client.agents.auth.delete('id'); - * ``` + * @deprecated */ delete(id: string, options?: RequestOptions): APIPromise { return this._client.delete(path`/agents/auth/${id}`, { @@ -126,13 +111,12 @@ export interface AgentAuthInvocationResponse { | 'expired'; /** - * The invocation type: + * The session type: * - * - login: First-time authentication - * - reauth: Re-authentication for previously authenticated agents - * - auto_login: Legacy type (no longer created, kept for backward compatibility) + * - login: User-initiated authentication + * - reauth: System-triggered re-authentication (via health check) */ - type: 'login' | 'auto_login' | 'reauth'; + type: 'login' | 'reauth'; /** * Error message explaining why the invocation failed (present when status=FAILED) @@ -188,9 +172,9 @@ export namespace AgentAuthInvocationResponse { label: string; /** - * The MFA delivery method type + * The MFA delivery method type (includes password for auth method selection pages) */ - type: 'sms' | 'call' | 'email' | 'totp' | 'push' | 'security_key'; + type: 'sms' | 'call' | 'email' | 'totp' | 'push' | 'password'; /** * Additional instructions from the site @@ -263,6 +247,21 @@ export interface AuthAgent { * Additional domains that are valid for this auth agent's authentication flow * (besides the primary domain). Useful when login pages redirect to different * domains. + * + * The following SSO/OAuth provider domains are automatically allowed by default + * and do not need to be specified: + * + * - Google: accounts.google.com + * - Microsoft/Azure AD: login.microsoftonline.com, login.live.com + * - Okta: _.okta.com, _.oktapreview.com + * - Auth0: _.auth0.com, _.us.auth0.com, _.eu.auth0.com, _.au.auth0.com + * - Apple: appleid.apple.com + * - GitHub: github.com + * - Facebook/Meta: www.facebook.com + * - LinkedIn: www.linkedin.com + * - Amazon Cognito: \*.amazoncognito.com + * - OneLogin: \*.onelogin.com + * - Ping Identity: _.pingone.com, _.pingidentity.com */ allowed_domains?: Array; @@ -273,14 +272,19 @@ export interface AuthAgent { can_reauth?: boolean; /** - * ID of the linked credential for automatic re-authentication + * Reference to credentials for managed auth. Use one of: + * + * - { name } for Kernel credentials + * - { provider, path } for external provider item + * - { provider, auto: true } for external provider domain lookup */ - credential_id?: string; + credential?: AuthAgent.Credential; /** - * Name of the linked credential for automatic re-authentication + * ID of the linked Kernel credential for automatic re-authentication (deprecated, + * use credential) */ - credential_name?: string; + credential_id?: string; /** * Whether this auth agent has stored selectors for deterministic re-authentication @@ -299,6 +303,37 @@ export interface AuthAgent { post_login_url?: string; } +export namespace AuthAgent { + /** + * Reference to credentials for managed auth. Use one of: + * + * - { name } for Kernel credentials + * - { provider, path } for external provider item + * - { provider, auto: true } for external provider domain lookup + */ + export interface Credential { + /** + * If true, lookup by domain from the specified provider + */ + auto?: boolean; + + /** + * Kernel credential name + */ + name?: string; + + /** + * Provider-specific path (e.g., "VaultName/ItemName" for 1Password) + */ + path?: string; + + /** + * External provider name (e.g., "my-1p") + */ + provider?: string; + } +} + /** * Request to create or find an auth agent */ @@ -317,6 +352,21 @@ export interface AuthAgentCreateRequest { * Additional domains that are valid for this auth agent's authentication flow * (besides the primary domain). Useful when login pages redirect to different * domains. + * + * The following SSO/OAuth provider domains are automatically allowed by default + * and do not need to be specified: + * + * - Google: accounts.google.com + * - Microsoft/Azure AD: login.microsoftonline.com, login.live.com + * - Okta: _.okta.com, _.oktapreview.com + * - Auth0: _.auth0.com, _.us.auth0.com, _.eu.auth0.com, _.au.auth0.com + * - Apple: appleid.apple.com + * - GitHub: github.com + * - Facebook/Meta: www.facebook.com + * - LinkedIn: www.linkedin.com + * - Amazon Cognito: \*.amazoncognito.com + * - OneLogin: \*.onelogin.com + * - Ping Identity: _.pingone.com, _.pingidentity.com */ allowed_domains?: Array; @@ -393,13 +443,12 @@ export interface AuthAgentInvocationCreateResponse { invocation_id: string; /** - * The invocation type: + * The session type: * - * - login: First-time authentication - * - reauth: Re-authentication for previously authenticated agents - * - auto_login: Legacy type (no longer created, kept for backward compatibility) + * - login: User-initiated authentication + * - reauth: System-triggered re-authentication (via health check) */ - type: 'login' | 'auto_login' | 'reauth'; + type: 'login' | 'reauth'; } /** @@ -426,6 +475,12 @@ export interface DiscoveredField { */ type: 'text' | 'email' | 'password' | 'tel' | 'number' | 'url' | 'code' | 'totp'; + /** + * If this field is associated with an MFA option, the type of that option (e.g., + * password field linked to "Enter password" option) + */ + linked_mfa_type?: 'sms' | 'call' | 'email' | 'totp' | 'push' | 'password' | null; + /** * Field placeholder */ @@ -452,6 +507,21 @@ export interface AuthCreateParams { * Additional domains that are valid for this auth agent's authentication flow * (besides the primary domain). Useful when login pages redirect to different * domains. + * + * The following SSO/OAuth provider domains are automatically allowed by default + * and do not need to be specified: + * + * - Google: accounts.google.com + * - Microsoft/Azure AD: login.microsoftonline.com, login.live.com + * - Okta: _.okta.com, _.oktapreview.com + * - Auth0: _.auth0.com, _.us.auth0.com, _.eu.auth0.com, _.au.auth0.com + * - Apple: appleid.apple.com + * - GitHub: github.com + * - Facebook/Meta: www.facebook.com + * - LinkedIn: www.linkedin.com + * - Amazon Cognito: \*.amazoncognito.com + * - OneLogin: \*.onelogin.com + * - Ping Identity: _.pingone.com, _.pingidentity.com */ allowed_domains?: Array; diff --git a/src/resources/agents/auth/invocations.ts b/src/resources/agents/auth/invocations.ts index 3a25011d..b41ea8e3 100644 --- a/src/resources/agents/auth/invocations.ts +++ b/src/resources/agents/auth/invocations.ts @@ -8,17 +8,11 @@ import { path } from '../../../internal/utils/path'; export class Invocations extends APIResource { /** - * Creates a new authentication invocation for the specified auth agent. This - * starts the auth flow and returns a hosted URL for the user to complete - * authentication. + * **Deprecated: Use POST /auth/connections/{id}/login instead.** Creates a new + * authentication invocation for the specified auth agent. This starts the auth + * flow and returns a hosted URL for the user to complete authentication. * - * @example - * ```ts - * const authAgentInvocationCreateResponse = - * await client.agents.auth.invocations.create({ - * auth_agent_id: 'abc123xyz', - * }); - * ``` + * @deprecated */ create( body: InvocationCreateParams, @@ -28,33 +22,22 @@ export class Invocations extends APIResource { } /** - * Returns invocation details including status, app_name, and domain. Supports both - * API key and JWT (from exchange endpoint) authentication. + * **Deprecated: Use GET /auth/connections/{id} instead.** Returns invocation + * details including status, app_name, and domain. Supports both API key and JWT + * (from exchange endpoint) authentication. * - * @example - * ```ts - * const agentAuthInvocationResponse = - * await client.agents.auth.invocations.retrieve( - * 'invocation_id', - * ); - * ``` + * @deprecated */ retrieve(invocationID: string, options?: RequestOptions): APIPromise { return this._client.get(path`/agents/auth/invocations/${invocationID}`, options); } /** - * Validates the handoff code and returns a JWT token for subsequent requests. No - * authentication required (the handoff code serves as the credential). + * **Deprecated: Use POST /auth/connections/{id}/exchange instead.** Validates the + * handoff code and returns a JWT token for subsequent requests. No authentication + * required (the handoff code serves as the credential). * - * @example - * ```ts - * const response = - * await client.agents.auth.invocations.exchange( - * 'invocation_id', - * { code: 'abc123xyz' }, - * ); - * ``` + * @deprecated */ exchange( invocationID: string, @@ -65,23 +48,11 @@ export class Invocations extends APIResource { } /** - * Submits field values for the discovered login form. Returns immediately after - * submission is accepted. Poll the invocation endpoint to track progress and get - * results. + * **Deprecated: Use POST /auth/connections/{id}/submit instead.** Submits field + * values for the discovered login form. Returns immediately after submission is + * accepted. Poll the invocation endpoint to track progress and get results. * - * @example - * ```ts - * const agentAuthSubmitResponse = - * await client.agents.auth.invocations.submit( - * 'invocation_id', - * { - * field_values: { - * email: 'user@example.com', - * password: '********', - * }, - * }, - * ); - * ``` + * @deprecated */ submit( invocationID: string, @@ -150,9 +121,9 @@ export declare namespace InvocationSubmitParams { export interface Variant2 { /** - * The MFA delivery method type + * The MFA delivery method type (includes password for auth method selection pages) */ - selected_mfa_type: 'sms' | 'call' | 'email' | 'totp' | 'push' | 'security_key'; + selected_mfa_type: 'sms' | 'call' | 'email' | 'totp' | 'push' | 'password'; } } diff --git a/src/resources/auth.ts b/src/resources/auth.ts new file mode 100644 index 00000000..b64faa13 --- /dev/null +++ b/src/resources/auth.ts @@ -0,0 +1,3 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export * from './auth/index'; diff --git a/src/resources/auth/auth.ts b/src/resources/auth/auth.ts new file mode 100644 index 00000000..2aaa817d --- /dev/null +++ b/src/resources/auth/auth.ts @@ -0,0 +1,43 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../core/resource'; +import * as ConnectionsAPI from './connections'; +import { + ConnectionCreateParams, + ConnectionFollowResponse, + ConnectionListParams, + ConnectionLoginParams, + ConnectionSubmitParams, + Connections, + LoginRequest, + LoginResponse, + ManagedAuth, + ManagedAuthCreateRequest, + ManagedAuthsOffsetPagination, + SubmitFieldsRequest, + SubmitFieldsResponse, +} from './connections'; + +export class Auth extends APIResource { + connections: ConnectionsAPI.Connections = new ConnectionsAPI.Connections(this._client); +} + +Auth.Connections = Connections; + +export declare namespace Auth { + export { + Connections as Connections, + type LoginRequest as LoginRequest, + type LoginResponse as LoginResponse, + type ManagedAuth as ManagedAuth, + type ManagedAuthCreateRequest as ManagedAuthCreateRequest, + type SubmitFieldsRequest as SubmitFieldsRequest, + type SubmitFieldsResponse as SubmitFieldsResponse, + type ConnectionFollowResponse as ConnectionFollowResponse, + type ManagedAuthsOffsetPagination as ManagedAuthsOffsetPagination, + type ConnectionCreateParams as ConnectionCreateParams, + type ConnectionListParams as ConnectionListParams, + type ConnectionLoginParams as ConnectionLoginParams, + type ConnectionSubmitParams as ConnectionSubmitParams, + }; +} diff --git a/src/resources/auth/connections.ts b/src/resources/auth/connections.ts new file mode 100644 index 00000000..3479a5ef --- /dev/null +++ b/src/resources/auth/connections.ts @@ -0,0 +1,843 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../core/resource'; +import * as Shared from '../shared'; +import * as AuthAPI from '../agents/auth/auth'; +import { APIPromise } from '../../core/api-promise'; +import { OffsetPagination, type OffsetPaginationParams, PagePromise } from '../../core/pagination'; +import { Stream } from '../../core/streaming'; +import { buildHeaders } from '../../internal/headers'; +import { RequestOptions } from '../../internal/request-options'; +import { path } from '../../internal/utils/path'; + +export class Connections extends APIResource { + /** + * Creates managed authentication for a profile and domain combination. Returns 409 + * Conflict if managed auth already exists for the given profile and domain. + * + * @example + * ```ts + * const managedAuth = await client.auth.connections.create({ + * domain: 'netflix.com', + * profile_name: 'user-123', + * }); + * ``` + */ + create(body: ConnectionCreateParams, options?: RequestOptions): APIPromise { + return this._client.post('/auth/connections', { body, ...options }); + } + + /** + * Retrieve managed auth by its ID. Includes current flow state if a login is in + * progress. + * + * @example + * ```ts + * const managedAuth = await client.auth.connections.retrieve( + * 'id', + * ); + * ``` + */ + retrieve(id: string, options?: RequestOptions): APIPromise { + return this._client.get(path`/auth/connections/${id}`, options); + } + + /** + * List managed auths with optional filters for profile_name and domain. + * + * @example + * ```ts + * // Automatically fetches more pages as needed. + * for await (const managedAuth of client.auth.connections.list()) { + * // ... + * } + * ``` + */ + list( + query: ConnectionListParams | null | undefined = {}, + options?: RequestOptions, + ): PagePromise { + return this._client.getAPIList('/auth/connections', OffsetPagination, { query, ...options }); + } + + /** + * Deletes managed auth and terminates its workflow. This will: + * + * - Delete the managed auth record + * - Terminate the Temporal workflow + * - Cancel any in-progress login flows + * + * @example + * ```ts + * await client.auth.connections.delete('id'); + * ``` + */ + delete(id: string, options?: RequestOptions): APIPromise { + return this._client.delete(path`/auth/connections/${id}`, { + ...options, + headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), + }); + } + + /** + * Establishes a Server-Sent Events (SSE) stream that delivers real-time login flow + * state updates. The stream terminates automatically once the flow reaches a + * terminal state (SUCCESS, FAILED, EXPIRED, CANCELED). + * + * @example + * ```ts + * const response = await client.auth.connections.follow('id'); + * ``` + */ + follow(id: string, options?: RequestOptions): APIPromise> { + return this._client.get(path`/auth/connections/${id}/events`, { + ...options, + headers: buildHeaders([{ Accept: 'text/event-stream' }, options?.headers]), + stream: true, + }) as APIPromise>; + } + + /** + * Starts a login flow for the managed auth. Returns immediately with a hosted URL + * for the user to complete authentication, or triggers automatic re-auth if + * credentials are stored. + * + * @example + * ```ts + * const loginResponse = await client.auth.connections.login( + * 'id', + * ); + * ``` + */ + login( + id: string, + body: ConnectionLoginParams | null | undefined = {}, + options?: RequestOptions, + ): APIPromise { + return this._client.post(path`/auth/connections/${id}/login`, { body, ...options }); + } + + /** + * Submits field values for the login form. Poll the managed auth to track progress + * and get results. + * + * @example + * ```ts + * const submitFieldsResponse = + * await client.auth.connections.submit('id', { + * fields: { + * email: 'user@example.com', + * password: 'secret', + * }, + * }); + * ``` + */ + submit( + id: string, + body: ConnectionSubmitParams, + options?: RequestOptions, + ): APIPromise { + return this._client.post(path`/auth/connections/${id}/submit`, { body, ...options }); + } +} + +export type ManagedAuthsOffsetPagination = OffsetPagination; + +/** + * Request to start a login flow + */ +export interface LoginRequest { + /** + * If provided, saves credentials under this name upon successful login + */ + save_credential_as?: string; +} + +/** + * Response from starting a login flow + */ +export interface LoginResponse { + /** + * Managed auth ID + */ + id: string; + + /** + * When the login flow expires + */ + flow_expires_at: string; + + /** + * Type of login flow started + */ + flow_type: 'LOGIN' | 'REAUTH'; + + /** + * URL to redirect user to for login + */ + hosted_url: string; + + /** + * One-time code for handoff (internal use) + */ + handoff_code?: string; + + /** + * Browser live view URL for watching the login flow + */ + live_view_url?: string; +} + +/** + * Managed authentication that keeps a profile logged into a specific domain. Flow + * fields (flow_status, flow_step, discovered_fields, mfa_options) reflect the most + * recent login flow and are null when no flow has been initiated. + */ +export interface ManagedAuth { + /** + * Unique identifier for the managed auth + */ + id: string; + + /** + * Target domain for authentication + */ + domain: string; + + /** + * Name of the profile associated with this managed auth + */ + profile_name: string; + + /** + * Current authentication status of the managed profile + */ + status: 'AUTHENTICATED' | 'NEEDS_AUTH'; + + /** + * Additional domains that are valid for this auth flow (besides the primary + * domain). Useful when login pages redirect to different domains. + * + * The following SSO/OAuth provider domains are automatically allowed by default + * and do not need to be specified: + * + * - Google: accounts.google.com + * - Microsoft/Azure AD: login.microsoftonline.com, login.live.com + * - Okta: _.okta.com, _.oktapreview.com + * - Auth0: _.auth0.com, _.us.auth0.com, _.eu.auth0.com, _.au.auth0.com + * - Apple: appleid.apple.com + * - GitHub: github.com + * - Facebook/Meta: www.facebook.com + * - LinkedIn: www.linkedin.com + * - Amazon Cognito: \*.amazoncognito.com + * - OneLogin: \*.onelogin.com + * - Ping Identity: _.pingone.com, _.pingidentity.com + */ + allowed_domains?: Array; + + /** + * Whether automatic re-authentication is possible (has credential, selectors, and + * login_url) + */ + can_reauth?: boolean; + + /** + * Reference to credentials for managed auth. Use one of: + * + * - { name } for Kernel credentials + * - { provider, path } for external provider item + * - { provider, auto: true } for external provider domain lookup + */ + credential?: ManagedAuth.Credential; + + /** + * Fields awaiting input (present when flow_step=awaiting_input) + */ + discovered_fields?: Array | null; + + /** + * Error message (present when flow_status=failed) + */ + error_message?: string | null; + + /** + * Instructions for external action (present when + * flow_step=awaiting_external_action) + */ + external_action_message?: string | null; + + /** + * When the current flow expires (null when no flow in progress) + */ + flow_expires_at?: string | null; + + /** + * Current flow status (null when no flow in progress) + */ + flow_status?: 'IN_PROGRESS' | 'SUCCESS' | 'FAILED' | 'EXPIRED' | 'CANCELED' | null; + + /** + * Current step in the flow (null when no flow in progress) + */ + flow_step?: + | 'DISCOVERING' + | 'AWAITING_INPUT' + | 'AWAITING_EXTERNAL_ACTION' + | 'SUBMITTING' + | 'COMPLETED' + | null; + + /** + * Type of the current flow (null when no flow in progress) + */ + flow_type?: 'LOGIN' | 'REAUTH' | null; + + /** + * Interval in seconds between automatic health checks. When set, the system + * periodically verifies the authentication status and triggers re-authentication + * if needed. Must be between 300 (5 minutes) and 86400 (24 hours). Default is 3600 + * (1 hour). + */ + health_check_interval?: number | null; + + /** + * URL to redirect user to for hosted login (present when flow in progress) + */ + hosted_url?: string | null; + + /** + * When the profile was last successfully authenticated + */ + last_auth_at?: string; + + /** + * Browser live view URL for debugging (present when flow in progress) + */ + live_view_url?: string | null; + + /** + * MFA method options (present when flow_step=awaiting_input and MFA selection + * required) + */ + mfa_options?: Array | null; + + /** + * SSO buttons available (present when flow_step=awaiting_input) + */ + pending_sso_buttons?: Array | null; + + /** + * URL where the browser landed after successful login + */ + post_login_url?: string; + + /** + * SSO provider being used (e.g., google, github, microsoft) + */ + sso_provider?: string | null; + + /** + * Visible error message from the website (e.g., 'Incorrect password'). Present + * when the website displays an error during login. + */ + website_error?: string | null; +} + +export namespace ManagedAuth { + /** + * Reference to credentials for managed auth. Use one of: + * + * - { name } for Kernel credentials + * - { provider, path } for external provider item + * - { provider, auto: true } for external provider domain lookup + */ + export interface Credential { + /** + * If true, lookup by domain from the specified provider + */ + auto?: boolean; + + /** + * Kernel credential name + */ + name?: string; + + /** + * Provider-specific path (e.g., "VaultName/ItemName" for 1Password) + */ + path?: string; + + /** + * External provider name (e.g., "my-1p") + */ + provider?: string; + } + + /** + * An MFA method option for verification + */ + export interface MfaOption { + /** + * The visible option text + */ + label: string; + + /** + * The MFA delivery method type (includes password for auth method selection pages) + */ + type: 'sms' | 'call' | 'email' | 'totp' | 'push' | 'password'; + + /** + * Additional instructions from the site + */ + description?: string | null; + + /** + * The masked destination (phone/email) if shown + */ + target?: string | null; + } + + /** + * An SSO button for signing in with an external identity provider + */ + export interface PendingSSOButton { + /** + * Visible button text + */ + label: string; + + /** + * Identity provider name + */ + provider: string; + + /** + * XPath selector for the button + */ + selector: string; + } +} + +/** + * Request to create managed auth for a profile and domain + */ +export interface ManagedAuthCreateRequest { + /** + * Domain for authentication + */ + domain: string; + + /** + * Name of the profile to manage authentication for + */ + profile_name: string; + + /** + * Additional domains valid for this auth flow (besides the primary domain). Useful + * when login pages redirect to different domains. + * + * The following SSO/OAuth provider domains are automatically allowed by default + * and do not need to be specified: + * + * - Google: accounts.google.com + * - Microsoft/Azure AD: login.microsoftonline.com, login.live.com + * - Okta: _.okta.com, _.oktapreview.com + * - Auth0: _.auth0.com, _.us.auth0.com, _.eu.auth0.com, _.au.auth0.com + * - Apple: appleid.apple.com + * - GitHub: github.com + * - Facebook/Meta: www.facebook.com + * - LinkedIn: www.linkedin.com + * - Amazon Cognito: \*.amazoncognito.com + * - OneLogin: \*.onelogin.com + * - Ping Identity: _.pingone.com, _.pingidentity.com + */ + allowed_domains?: Array; + + /** + * Reference to credentials for managed auth. Use one of: + * + * - { name } for Kernel credentials + * - { provider, path } for external provider item + * - { provider, auto: true } for external provider domain lookup + */ + credential?: ManagedAuthCreateRequest.Credential; + + /** + * Interval in seconds between automatic health checks. When set, the system + * periodically verifies the authentication status and triggers re-authentication + * if needed. Must be between 300 (5 minutes) and 86400 (24 hours). Default is 3600 + * (1 hour). + */ + health_check_interval?: number; + + /** + * Optional login page URL to skip discovery + */ + login_url?: string; + + /** + * Optional proxy configuration + */ + proxy?: ManagedAuthCreateRequest.Proxy; +} + +export namespace ManagedAuthCreateRequest { + /** + * Reference to credentials for managed auth. Use one of: + * + * - { name } for Kernel credentials + * - { provider, path } for external provider item + * - { provider, auto: true } for external provider domain lookup + */ + export interface Credential { + /** + * If true, lookup by domain from the specified provider + */ + auto?: boolean; + + /** + * Kernel credential name + */ + name?: string; + + /** + * Provider-specific path (e.g., "VaultName/ItemName" for 1Password) + */ + path?: string; + + /** + * External provider name (e.g., "my-1p") + */ + provider?: string; + } + + /** + * Optional proxy configuration + */ + export interface Proxy { + /** + * ID of the proxy to use + */ + proxy_id?: string; + } +} + +/** + * Request to submit field values for login + */ +export interface SubmitFieldsRequest { + /** + * Map of field name to value + */ + fields: { [key: string]: string }; + + /** + * Optional MFA option ID if user selected an MFA method + */ + mfa_option_id?: string; + + /** + * Optional XPath selector if user chose to click an SSO button instead + */ + sso_button_selector?: string; +} + +/** + * Response from submitting field values + */ +export interface SubmitFieldsResponse { + /** + * Whether the submission was accepted for processing + */ + accepted: boolean; +} + +/** + * Union type representing any managed auth event. + */ +export type ConnectionFollowResponse = + | ConnectionFollowResponse.ManagedAuthStateEvent + | Shared.ErrorEvent + | Shared.HeartbeatEvent; + +export namespace ConnectionFollowResponse { + /** + * An event representing the current state of a managed auth flow. + */ + export interface ManagedAuthStateEvent { + /** + * Event type identifier (always "managed_auth_state"). + */ + event: 'managed_auth_state'; + + /** + * Current flow status. + */ + flow_status: 'IN_PROGRESS' | 'SUCCESS' | 'FAILED' | 'EXPIRED' | 'CANCELED'; + + /** + * Current step in the flow. + */ + flow_step: 'DISCOVERING' | 'AWAITING_INPUT' | 'AWAITING_EXTERNAL_ACTION' | 'SUBMITTING' | 'COMPLETED'; + + /** + * Time the state was reported. + */ + timestamp: string; + + /** + * Fields awaiting input (present when flow_step=AWAITING_INPUT). + */ + discovered_fields?: Array; + + /** + * Error message (present when flow_status=FAILED). + */ + error_message?: string; + + /** + * Instructions for external action (present when + * flow_step=AWAITING_EXTERNAL_ACTION). + */ + external_action_message?: string; + + /** + * Type of the current flow. + */ + flow_type?: 'LOGIN' | 'REAUTH'; + + /** + * URL to redirect user to for hosted login. + */ + hosted_url?: string; + + /** + * Browser live view URL for debugging. + */ + live_view_url?: string; + + /** + * MFA method options (present when flow_step=AWAITING_INPUT and MFA selection + * required). + */ + mfa_options?: Array; + + /** + * SSO buttons available (present when flow_step=AWAITING_INPUT). + */ + pending_sso_buttons?: Array; + + /** + * URL where the browser landed after successful login. + */ + post_login_url?: string; + + /** + * Visible error message from the website (e.g., 'Incorrect password'). Present + * when the website displays an error during login. + */ + website_error?: string; + } + + export namespace ManagedAuthStateEvent { + /** + * An MFA method option for verification + */ + export interface MfaOption { + /** + * The visible option text + */ + label: string; + + /** + * The MFA delivery method type (includes password for auth method selection pages) + */ + type: 'sms' | 'call' | 'email' | 'totp' | 'push' | 'password'; + + /** + * Additional instructions from the site + */ + description?: string | null; + + /** + * The masked destination (phone/email) if shown + */ + target?: string | null; + } + + /** + * An SSO button for signing in with an external identity provider + */ + export interface PendingSSOButton { + /** + * Visible button text + */ + label: string; + + /** + * Identity provider name + */ + provider: string; + + /** + * XPath selector for the button + */ + selector: string; + } + } +} + +export interface ConnectionCreateParams { + /** + * Domain for authentication + */ + domain: string; + + /** + * Name of the profile to manage authentication for + */ + profile_name: string; + + /** + * Additional domains valid for this auth flow (besides the primary domain). Useful + * when login pages redirect to different domains. + * + * The following SSO/OAuth provider domains are automatically allowed by default + * and do not need to be specified: + * + * - Google: accounts.google.com + * - Microsoft/Azure AD: login.microsoftonline.com, login.live.com + * - Okta: _.okta.com, _.oktapreview.com + * - Auth0: _.auth0.com, _.us.auth0.com, _.eu.auth0.com, _.au.auth0.com + * - Apple: appleid.apple.com + * - GitHub: github.com + * - Facebook/Meta: www.facebook.com + * - LinkedIn: www.linkedin.com + * - Amazon Cognito: \*.amazoncognito.com + * - OneLogin: \*.onelogin.com + * - Ping Identity: _.pingone.com, _.pingidentity.com + */ + allowed_domains?: Array; + + /** + * Reference to credentials for managed auth. Use one of: + * + * - { name } for Kernel credentials + * - { provider, path } for external provider item + * - { provider, auto: true } for external provider domain lookup + */ + credential?: ConnectionCreateParams.Credential; + + /** + * Interval in seconds between automatic health checks. When set, the system + * periodically verifies the authentication status and triggers re-authentication + * if needed. Must be between 300 (5 minutes) and 86400 (24 hours). Default is 3600 + * (1 hour). + */ + health_check_interval?: number; + + /** + * Optional login page URL to skip discovery + */ + login_url?: string; + + /** + * Optional proxy configuration + */ + proxy?: ConnectionCreateParams.Proxy; +} + +export namespace ConnectionCreateParams { + /** + * Reference to credentials for managed auth. Use one of: + * + * - { name } for Kernel credentials + * - { provider, path } for external provider item + * - { provider, auto: true } for external provider domain lookup + */ + export interface Credential { + /** + * If true, lookup by domain from the specified provider + */ + auto?: boolean; + + /** + * Kernel credential name + */ + name?: string; + + /** + * Provider-specific path (e.g., "VaultName/ItemName" for 1Password) + */ + path?: string; + + /** + * External provider name (e.g., "my-1p") + */ + provider?: string; + } + + /** + * Optional proxy configuration + */ + export interface Proxy { + /** + * ID of the proxy to use + */ + proxy_id?: string; + } +} + +export interface ConnectionListParams extends OffsetPaginationParams { + /** + * Filter by domain + */ + domain?: string; + + /** + * Filter by profile name + */ + profile_name?: string; +} + +export interface ConnectionLoginParams { + /** + * If provided, saves credentials under this name upon successful login + */ + save_credential_as?: string; +} + +export interface ConnectionSubmitParams { + /** + * Map of field name to value + */ + fields: { [key: string]: string }; + + /** + * Optional MFA option ID if user selected an MFA method + */ + mfa_option_id?: string; + + /** + * Optional XPath selector if user chose to click an SSO button instead + */ + sso_button_selector?: string; +} + +export declare namespace Connections { + export { + type LoginRequest as LoginRequest, + type LoginResponse as LoginResponse, + type ManagedAuth as ManagedAuth, + type ManagedAuthCreateRequest as ManagedAuthCreateRequest, + type SubmitFieldsRequest as SubmitFieldsRequest, + type SubmitFieldsResponse as SubmitFieldsResponse, + type ConnectionFollowResponse as ConnectionFollowResponse, + type ManagedAuthsOffsetPagination as ManagedAuthsOffsetPagination, + type ConnectionCreateParams as ConnectionCreateParams, + type ConnectionListParams as ConnectionListParams, + type ConnectionLoginParams as ConnectionLoginParams, + type ConnectionSubmitParams as ConnectionSubmitParams, + }; +} diff --git a/src/resources/auth/index.ts b/src/resources/auth/index.ts new file mode 100644 index 00000000..4debc7e9 --- /dev/null +++ b/src/resources/auth/index.ts @@ -0,0 +1,18 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export { Auth } from './auth'; +export { + Connections, + type LoginRequest, + type LoginResponse, + type ManagedAuth, + type ManagedAuthCreateRequest, + type SubmitFieldsRequest, + type SubmitFieldsResponse, + type ConnectionFollowResponse, + type ConnectionCreateParams, + type ConnectionListParams, + type ConnectionLoginParams, + type ConnectionSubmitParams, + type ManagedAuthsOffsetPagination, +} from './connections'; diff --git a/src/resources/credential-providers.ts b/src/resources/credential-providers.ts index 596e9e52..42733a97 100644 --- a/src/resources/credential-providers.ts +++ b/src/resources/credential-providers.ts @@ -16,12 +16,13 @@ export class CredentialProviders extends APIResource { * const credentialProvider = * await client.credentialProviders.create({ * token: 'ops_eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...', + * name: 'my-1password', * provider_type: 'onepassword', * }); * ``` */ create(body: CredentialProviderCreateParams, options?: RequestOptions): APIPromise { - return this._client.post('/org/credential-providers', { body, ...options }); + return this._client.post('/org/credential_providers', { body, ...options }); } /** @@ -34,7 +35,7 @@ export class CredentialProviders extends APIResource { * ``` */ retrieve(id: string, options?: RequestOptions): APIPromise { - return this._client.get(path`/org/credential-providers/${id}`, options); + return this._client.get(path`/org/credential_providers/${id}`, options); } /** @@ -51,7 +52,7 @@ export class CredentialProviders extends APIResource { body: CredentialProviderUpdateParams, options?: RequestOptions, ): APIPromise { - return this._client.patch(path`/org/credential-providers/${id}`, { body, ...options }); + return this._client.patch(path`/org/credential_providers/${id}`, { body, ...options }); } /** @@ -64,7 +65,7 @@ export class CredentialProviders extends APIResource { * ``` */ list(options?: RequestOptions): APIPromise { - return this._client.get('/org/credential-providers', options); + return this._client.get('/org/credential_providers', options); } /** @@ -76,12 +77,27 @@ export class CredentialProviders extends APIResource { * ``` */ delete(id: string, options?: RequestOptions): APIPromise { - return this._client.delete(path`/org/credential-providers/${id}`, { + return this._client.delete(path`/org/credential_providers/${id}`, { ...options, headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), }); } + /** + * Returns available credential items (e.g., 1Password login items) from the + * provider. + * + * @example + * ```ts + * const response = await client.credentialProviders.listItems( + * 'id', + * ); + * ``` + */ + listItems(id: string, options?: RequestOptions): APIPromise { + return this._client.get(path`/org/credential_providers/${id}/items`, options); + } + /** * Validate the credential provider's token and list accessible vaults. * @@ -92,7 +108,7 @@ export class CredentialProviders extends APIResource { * ``` */ test(id: string, options?: RequestOptions): APIPromise { - return this._client.post(path`/org/credential-providers/${id}/test`, options); + return this._client.post(path`/org/credential_providers/${id}/test`, options); } } @@ -105,6 +121,11 @@ export interface CreateCredentialProviderRequest { */ token: string; + /** + * Human-readable name for this provider instance (unique per org) + */ + name: string; + /** * Type of credential provider */ @@ -136,6 +157,11 @@ export interface CredentialProvider { */ enabled: boolean; + /** + * Human-readable name for this provider instance + */ + name: string; + /** * Priority order for credential lookups (lower numbers are checked first) */ @@ -152,6 +178,41 @@ export interface CredentialProvider { updated_at: string; } +/** + * A credential item from an external provider (e.g., a 1Password login item) + */ +export interface CredentialProviderItem { + /** + * Unique identifier for the item within the provider + */ + id: string; + + /** + * Path to reference this item (VaultName/ItemTitle format) + */ + path: string; + + /** + * Display name of the credential item + */ + title: string; + + /** + * ID of the vault containing this item + */ + vault_id: string; + + /** + * Name of the vault containing this item + */ + vault_name: string; + + /** + * URLs associated with this credential + */ + urls?: Array; +} + /** * Result of testing a credential provider connection */ @@ -205,6 +266,11 @@ export interface UpdateCredentialProviderRequest { */ enabled?: boolean; + /** + * Human-readable name for this provider instance + */ + name?: string; + /** * Priority order for credential lookups (lower numbers are checked first) */ @@ -213,12 +279,21 @@ export interface UpdateCredentialProviderRequest { export type CredentialProviderListResponse = Array; +export interface CredentialProviderListItemsResponse { + items?: Array; +} + export interface CredentialProviderCreateParams { /** * Service account token for the provider (e.g., 1Password service account token) */ token: string; + /** + * Human-readable name for this provider instance (unique per org) + */ + name: string; + /** * Type of credential provider */ @@ -246,6 +321,11 @@ export interface CredentialProviderUpdateParams { */ enabled?: boolean; + /** + * Human-readable name for this provider instance + */ + name?: string; + /** * Priority order for credential lookups (lower numbers are checked first) */ @@ -256,9 +336,11 @@ export declare namespace CredentialProviders { export { type CreateCredentialProviderRequest as CreateCredentialProviderRequest, type CredentialProvider as CredentialProvider, + type CredentialProviderItem as CredentialProviderItem, type CredentialProviderTestResult as CredentialProviderTestResult, type UpdateCredentialProviderRequest as UpdateCredentialProviderRequest, type CredentialProviderListResponse as CredentialProviderListResponse, + type CredentialProviderListItemsResponse as CredentialProviderListItemsResponse, type CredentialProviderCreateParams as CredentialProviderCreateParams, type CredentialProviderUpdateParams as CredentialProviderUpdateParams, }; diff --git a/src/resources/index.ts b/src/resources/index.ts index a2d913f7..d29baae8 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -8,6 +8,7 @@ export { type AppListParams, type AppListResponsesOffsetPagination, } from './apps'; +export { Auth } from './auth/auth'; export { BrowserPools, type BrowserPool, @@ -39,9 +40,11 @@ export { CredentialProviders, type CreateCredentialProviderRequest, type CredentialProvider, + type CredentialProviderItem, type CredentialProviderTestResult, type UpdateCredentialProviderRequest, type CredentialProviderListResponse, + type CredentialProviderListItemsResponse, type CredentialProviderCreateParams, type CredentialProviderUpdateParams, } from './credential-providers'; diff --git a/tests/api-resources/auth/connections.test.ts b/tests/api-resources/auth/connections.test.ts new file mode 100644 index 00000000..14c2abf0 --- /dev/null +++ b/tests/api-resources/auth/connections.test.ts @@ -0,0 +1,154 @@ +// 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 connections', () => { + // Prism tests are disabled + test.skip('create: only required params', async () => { + const responsePromise = client.auth.connections.create({ + domain: 'netflix.com', + profile_name: 'user-123', + }); + 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); + }); + + // Prism tests are disabled + test.skip('create: required and optional params', async () => { + const response = await client.auth.connections.create({ + domain: 'netflix.com', + profile_name: 'user-123', + allowed_domains: ['login.netflix.com', 'auth.netflix.com'], + credential: { + auto: true, + name: 'my-netflix-creds', + path: 'Personal/Netflix', + provider: 'my-1p', + }, + health_check_interval: 3600, + login_url: 'https://netflix.com/login', + proxy: { proxy_id: 'proxy_id' }, + }); + }); + + // Prism tests are disabled + test.skip('retrieve', async () => { + const responsePromise = client.auth.connections.retrieve('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); + }); + + // Prism tests are disabled + test.skip('list', async () => { + const responsePromise = client.auth.connections.list(); + 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); + }); + + // Prism tests are disabled + test.skip('list: 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.auth.connections.list( + { + domain: 'domain', + limit: 100, + offset: 0, + profile_name: 'profile_name', + }, + { path: '/_stainless_unknown_path' }, + ), + ).rejects.toThrow(Kernel.NotFoundError); + }); + + // Prism tests are disabled + test.skip('delete', async () => { + const responsePromise = client.auth.connections.delete('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); + }); + + // Prism doesn't support text/event-stream responses + test.skip('follow', async () => { + const responsePromise = client.auth.connections.follow('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); + }); + + // Prism tests are disabled + test.skip('login', async () => { + const responsePromise = client.auth.connections.login('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); + }); + + // Prism tests are disabled + test.skip('login: 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.auth.connections.login( + 'id', + { save_credential_as: 'my-netflix-login' }, + { path: '/_stainless_unknown_path' }, + ), + ).rejects.toThrow(Kernel.NotFoundError); + }); + + // Prism tests are disabled + test.skip('submit: only required params', async () => { + const responsePromise = client.auth.connections.submit('id', { + fields: { email: 'user@example.com', password: 'secret' }, + }); + 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); + }); + + // Prism tests are disabled + test.skip('submit: required and optional params', async () => { + const response = await client.auth.connections.submit('id', { + fields: { email: 'user@example.com', password: 'secret' }, + mfa_option_id: 'sms', + sso_button_selector: "xpath=//button[contains(text(), 'Continue with Google')]", + }); + }); +}); diff --git a/tests/api-resources/credential-providers.test.ts b/tests/api-resources/credential-providers.test.ts index 5a20da8b..5327b203 100644 --- a/tests/api-resources/credential-providers.test.ts +++ b/tests/api-resources/credential-providers.test.ts @@ -12,6 +12,7 @@ describe('resource credentialProviders', () => { test.skip('create: only required params', async () => { const responsePromise = client.credentialProviders.create({ token: 'ops_eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...', + name: 'my-1password', provider_type: 'onepassword', }); const rawResponse = await responsePromise.asResponse(); @@ -27,6 +28,7 @@ describe('resource credentialProviders', () => { test.skip('create: required and optional params', async () => { const response = await client.credentialProviders.create({ token: 'ops_eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...', + name: 'my-1password', provider_type: 'onepassword', cache_ttl_seconds: 300, }); @@ -80,6 +82,18 @@ describe('resource credentialProviders', () => { expect(dataAndResponse.response).toBe(rawResponse); }); + // Prism tests are disabled + test.skip('listItems', async () => { + const responsePromise = client.credentialProviders.listItems('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); + }); + // Prism tests are disabled test.skip('test', async () => { const responsePromise = client.credentialProviders.test('id'); From 0b3e640902c2b57be91fab66a6f5c6ff440e257b Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 6 Feb 2026 20:52:03 +0000 Subject: [PATCH 277/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 8e3d9554..85df4711 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.31.0" + ".": "0.31.1" } diff --git a/package.json b/package.json index 53f4cbd2..5b65c05f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.31.0", + "version": "0.31.1", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index b6314c28..c71c0da2 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.31.0'; // x-release-please-version +export const VERSION = '0.31.1'; // x-release-please-version From 1e0c953a8caf867fae64ffe9c66af743fd5e2c70 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 6 Feb 2026 21:19:28 +0000 Subject: [PATCH 278/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 85df4711..6fef4e56 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.31.1" + ".": "0.31.2" } diff --git a/package.json b/package.json index 5b65c05f..8a102b75 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.31.1", + "version": "0.31.2", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index c71c0da2..a942d18d 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.31.1'; // x-release-please-version +export const VERSION = '0.31.2'; // x-release-please-version From 93bf59805e031f60e2280d2e73b0dbe82f8e35f5 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 7 Feb 2026 18:15:11 +0000 Subject: [PATCH 279/551] chore: switch npm publish to OIDC auth in stainless config --- .github/workflows/publish-npm.yml | 5 +++-- .github/workflows/release-doctor.yml | 2 -- .stats.yml | 2 +- bin/check-release-environment | 4 ---- bin/publish-npm | 13 +++++++++++-- 5 files changed, 15 insertions(+), 11 deletions(-) diff --git a/.github/workflows/publish-npm.yml b/.github/workflows/publish-npm.yml index a6604782..8984e27c 100644 --- a/.github/workflows/publish-npm.yml +++ b/.github/workflows/publish-npm.yml @@ -12,6 +12,9 @@ jobs: publish: name: publish runs-on: ubuntu-latest + permissions: + contents: read + id-token: write steps: - uses: actions/checkout@v6 @@ -28,5 +31,3 @@ jobs: - name: Publish to NPM run: | bash ./bin/publish-npm - env: - NPM_TOKEN: ${{ secrets.KERNEL_NPM_TOKEN || secrets.NPM_TOKEN }} diff --git a/.github/workflows/release-doctor.yml b/.github/workflows/release-doctor.yml index 588ae1bc..2d0c9317 100644 --- a/.github/workflows/release-doctor.yml +++ b/.github/workflows/release-doctor.yml @@ -17,6 +17,4 @@ jobs: - name: Check release environment run: | bash ./bin/check-release-environment - env: - NPM_TOKEN: ${{ secrets.KERNEL_NPM_TOKEN || secrets.NPM_TOKEN }} diff --git a/.stats.yml b/.stats.yml index 29643219..0edbaa27 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 108 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-3fbe762c99e8a120c426ac22bc1fa257c9127d631b12a38a6440a37f52935543.yml openapi_spec_hash: 5a190df210ed90b20a71c5061ff43917 -config_hash: 38c9b3b355025daf9bb643040e4af94e +config_hash: 3b1fbbb6bda0dac7e8b42e155cd7da56 diff --git a/bin/check-release-environment b/bin/check-release-environment index e4b6d58e..6b43775a 100644 --- a/bin/check-release-environment +++ b/bin/check-release-environment @@ -2,10 +2,6 @@ errors=() -if [ -z "${NPM_TOKEN}" ]; then - errors+=("The NPM_TOKEN secret has not been set. Please set it in either this repository's secrets or your organization secrets") -fi - lenErrors=${#errors[@]} if [[ lenErrors -gt 0 ]]; then diff --git a/bin/publish-npm b/bin/publish-npm index 45e8aa80..3d05c0bd 100644 --- a/bin/publish-npm +++ b/bin/publish-npm @@ -2,7 +2,12 @@ set -eux -npm config set '//registry.npmjs.org/:_authToken' "$NPM_TOKEN" +if [[ ${NPM_TOKEN:-} ]]; then + npm config set '//registry.npmjs.org/:_authToken' "$NPM_TOKEN" +elif [[ ! ${ACTIONS_ID_TOKEN_REQUEST_TOKEN:-} ]]; then + echo "ERROR: NPM_TOKEN must be set if not running in a Github Action with id-token permission" + exit 1 +fi yarn build cd dist @@ -57,5 +62,9 @@ else TAG="latest" fi +# Install OIDC compatible npm version +npm install --prefix ../oidc/ npm@11.6.2 + # Publish with the appropriate tag -yarn publish --tag "$TAG" +export npm_config_registry='https://registry.npmjs.org' +../oidc/node_modules/.bin/npm publish --tag "$TAG" From a58779e70229a6e82da5eedc541aec4dc8e0e05d Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 7 Feb 2026 18:15:45 +0000 Subject: [PATCH 280/551] feat(auth): add reauth circuit breaker logic --- .stats.yml | 4 ++-- src/resources/agents/auth/auth.ts | 5 +++++ src/resources/auth/connections.ts | 5 +++++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 0edbaa27..ad62343f 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 108 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-3fbe762c99e8a120c426ac22bc1fa257c9127d631b12a38a6440a37f52935543.yml -openapi_spec_hash: 5a190df210ed90b20a71c5061ff43917 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-f967d3024897a6125d5d18c4577dbb2cc22d742d487e6a43165198685f992379.yml +openapi_spec_hash: e1c40ef0aee3a79168eb9cc854a9e403 config_hash: 3b1fbbb6bda0dac7e8b42e155cd7da56 diff --git a/src/resources/agents/auth/auth.ts b/src/resources/agents/auth/auth.ts index e4de6ba6..c8125182 100644 --- a/src/resources/agents/auth/auth.ts +++ b/src/resources/agents/auth/auth.ts @@ -271,6 +271,11 @@ export interface AuthAgent { */ can_reauth?: boolean; + /** + * Reason why automatic re-authentication is or is not possible + */ + can_reauth_reason?: string; + /** * Reference to credentials for managed auth. Use one of: * diff --git a/src/resources/auth/connections.ts b/src/resources/auth/connections.ts index 3479a5ef..89250926 100644 --- a/src/resources/auth/connections.ts +++ b/src/resources/auth/connections.ts @@ -241,6 +241,11 @@ export interface ManagedAuth { */ can_reauth?: boolean; + /** + * Reason why automatic re-authentication is or is not possible + */ + can_reauth_reason?: string; + /** * Reference to credentials for managed auth. Use one of: * From 3421b3fd366e42d24f320907c4464cec18f62714 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 7 Feb 2026 18:20:00 +0000 Subject: [PATCH 281/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 6fef4e56..47582228 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.31.2" + ".": "0.32.0" } diff --git a/package.json b/package.json index 8a102b75..c05a3e85 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.31.2", + "version": "0.32.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index a942d18d..b413d151 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.31.2'; // x-release-please-version +export const VERSION = '0.32.0'; // x-release-please-version From 38085f9ac029e3b8b837bd146d4f4e8c005c54b9 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 7 Feb 2026 20:23:25 +0000 Subject: [PATCH 282/551] feat: Browser API endpoint grouping --- .stats.yml | 4 +-- src/resources/agents/auth/auth.ts | 4 +-- src/resources/auth/connections.ts | 42 +++++++++++++++---------------- 3 files changed, 25 insertions(+), 25 deletions(-) diff --git a/.stats.yml b/.stats.yml index ad62343f..796d854d 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 108 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-f967d3024897a6125d5d18c4577dbb2cc22d742d487e6a43165198685f992379.yml -openapi_spec_hash: e1c40ef0aee3a79168eb9cc854a9e403 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-848817f2b20afb49a652952c814b99e27a94090e0770465e9a87748d27e227a7.yml +openapi_spec_hash: 91efb805e45cdd4c73cd8b0950bef019 config_hash: 3b1fbbb6bda0dac7e8b42e155cd7da56 diff --git a/src/resources/agents/auth/auth.ts b/src/resources/agents/auth/auth.ts index c8125182..813aa170 100644 --- a/src/resources/agents/auth/auth.ts +++ b/src/resources/agents/auth/auth.ts @@ -277,7 +277,7 @@ export interface AuthAgent { can_reauth_reason?: string; /** - * Reference to credentials for managed auth. Use one of: + * Reference to credentials for the auth connection. Use one of: * * - { name } for Kernel credentials * - { provider, path } for external provider item @@ -310,7 +310,7 @@ export interface AuthAgent { export namespace AuthAgent { /** - * Reference to credentials for managed auth. Use one of: + * Reference to credentials for the auth connection. Use one of: * * - { name } for Kernel credentials * - { provider, path } for external provider item diff --git a/src/resources/auth/connections.ts b/src/resources/auth/connections.ts index 89250926..ff577115 100644 --- a/src/resources/auth/connections.ts +++ b/src/resources/auth/connections.ts @@ -12,8 +12,8 @@ import { path } from '../../internal/utils/path'; export class Connections extends APIResource { /** - * Creates managed authentication for a profile and domain combination. Returns 409 - * Conflict if managed auth already exists for the given profile and domain. + * Creates an auth connection for a profile and domain combination. Returns 409 + * Conflict if an auth connection already exists for the given profile and domain. * * @example * ```ts @@ -28,8 +28,8 @@ export class Connections extends APIResource { } /** - * Retrieve managed auth by its ID. Includes current flow state if a login is in - * progress. + * Retrieve an auth connection by its ID. Includes current flow state if a login is + * in progress. * * @example * ```ts @@ -43,7 +43,7 @@ export class Connections extends APIResource { } /** - * List managed auths with optional filters for profile_name and domain. + * List auth connections with optional filters for profile_name and domain. * * @example * ```ts @@ -61,9 +61,9 @@ export class Connections extends APIResource { } /** - * Deletes managed auth and terminates its workflow. This will: + * Deletes an auth connection and terminates its workflow. This will: * - * - Delete the managed auth record + * - Delete the auth connection record * - Terminate the Temporal workflow * - Cancel any in-progress login flows * @@ -98,8 +98,8 @@ export class Connections extends APIResource { } /** - * Starts a login flow for the managed auth. Returns immediately with a hosted URL - * for the user to complete authentication, or triggers automatic re-auth if + * Starts a login flow for the auth connection. Returns immediately with a hosted + * URL for the user to complete authentication, or triggers automatic re-auth if * credentials are stored. * * @example @@ -118,8 +118,8 @@ export class Connections extends APIResource { } /** - * Submits field values for the login form. Poll the managed auth to track progress - * and get results. + * Submits field values for the login form. Poll the auth connection to track + * progress and get results. * * @example * ```ts @@ -158,7 +158,7 @@ export interface LoginRequest { */ export interface LoginResponse { /** - * Managed auth ID + * Auth connection ID */ id: string; @@ -195,7 +195,7 @@ export interface LoginResponse { */ export interface ManagedAuth { /** - * Unique identifier for the managed auth + * Unique identifier for the auth connection */ id: string; @@ -205,7 +205,7 @@ export interface ManagedAuth { domain: string; /** - * Name of the profile associated with this managed auth + * Name of the profile associated with this auth connection */ profile_name: string; @@ -247,7 +247,7 @@ export interface ManagedAuth { can_reauth_reason?: string; /** - * Reference to credentials for managed auth. Use one of: + * Reference to credentials for the auth connection. Use one of: * * - { name } for Kernel credentials * - { provider, path } for external provider item @@ -350,7 +350,7 @@ export interface ManagedAuth { export namespace ManagedAuth { /** - * Reference to credentials for managed auth. Use one of: + * Reference to credentials for the auth connection. Use one of: * * - { name } for Kernel credentials * - { provider, path } for external provider item @@ -425,7 +425,7 @@ export namespace ManagedAuth { } /** - * Request to create managed auth for a profile and domain + * Request to create an auth connection for a profile and domain */ export interface ManagedAuthCreateRequest { /** @@ -460,7 +460,7 @@ export interface ManagedAuthCreateRequest { allowed_domains?: Array; /** - * Reference to credentials for managed auth. Use one of: + * Reference to credentials for the auth connection. Use one of: * * - { name } for Kernel credentials * - { provider, path } for external provider item @@ -489,7 +489,7 @@ export interface ManagedAuthCreateRequest { export namespace ManagedAuthCreateRequest { /** - * Reference to credentials for managed auth. Use one of: + * Reference to credentials for the auth connection. Use one of: * * - { name } for Kernel credentials * - { provider, path } for external provider item @@ -726,7 +726,7 @@ export interface ConnectionCreateParams { allowed_domains?: Array; /** - * Reference to credentials for managed auth. Use one of: + * Reference to credentials for the auth connection. Use one of: * * - { name } for Kernel credentials * - { provider, path } for external provider item @@ -755,7 +755,7 @@ export interface ConnectionCreateParams { export namespace ConnectionCreateParams { /** - * Reference to credentials for managed auth. Use one of: + * Reference to credentials for the auth connection. Use one of: * * - { name } for Kernel credentials * - { provider, path } for external provider item From 6b2a740507cd74735f244c9574073be38a6b5d8f Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 9 Feb 2026 19:24:44 +0000 Subject: [PATCH 283/551] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 796d854d..15c374f0 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 108 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-848817f2b20afb49a652952c814b99e27a94090e0770465e9a87748d27e227a7.yml -openapi_spec_hash: 91efb805e45cdd4c73cd8b0950bef019 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-13e82ae9e725e2c3ca19da7248a7a9c8696a0dfe088654cf26aea07c76d6567a.yml +openapi_spec_hash: 6d4151a6066a8474bc56923299aec18a config_hash: 3b1fbbb6bda0dac7e8b42e155cd7da56 From cf4425f2b06b9e77b5172da6f16f8bf565ae58a8 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 10 Feb 2026 01:48:26 +0000 Subject: [PATCH 284/551] =?UTF-8?q?refactor(api):=20remove=20deprecated=20?= =?UTF-8?q?agent-auth=20endpoints=20from=20stainless.=E2=80=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .stats.yml | 4 +- api.md | 34 - src/client.ts | 5 - src/resources/agents.ts | 3 - src/resources/agents/agents.ts | 39 -- src/resources/agents/auth.ts | 3 - src/resources/agents/auth/auth.ts | 599 ------------------ src/resources/agents/auth/index.ts | 22 - src/resources/agents/auth/invocations.ts | 137 ---- src/resources/agents/index.ts | 16 - src/resources/auth/connections.ts | 87 ++- src/resources/index.ts | 1 - tests/api-resources/agents/auth/auth.test.ts | 86 --- .../agents/auth/invocations.test.ts | 80 --- 14 files changed, 86 insertions(+), 1030 deletions(-) delete mode 100644 src/resources/agents.ts delete mode 100644 src/resources/agents/agents.ts delete mode 100644 src/resources/agents/auth.ts delete mode 100644 src/resources/agents/auth/auth.ts delete mode 100644 src/resources/agents/auth/index.ts delete mode 100644 src/resources/agents/auth/invocations.ts delete mode 100644 src/resources/agents/index.ts delete mode 100644 tests/api-resources/agents/auth/auth.test.ts delete mode 100644 tests/api-resources/agents/auth/invocations.test.ts diff --git a/.stats.yml b/.stats.yml index 15c374f0..207d8996 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 108 +configured_endpoints: 100 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-13e82ae9e725e2c3ca19da7248a7a9c8696a0dfe088654cf26aea07c76d6567a.yml openapi_spec_hash: 6d4151a6066a8474bc56923299aec18a -config_hash: 3b1fbbb6bda0dac7e8b42e155cd7da56 +config_hash: 82f0a04081a3ab7111d3a9c68cd3ff2b diff --git a/api.md b/api.md index 8037ef03..9c757f59 100644 --- a/api.md +++ b/api.md @@ -278,40 +278,6 @@ Methods: - client.browserPools.flush(idOrName) -> void - client.browserPools.release(idOrName, { ...params }) -> void -# Agents - -## Auth - -Types: - -- AgentAuthInvocationResponse -- AgentAuthSubmitResponse -- AuthAgent -- AuthAgentCreateRequest -- AuthAgentInvocationCreateRequest -- AuthAgentInvocationCreateResponse -- DiscoveredField - -Methods: - -- client.agents.auth.create({ ...params }) -> AuthAgent -- client.agents.auth.retrieve(id) -> AuthAgent -- client.agents.auth.list({ ...params }) -> AuthAgentsOffsetPagination -- client.agents.auth.delete(id) -> void - -### Invocations - -Types: - -- InvocationExchangeResponse - -Methods: - -- client.agents.auth.invocations.create({ ...params }) -> AuthAgentInvocationCreateResponse -- client.agents.auth.invocations.retrieve(invocationID) -> AgentAuthInvocationResponse -- client.agents.auth.invocations.exchange(invocationID, { ...params }) -> InvocationExchangeResponse -- client.agents.auth.invocations.submit(invocationID, { ...params }) -> AgentAuthSubmitResponse - # Credentials Types: diff --git a/src/client.ts b/src/client.ts index d191bb5d..765bc7a4 100644 --- a/src/client.ts +++ b/src/client.ts @@ -96,7 +96,6 @@ import { ProxyListResponse, ProxyRetrieveResponse, } from './resources/proxies'; -import { Agents } from './resources/agents/agents'; import { Auth } from './resources/auth/auth'; import { BrowserCreateParams, @@ -875,7 +874,6 @@ export class Kernel { proxies: API.Proxies = new API.Proxies(this); extensions: API.Extensions = new API.Extensions(this); browserPools: API.BrowserPools = new API.BrowserPools(this); - agents: API.Agents = new API.Agents(this); credentials: API.Credentials = new API.Credentials(this); credentialProviders: API.CredentialProviders = new API.CredentialProviders(this); } @@ -889,7 +887,6 @@ Kernel.Auth = Auth; Kernel.Proxies = Proxies; Kernel.Extensions = Extensions; Kernel.BrowserPools = BrowserPools; -Kernel.Agents = Agents; Kernel.Credentials = Credentials; Kernel.CredentialProviders = CredentialProviders; @@ -992,8 +989,6 @@ export declare namespace Kernel { type BrowserPoolReleaseParams as BrowserPoolReleaseParams, }; - export { Agents as Agents }; - export { Credentials as Credentials, type CreateCredentialRequest as CreateCredentialRequest, diff --git a/src/resources/agents.ts b/src/resources/agents.ts deleted file mode 100644 index 0c43db07..00000000 --- a/src/resources/agents.ts +++ /dev/null @@ -1,3 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -export * from './agents/index'; diff --git a/src/resources/agents/agents.ts b/src/resources/agents/agents.ts deleted file mode 100644 index dd0955e8..00000000 --- a/src/resources/agents/agents.ts +++ /dev/null @@ -1,39 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { APIResource } from '../../core/resource'; -import * as AuthAPI from './auth/auth'; -import { - AgentAuthInvocationResponse, - AgentAuthSubmitResponse, - Auth, - AuthAgent, - AuthAgentCreateRequest, - AuthAgentInvocationCreateRequest, - AuthAgentInvocationCreateResponse, - AuthAgentsOffsetPagination, - AuthCreateParams, - AuthListParams, - DiscoveredField, -} from './auth/auth'; - -export class Agents extends APIResource { - auth: AuthAPI.Auth = new AuthAPI.Auth(this._client); -} - -Agents.Auth = Auth; - -export declare namespace Agents { - export { - Auth as Auth, - type AgentAuthInvocationResponse as AgentAuthInvocationResponse, - type AgentAuthSubmitResponse as AgentAuthSubmitResponse, - type AuthAgent as AuthAgent, - type AuthAgentCreateRequest as AuthAgentCreateRequest, - type AuthAgentInvocationCreateRequest as AuthAgentInvocationCreateRequest, - type AuthAgentInvocationCreateResponse as AuthAgentInvocationCreateResponse, - type DiscoveredField as DiscoveredField, - type AuthAgentsOffsetPagination as AuthAgentsOffsetPagination, - type AuthCreateParams as AuthCreateParams, - type AuthListParams as AuthListParams, - }; -} diff --git a/src/resources/agents/auth.ts b/src/resources/agents/auth.ts deleted file mode 100644 index b64faa13..00000000 --- a/src/resources/agents/auth.ts +++ /dev/null @@ -1,3 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -export * from './auth/index'; diff --git a/src/resources/agents/auth/auth.ts b/src/resources/agents/auth/auth.ts deleted file mode 100644 index 813aa170..00000000 --- a/src/resources/agents/auth/auth.ts +++ /dev/null @@ -1,599 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { APIResource } from '../../../core/resource'; -import * as InvocationsAPI from './invocations'; -import { - InvocationCreateParams, - InvocationExchangeParams, - InvocationExchangeResponse, - InvocationSubmitParams, - Invocations, -} from './invocations'; -import { APIPromise } from '../../../core/api-promise'; -import { OffsetPagination, type OffsetPaginationParams, PagePromise } from '../../../core/pagination'; -import { buildHeaders } from '../../../internal/headers'; -import { RequestOptions } from '../../../internal/request-options'; -import { path } from '../../../internal/utils/path'; - -export class Auth extends APIResource { - invocations: InvocationsAPI.Invocations = new InvocationsAPI.Invocations(this._client); - - /** - * **Deprecated: Use POST /auth/connections instead.** Creates a new auth agent for - * the specified domain and profile combination, or returns an existing one if it - * already exists. This is idempotent - calling with the same domain and profile - * will return the same agent. Does NOT start an invocation - use POST - * /agents/auth/invocations to start an auth flow. - * - * @deprecated - */ - create(body: AuthCreateParams, options?: RequestOptions): APIPromise { - return this._client.post('/agents/auth', { body, ...options }); - } - - /** - * **Deprecated: Use GET /auth/connections/{id} instead.** Retrieve an auth agent - * by its ID. Returns the current authentication status of the managed profile. - * - * @deprecated - */ - retrieve(id: string, options?: RequestOptions): APIPromise { - return this._client.get(path`/agents/auth/${id}`, options); - } - - /** - * **Deprecated: Use GET /auth/connections instead.** List auth agents with - * optional filters for profile_name and domain. - * - * @deprecated - */ - list( - query: AuthListParams | null | undefined = {}, - options?: RequestOptions, - ): PagePromise { - return this._client.getAPIList('/agents/auth', OffsetPagination, { query, ...options }); - } - - /** - * **Deprecated: Use DELETE /auth/connections/{id} instead.** Deletes an auth agent - * and terminates its workflow. This will: - * - * - Soft delete the auth agent record - * - Gracefully terminate the agent's Temporal workflow - * - Cancel any in-progress invocations - * - * @deprecated - */ - delete(id: string, options?: RequestOptions): APIPromise { - return this._client.delete(path`/agents/auth/${id}`, { - ...options, - headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), - }); - } -} - -export type AuthAgentsOffsetPagination = OffsetPagination; - -/** - * Response from get invocation endpoint - */ -export interface AgentAuthInvocationResponse { - /** - * App name (org name at time of invocation creation) - */ - app_name: string; - - /** - * Domain for authentication - */ - domain: string; - - /** - * When the handoff code expires - */ - expires_at: string; - - /** - * Invocation status - */ - status: 'IN_PROGRESS' | 'SUCCESS' | 'EXPIRED' | 'CANCELED' | 'FAILED'; - - /** - * Current step in the invocation workflow - */ - step: - | 'initialized' - | 'discovering' - | 'awaiting_input' - | 'awaiting_external_action' - | 'submitting' - | 'completed' - | 'expired'; - - /** - * The session type: - * - * - login: User-initiated authentication - * - reauth: System-triggered re-authentication (via health check) - */ - type: 'login' | 'reauth'; - - /** - * Error message explaining why the invocation failed (present when status=FAILED) - */ - error_message?: string | null; - - /** - * Instructions for user when external action is required (present when - * step=awaiting_external_action) - */ - external_action_message?: string | null; - - /** - * Browser live view URL for debugging the invocation - */ - live_view_url?: string | null; - - /** - * MFA method options to choose from (present when step=awaiting_input and MFA - * selection is required) - */ - mfa_options?: Array | null; - - /** - * Fields currently awaiting input (present when step=awaiting_input) - */ - pending_fields?: Array | null; - - /** - * SSO buttons available on the page (present when step=awaiting_input) - */ - pending_sso_buttons?: Array | null; - - /** - * SSO provider being used for authentication (e.g., google, github, microsoft) - */ - sso_provider?: string | null; - - /** - * Names of fields that have been submitted (present when step=submitting or later) - */ - submitted_fields?: Array | null; -} - -export namespace AgentAuthInvocationResponse { - /** - * An MFA method option for verification - */ - export interface MfaOption { - /** - * The visible option text - */ - label: string; - - /** - * The MFA delivery method type (includes password for auth method selection pages) - */ - type: 'sms' | 'call' | 'email' | 'totp' | 'push' | 'password'; - - /** - * Additional instructions from the site - */ - description?: string | null; - - /** - * The masked destination (phone/email) if shown - */ - target?: string | null; - } - - /** - * An SSO button for signing in with an external identity provider - */ - export interface PendingSSOButton { - /** - * Visible button text - */ - label: string; - - /** - * Identity provider name - */ - provider: string; - - /** - * XPath selector for the button - */ - selector: string; - } -} - -/** - * Response from submit endpoint - returns immediately after submission is accepted - */ -export interface AgentAuthSubmitResponse { - /** - * Whether the submission was accepted for processing - */ - accepted: boolean; -} - -/** - * An auth agent that manages authentication for a specific domain and profile - * combination - */ -export interface AuthAgent { - /** - * Unique identifier for the auth agent - */ - id: string; - - /** - * Target domain for authentication - */ - domain: string; - - /** - * Name of the profile associated with this auth agent - */ - profile_name: string; - - /** - * Current authentication status of the managed profile - */ - status: 'AUTHENTICATED' | 'NEEDS_AUTH'; - - /** - * Additional domains that are valid for this auth agent's authentication flow - * (besides the primary domain). Useful when login pages redirect to different - * domains. - * - * The following SSO/OAuth provider domains are automatically allowed by default - * and do not need to be specified: - * - * - Google: accounts.google.com - * - Microsoft/Azure AD: login.microsoftonline.com, login.live.com - * - Okta: _.okta.com, _.oktapreview.com - * - Auth0: _.auth0.com, _.us.auth0.com, _.eu.auth0.com, _.au.auth0.com - * - Apple: appleid.apple.com - * - GitHub: github.com - * - Facebook/Meta: www.facebook.com - * - LinkedIn: www.linkedin.com - * - Amazon Cognito: \*.amazoncognito.com - * - OneLogin: \*.onelogin.com - * - Ping Identity: _.pingone.com, _.pingidentity.com - */ - allowed_domains?: Array; - - /** - * Whether automatic re-authentication is possible (has credential_id, selectors, - * and login_url) - */ - can_reauth?: boolean; - - /** - * Reason why automatic re-authentication is or is not possible - */ - can_reauth_reason?: string; - - /** - * Reference to credentials for the auth connection. Use one of: - * - * - { name } for Kernel credentials - * - { provider, path } for external provider item - * - { provider, auto: true } for external provider domain lookup - */ - credential?: AuthAgent.Credential; - - /** - * ID of the linked Kernel credential for automatic re-authentication (deprecated, - * use credential) - */ - credential_id?: string; - - /** - * Whether this auth agent has stored selectors for deterministic re-authentication - */ - has_selectors?: boolean; - - /** - * When the last authentication check was performed - */ - last_auth_check_at?: string; - - /** - * URL where the browser landed after successful login. Query parameters and - * fragments are stripped for privacy. - */ - post_login_url?: string; -} - -export namespace AuthAgent { - /** - * Reference to credentials for the auth connection. Use one of: - * - * - { name } for Kernel credentials - * - { provider, path } for external provider item - * - { provider, auto: true } for external provider domain lookup - */ - export interface Credential { - /** - * If true, lookup by domain from the specified provider - */ - auto?: boolean; - - /** - * Kernel credential name - */ - name?: string; - - /** - * Provider-specific path (e.g., "VaultName/ItemName" for 1Password) - */ - path?: string; - - /** - * External provider name (e.g., "my-1p") - */ - provider?: string; - } -} - -/** - * Request to create or find an auth agent - */ -export interface AuthAgentCreateRequest { - /** - * Domain for authentication - */ - domain: string; - - /** - * Name of the profile to use for this auth agent - */ - profile_name: string; - - /** - * Additional domains that are valid for this auth agent's authentication flow - * (besides the primary domain). Useful when login pages redirect to different - * domains. - * - * The following SSO/OAuth provider domains are automatically allowed by default - * and do not need to be specified: - * - * - Google: accounts.google.com - * - Microsoft/Azure AD: login.microsoftonline.com, login.live.com - * - Okta: _.okta.com, _.oktapreview.com - * - Auth0: _.auth0.com, _.us.auth0.com, _.eu.auth0.com, _.au.auth0.com - * - Apple: appleid.apple.com - * - GitHub: github.com - * - Facebook/Meta: www.facebook.com - * - LinkedIn: www.linkedin.com - * - Amazon Cognito: \*.amazoncognito.com - * - OneLogin: \*.onelogin.com - * - Ping Identity: _.pingone.com, _.pingidentity.com - */ - allowed_domains?: Array; - - /** - * Optional name of an existing credential to use for this auth agent. If provided, - * the credential will be linked to the agent and its values will be used to - * auto-fill the login form on invocation. - */ - credential_name?: string; - - /** - * Optional login page URL. If provided, will be stored on the agent and used to - * skip discovery in future invocations. - */ - login_url?: string; - - /** - * Optional proxy configuration - */ - proxy?: AuthAgentCreateRequest.Proxy; -} - -export namespace AuthAgentCreateRequest { - /** - * Optional proxy configuration - */ - export interface Proxy { - /** - * ID of the proxy to use - */ - proxy_id?: string; - } -} - -/** - * Request to create an invocation for an existing auth agent - */ -export interface AuthAgentInvocationCreateRequest { - /** - * ID of the auth agent to create an invocation for - */ - auth_agent_id: string; - - /** - * If provided, saves the submitted credentials under this name upon successful - * login. The credential will be linked to the auth agent for automatic - * re-authentication. - */ - save_credential_as?: string; -} - -/** - * Response from creating an invocation. Always returns an invocation_id. - */ -export interface AuthAgentInvocationCreateResponse { - /** - * When the handoff code expires. - */ - expires_at: string; - - /** - * One-time code for handoff. - */ - handoff_code: string; - - /** - * URL to redirect user to. - */ - hosted_url: string; - - /** - * Unique identifier for the invocation. - */ - invocation_id: string; - - /** - * The session type: - * - * - login: User-initiated authentication - * - reauth: System-triggered re-authentication (via health check) - */ - type: 'login' | 'reauth'; -} - -/** - * A discovered form field - */ -export interface DiscoveredField { - /** - * Field label - */ - label: string; - - /** - * Field name - */ - name: string; - - /** - * CSS selector for the field - */ - selector: string; - - /** - * Field type - */ - type: 'text' | 'email' | 'password' | 'tel' | 'number' | 'url' | 'code' | 'totp'; - - /** - * If this field is associated with an MFA option, the type of that option (e.g., - * password field linked to "Enter password" option) - */ - linked_mfa_type?: 'sms' | 'call' | 'email' | 'totp' | 'push' | 'password' | null; - - /** - * Field placeholder - */ - placeholder?: string; - - /** - * Whether field is required - */ - required?: boolean; -} - -export interface AuthCreateParams { - /** - * Domain for authentication - */ - domain: string; - - /** - * Name of the profile to use for this auth agent - */ - profile_name: string; - - /** - * Additional domains that are valid for this auth agent's authentication flow - * (besides the primary domain). Useful when login pages redirect to different - * domains. - * - * The following SSO/OAuth provider domains are automatically allowed by default - * and do not need to be specified: - * - * - Google: accounts.google.com - * - Microsoft/Azure AD: login.microsoftonline.com, login.live.com - * - Okta: _.okta.com, _.oktapreview.com - * - Auth0: _.auth0.com, _.us.auth0.com, _.eu.auth0.com, _.au.auth0.com - * - Apple: appleid.apple.com - * - GitHub: github.com - * - Facebook/Meta: www.facebook.com - * - LinkedIn: www.linkedin.com - * - Amazon Cognito: \*.amazoncognito.com - * - OneLogin: \*.onelogin.com - * - Ping Identity: _.pingone.com, _.pingidentity.com - */ - allowed_domains?: Array; - - /** - * Optional name of an existing credential to use for this auth agent. If provided, - * the credential will be linked to the agent and its values will be used to - * auto-fill the login form on invocation. - */ - credential_name?: string; - - /** - * Optional login page URL. If provided, will be stored on the agent and used to - * skip discovery in future invocations. - */ - login_url?: string; - - /** - * Optional proxy configuration - */ - proxy?: AuthCreateParams.Proxy; -} - -export namespace AuthCreateParams { - /** - * Optional proxy configuration - */ - export interface Proxy { - /** - * ID of the proxy to use - */ - proxy_id?: string; - } -} - -export interface AuthListParams extends OffsetPaginationParams { - /** - * Filter by domain - */ - domain?: string; - - /** - * Filter by profile name - */ - profile_name?: string; -} - -Auth.Invocations = Invocations; - -export declare namespace Auth { - export { - type AgentAuthInvocationResponse as AgentAuthInvocationResponse, - type AgentAuthSubmitResponse as AgentAuthSubmitResponse, - type AuthAgent as AuthAgent, - type AuthAgentCreateRequest as AuthAgentCreateRequest, - type AuthAgentInvocationCreateRequest as AuthAgentInvocationCreateRequest, - type AuthAgentInvocationCreateResponse as AuthAgentInvocationCreateResponse, - type DiscoveredField as DiscoveredField, - type AuthAgentsOffsetPagination as AuthAgentsOffsetPagination, - type AuthCreateParams as AuthCreateParams, - type AuthListParams as AuthListParams, - }; - - export { - Invocations as Invocations, - type InvocationExchangeResponse as InvocationExchangeResponse, - type InvocationCreateParams as InvocationCreateParams, - type InvocationExchangeParams as InvocationExchangeParams, - type InvocationSubmitParams as InvocationSubmitParams, - }; -} diff --git a/src/resources/agents/auth/index.ts b/src/resources/agents/auth/index.ts deleted file mode 100644 index 490ad25c..00000000 --- a/src/resources/agents/auth/index.ts +++ /dev/null @@ -1,22 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -export { - Auth, - type AgentAuthInvocationResponse, - type AgentAuthSubmitResponse, - type AuthAgent, - type AuthAgentCreateRequest, - type AuthAgentInvocationCreateRequest, - type AuthAgentInvocationCreateResponse, - type DiscoveredField, - type AuthCreateParams, - type AuthListParams, - type AuthAgentsOffsetPagination, -} from './auth'; -export { - Invocations, - type InvocationExchangeResponse, - type InvocationCreateParams, - type InvocationExchangeParams, - type InvocationSubmitParams, -} from './invocations'; diff --git a/src/resources/agents/auth/invocations.ts b/src/resources/agents/auth/invocations.ts deleted file mode 100644 index b41ea8e3..00000000 --- a/src/resources/agents/auth/invocations.ts +++ /dev/null @@ -1,137 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { APIResource } from '../../../core/resource'; -import * as AuthAPI from './auth'; -import { APIPromise } from '../../../core/api-promise'; -import { RequestOptions } from '../../../internal/request-options'; -import { path } from '../../../internal/utils/path'; - -export class Invocations extends APIResource { - /** - * **Deprecated: Use POST /auth/connections/{id}/login instead.** Creates a new - * authentication invocation for the specified auth agent. This starts the auth - * flow and returns a hosted URL for the user to complete authentication. - * - * @deprecated - */ - create( - body: InvocationCreateParams, - options?: RequestOptions, - ): APIPromise { - return this._client.post('/agents/auth/invocations', { body, ...options }); - } - - /** - * **Deprecated: Use GET /auth/connections/{id} instead.** Returns invocation - * details including status, app_name, and domain. Supports both API key and JWT - * (from exchange endpoint) authentication. - * - * @deprecated - */ - retrieve(invocationID: string, options?: RequestOptions): APIPromise { - return this._client.get(path`/agents/auth/invocations/${invocationID}`, options); - } - - /** - * **Deprecated: Use POST /auth/connections/{id}/exchange instead.** Validates the - * handoff code and returns a JWT token for subsequent requests. No authentication - * required (the handoff code serves as the credential). - * - * @deprecated - */ - exchange( - invocationID: string, - body: InvocationExchangeParams, - options?: RequestOptions, - ): APIPromise { - return this._client.post(path`/agents/auth/invocations/${invocationID}/exchange`, { body, ...options }); - } - - /** - * **Deprecated: Use POST /auth/connections/{id}/submit instead.** Submits field - * values for the discovered login form. Returns immediately after submission is - * accepted. Poll the invocation endpoint to track progress and get results. - * - * @deprecated - */ - submit( - invocationID: string, - body: InvocationSubmitParams, - options?: RequestOptions, - ): APIPromise { - return this._client.post(path`/agents/auth/invocations/${invocationID}/submit`, { body, ...options }); - } -} - -/** - * Response from exchange endpoint - */ -export interface InvocationExchangeResponse { - /** - * Invocation ID - */ - invocation_id: string; - - /** - * JWT token with invocation_id claim (30 minute TTL) - */ - jwt: string; -} - -export interface InvocationCreateParams { - /** - * ID of the auth agent to create an invocation for - */ - auth_agent_id: string; - - /** - * If provided, saves the submitted credentials under this name upon successful - * login. The credential will be linked to the auth agent for automatic - * re-authentication. - */ - save_credential_as?: string; -} - -export interface InvocationExchangeParams { - /** - * Handoff code from start endpoint - */ - code: string; -} - -export type InvocationSubmitParams = - | InvocationSubmitParams.Variant0 - | InvocationSubmitParams.Variant1 - | InvocationSubmitParams.Variant2; - -export declare namespace InvocationSubmitParams { - export interface Variant0 { - /** - * Values for the discovered login fields - */ - field_values: { [key: string]: string }; - } - - export interface Variant1 { - /** - * Selector of SSO button to click - */ - sso_button: string; - } - - export interface Variant2 { - /** - * The MFA delivery method type (includes password for auth method selection pages) - */ - selected_mfa_type: 'sms' | 'call' | 'email' | 'totp' | 'push' | 'password'; - } -} - -export declare namespace Invocations { - export { - type InvocationExchangeResponse as InvocationExchangeResponse, - type InvocationCreateParams as InvocationCreateParams, - type InvocationExchangeParams as InvocationExchangeParams, - type InvocationSubmitParams as InvocationSubmitParams, - }; -} diff --git a/src/resources/agents/index.ts b/src/resources/agents/index.ts deleted file mode 100644 index 65bd5a46..00000000 --- a/src/resources/agents/index.ts +++ /dev/null @@ -1,16 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -export { Agents } from './agents'; -export { - Auth, - type AgentAuthInvocationResponse, - type AgentAuthSubmitResponse, - type AuthAgent, - type AuthAgentCreateRequest, - type AuthAgentInvocationCreateRequest, - type AuthAgentInvocationCreateResponse, - type DiscoveredField, - type AuthCreateParams, - type AuthListParams, - type AuthAgentsOffsetPagination, -} from './auth/index'; diff --git a/src/resources/auth/connections.ts b/src/resources/auth/connections.ts index ff577115..bb0190a5 100644 --- a/src/resources/auth/connections.ts +++ b/src/resources/auth/connections.ts @@ -2,7 +2,6 @@ import { APIResource } from '../../core/resource'; import * as Shared from '../shared'; -import * as AuthAPI from '../agents/auth/auth'; import { APIPromise } from '../../core/api-promise'; import { OffsetPagination, type OffsetPaginationParams, PagePromise } from '../../core/pagination'; import { Stream } from '../../core/streaming'; @@ -258,7 +257,7 @@ export interface ManagedAuth { /** * Fields awaiting input (present when flow_step=awaiting_input) */ - discovered_fields?: Array | null; + discovered_fields?: Array | null; /** * Error message (present when flow_status=failed) @@ -378,6 +377,47 @@ export namespace ManagedAuth { provider?: string; } + /** + * A discovered form field + */ + export interface DiscoveredField { + /** + * Field label + */ + label: string; + + /** + * Field name + */ + name: string; + + /** + * CSS selector for the field + */ + selector: string; + + /** + * Field type + */ + type: 'text' | 'email' | 'password' | 'tel' | 'number' | 'url' | 'code' | 'totp'; + + /** + * If this field is associated with an MFA option, the type of that option (e.g., + * password field linked to "Enter password" option) + */ + linked_mfa_type?: 'sms' | 'call' | 'email' | 'totp' | 'push' | 'password' | null; + + /** + * Field placeholder + */ + placeholder?: string; + + /** + * Whether field is required + */ + required?: boolean; + } + /** * An MFA method option for verification */ @@ -594,7 +634,7 @@ export namespace ConnectionFollowResponse { /** * Fields awaiting input (present when flow_step=AWAITING_INPUT). */ - discovered_fields?: Array; + discovered_fields?: Array; /** * Error message (present when flow_status=FAILED). @@ -646,6 +686,47 @@ export namespace ConnectionFollowResponse { } export namespace ManagedAuthStateEvent { + /** + * A discovered form field + */ + export interface DiscoveredField { + /** + * Field label + */ + label: string; + + /** + * Field name + */ + name: string; + + /** + * CSS selector for the field + */ + selector: string; + + /** + * Field type + */ + type: 'text' | 'email' | 'password' | 'tel' | 'number' | 'url' | 'code' | 'totp'; + + /** + * If this field is associated with an MFA option, the type of that option (e.g., + * password field linked to "Enter password" option) + */ + linked_mfa_type?: 'sms' | 'call' | 'email' | 'totp' | 'push' | 'password' | null; + + /** + * Field placeholder + */ + placeholder?: string; + + /** + * Whether field is required + */ + required?: boolean; + } + /** * An MFA method option for verification */ diff --git a/src/resources/index.ts b/src/resources/index.ts index d29baae8..da81ceca 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -1,7 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. export * from './shared'; -export { Agents } from './agents/agents'; export { Apps, type AppListResponse, diff --git a/tests/api-resources/agents/auth/auth.test.ts b/tests/api-resources/agents/auth/auth.test.ts deleted file mode 100644 index 1f8a9237..00000000 --- a/tests/api-resources/agents/auth/auth.test.ts +++ /dev/null @@ -1,86 +0,0 @@ -// 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 auth', () => { - // Prism tests are disabled - test.skip('create: only required params', async () => { - const responsePromise = client.agents.auth.create({ domain: 'netflix.com', profile_name: 'user-123' }); - 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); - }); - - // Prism tests are disabled - test.skip('create: required and optional params', async () => { - const response = await client.agents.auth.create({ - domain: 'netflix.com', - profile_name: 'user-123', - allowed_domains: ['login.netflix.com', 'auth.netflix.com'], - credential_name: 'my-netflix-login', - login_url: 'https://netflix.com/login', - proxy: { proxy_id: 'proxy_id' }, - }); - }); - - // Prism tests are disabled - test.skip('retrieve', async () => { - const responsePromise = client.agents.auth.retrieve('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); - }); - - // Prism tests are disabled - test.skip('list', async () => { - const responsePromise = client.agents.auth.list(); - 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); - }); - - // Prism tests are disabled - test.skip('list: 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.agents.auth.list( - { - domain: 'domain', - limit: 100, - offset: 0, - profile_name: 'profile_name', - }, - { path: '/_stainless_unknown_path' }, - ), - ).rejects.toThrow(Kernel.NotFoundError); - }); - - // Prism tests are disabled - test.skip('delete', async () => { - const responsePromise = client.agents.auth.delete('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); - }); -}); diff --git a/tests/api-resources/agents/auth/invocations.test.ts b/tests/api-resources/agents/auth/invocations.test.ts deleted file mode 100644 index b30496c8..00000000 --- a/tests/api-resources/agents/auth/invocations.test.ts +++ /dev/null @@ -1,80 +0,0 @@ -// 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 invocations', () => { - // Prism tests are disabled - test.skip('create: only required params', async () => { - const responsePromise = client.agents.auth.invocations.create({ auth_agent_id: 'abc123xyz' }); - 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); - }); - - // Prism tests are disabled - test.skip('create: required and optional params', async () => { - const response = await client.agents.auth.invocations.create({ - auth_agent_id: 'abc123xyz', - save_credential_as: 'my-netflix-login', - }); - }); - - // Prism tests are disabled - test.skip('retrieve', async () => { - const responsePromise = client.agents.auth.invocations.retrieve('invocation_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); - }); - - // Prism tests are disabled - test.skip('exchange: only required params', async () => { - const responsePromise = client.agents.auth.invocations.exchange('invocation_id', { code: 'abc123xyz' }); - 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); - }); - - // Prism tests are disabled - test.skip('exchange: required and optional params', async () => { - const response = await client.agents.auth.invocations.exchange('invocation_id', { code: 'abc123xyz' }); - }); - - // Prism tests are disabled - test.skip('submit: only required params', async () => { - const responsePromise = client.agents.auth.invocations.submit('invocation_id', { - field_values: { email: 'user@example.com', password: '********' }, - }); - 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); - }); - - // Prism tests are disabled - test.skip('submit: required and optional params', async () => { - const response = await client.agents.auth.invocations.submit('invocation_id', { - field_values: { email: 'user@example.com', password: '********' }, - }); - }); -}); From ceaf78de49d57644f87a81333e41ba2988324fbc Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 10 Feb 2026 22:55:58 +0000 Subject: [PATCH 285/551] refactor(auth): simplify proxy configuration in OpenAPI schema --- .stats.yml | 4 +- src/resources/auth/connections.ts | 78 ++++++++++++++++++-- tests/api-resources/auth/connections.test.ts | 7 +- 3 files changed, 77 insertions(+), 12 deletions(-) diff --git a/.stats.yml b/.stats.yml index 207d8996..c359ff6b 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 100 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-13e82ae9e725e2c3ca19da7248a7a9c8696a0dfe088654cf26aea07c76d6567a.yml -openapi_spec_hash: 6d4151a6066a8474bc56923299aec18a +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-eaf23b9711c16c82563be76641c9c89988288307278dcd630a36f4f186f85afa.yml +openapi_spec_hash: 369570222f4f725e1de11285422837cc config_hash: 82f0a04081a3ab7111d3a9c68cd3ff2b diff --git a/src/resources/auth/connections.ts b/src/resources/auth/connections.ts index bb0190a5..fa8324d1 100644 --- a/src/resources/auth/connections.ts +++ b/src/resources/auth/connections.ts @@ -146,12 +146,36 @@ export type ManagedAuthsOffsetPagination = OffsetPagination; * Request to start a login flow */ export interface LoginRequest { + /** + * Proxy selection. Provide either id or name. The proxy must belong to the + * caller's org. + */ + proxy?: LoginRequest.Proxy; + /** * If provided, saves credentials under this name upon successful login */ save_credential_as?: string; } +export namespace LoginRequest { + /** + * Proxy selection. Provide either id or name. The proxy must belong to the + * caller's org. + */ + export interface Proxy { + /** + * Proxy ID + */ + id?: string; + + /** + * Proxy name + */ + name?: string; + } +} + /** * Response from starting a login flow */ @@ -522,7 +546,8 @@ export interface ManagedAuthCreateRequest { login_url?: string; /** - * Optional proxy configuration + * Proxy selection. Provide either id or name. The proxy must belong to the + * caller's org. */ proxy?: ManagedAuthCreateRequest.Proxy; } @@ -558,13 +583,19 @@ export namespace ManagedAuthCreateRequest { } /** - * Optional proxy configuration + * Proxy selection. Provide either id or name. The proxy must belong to the + * caller's org. */ export interface Proxy { /** - * ID of the proxy to use + * Proxy ID */ - proxy_id?: string; + id?: string; + + /** + * Proxy name + */ + name?: string; } } @@ -829,7 +860,8 @@ export interface ConnectionCreateParams { login_url?: string; /** - * Optional proxy configuration + * Proxy selection. Provide either id or name. The proxy must belong to the + * caller's org. */ proxy?: ConnectionCreateParams.Proxy; } @@ -865,13 +897,19 @@ export namespace ConnectionCreateParams { } /** - * Optional proxy configuration + * Proxy selection. Provide either id or name. The proxy must belong to the + * caller's org. */ export interface Proxy { /** - * ID of the proxy to use + * Proxy ID */ - proxy_id?: string; + id?: string; + + /** + * Proxy name + */ + name?: string; } } @@ -888,12 +926,36 @@ export interface ConnectionListParams extends OffsetPaginationParams { } export interface ConnectionLoginParams { + /** + * Proxy selection. Provide either id or name. The proxy must belong to the + * caller's org. + */ + proxy?: ConnectionLoginParams.Proxy; + /** * If provided, saves credentials under this name upon successful login */ save_credential_as?: string; } +export namespace ConnectionLoginParams { + /** + * Proxy selection. Provide either id or name. The proxy must belong to the + * caller's org. + */ + export interface Proxy { + /** + * Proxy ID + */ + id?: string; + + /** + * Proxy name + */ + name?: string; + } +} + export interface ConnectionSubmitParams { /** * Map of field name to value diff --git a/tests/api-resources/auth/connections.test.ts b/tests/api-resources/auth/connections.test.ts index 14c2abf0..20e5bd45 100644 --- a/tests/api-resources/auth/connections.test.ts +++ b/tests/api-resources/auth/connections.test.ts @@ -37,7 +37,7 @@ describe('resource connections', () => { }, health_check_interval: 3600, login_url: 'https://netflix.com/login', - proxy: { proxy_id: 'proxy_id' }, + proxy: { id: 'id', name: 'name' }, }); }); @@ -123,7 +123,10 @@ describe('resource connections', () => { await expect( client.auth.connections.login( 'id', - { save_credential_as: 'my-netflix-login' }, + { + proxy: { id: 'id', name: 'name' }, + save_credential_as: 'my-netflix-login', + }, { path: '/_stainless_unknown_path' }, ), ).rejects.toThrow(Kernel.NotFoundError); From f53474fc3881f4b09dda56299ab39ea01a820b8b Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 11 Feb 2026 04:42:42 +0000 Subject: [PATCH 286/551] feat(auth): plan-based min health check intervals --- .stats.yml | 4 ++-- src/resources/auth/connections.ts | 15 +++++++++------ 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/.stats.yml b/.stats.yml index c359ff6b..bc10806d 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 100 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-eaf23b9711c16c82563be76641c9c89988288307278dcd630a36f4f186f85afa.yml -openapi_spec_hash: 369570222f4f725e1de11285422837cc +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-92e99f12ad95d7c00047c3f8226cd705174c68c555b42f137f3051768fdf76ae.yml +openapi_spec_hash: 886e96ba621aecde2a3920825771f260 config_hash: 82f0a04081a3ab7111d3a9c68cd3ff2b diff --git a/src/resources/auth/connections.ts b/src/resources/auth/connections.ts index fa8324d1..c1fe6c63 100644 --- a/src/resources/auth/connections.ts +++ b/src/resources/auth/connections.ts @@ -323,8 +323,9 @@ export interface ManagedAuth { /** * Interval in seconds between automatic health checks. When set, the system * periodically verifies the authentication status and triggers re-authentication - * if needed. Must be between 300 (5 minutes) and 86400 (24 hours). Default is 3600 - * (1 hour). + * if needed. Maximum is 86400 (24 hours). Default is 3600 (1 hour). The minimum + * depends on your plan: Enterprise: 300 (5 minutes), Startup: 1200 (20 minutes), + * Hobbyist: 3600 (1 hour). */ health_check_interval?: number | null; @@ -535,8 +536,9 @@ export interface ManagedAuthCreateRequest { /** * Interval in seconds between automatic health checks. When set, the system * periodically verifies the authentication status and triggers re-authentication - * if needed. Must be between 300 (5 minutes) and 86400 (24 hours). Default is 3600 - * (1 hour). + * if needed. Maximum is 86400 (24 hours). Default is 3600 (1 hour). The minimum + * depends on your plan: Enterprise: 300 (5 minutes), Startup: 1200 (20 minutes), + * Hobbyist: 3600 (1 hour). */ health_check_interval?: number; @@ -849,8 +851,9 @@ export interface ConnectionCreateParams { /** * Interval in seconds between automatic health checks. When set, the system * periodically verifies the authentication status and triggers re-authentication - * if needed. Must be between 300 (5 minutes) and 86400 (24 hours). Default is 3600 - * (1 hour). + * if needed. Maximum is 86400 (24 hours). Default is 3600 (1 hour). The minimum + * depends on your plan: Enterprise: 300 (5 minutes), Startup: 1200 (20 minutes), + * Hobbyist: 3600 (1 hour). */ health_check_interval?: number; From dc6c171f76893f543c9399b283adc43e203d3676 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 11 Feb 2026 10:57:25 +0000 Subject: [PATCH 287/551] feat(auth): add save_credentials support --- .stats.yml | 6 +- api.md | 1 - src/resources/auth/auth.ts | 2 - src/resources/auth/connections.ts | 77 +++++++------------- src/resources/auth/index.ts | 1 - src/resources/credentials.ts | 5 ++ tests/api-resources/auth/connections.test.ts | 21 +----- 7 files changed, 40 insertions(+), 73 deletions(-) diff --git a/.stats.yml b/.stats.yml index bc10806d..00007d67 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 100 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-92e99f12ad95d7c00047c3f8226cd705174c68c555b42f137f3051768fdf76ae.yml -openapi_spec_hash: 886e96ba621aecde2a3920825771f260 -config_hash: 82f0a04081a3ab7111d3a9c68cd3ff2b +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-82fd51be8dc9b6ad425425f9eb747dd337df494a030d03d37f101e2236c85548.yml +openapi_spec_hash: ab396816e2b7da9938d42ec5a41cc8e1 +config_hash: 27c0ea01aeb797a1767af139851c5b66 diff --git a/api.md b/api.md index 9c757f59..4aaf7c31 100644 --- a/api.md +++ b/api.md @@ -209,7 +209,6 @@ Methods: Types: -- LoginRequest - LoginResponse - ManagedAuth - ManagedAuthCreateRequest diff --git a/src/resources/auth/auth.ts b/src/resources/auth/auth.ts index 2aaa817d..ee5d2fa4 100644 --- a/src/resources/auth/auth.ts +++ b/src/resources/auth/auth.ts @@ -9,7 +9,6 @@ import { ConnectionLoginParams, ConnectionSubmitParams, Connections, - LoginRequest, LoginResponse, ManagedAuth, ManagedAuthCreateRequest, @@ -27,7 +26,6 @@ Auth.Connections = Connections; export declare namespace Auth { export { Connections as Connections, - type LoginRequest as LoginRequest, type LoginResponse as LoginResponse, type ManagedAuth as ManagedAuth, type ManagedAuthCreateRequest as ManagedAuthCreateRequest, diff --git a/src/resources/auth/connections.ts b/src/resources/auth/connections.ts index c1fe6c63..e6fdcbaa 100644 --- a/src/resources/auth/connections.ts +++ b/src/resources/auth/connections.ts @@ -123,12 +123,7 @@ export class Connections extends APIResource { * @example * ```ts * const submitFieldsResponse = - * await client.auth.connections.submit('id', { - * fields: { - * email: 'user@example.com', - * password: 'secret', - * }, - * }); + * await client.auth.connections.submit('id'); * ``` */ submit( @@ -142,40 +137,6 @@ export class Connections extends APIResource { export type ManagedAuthsOffsetPagination = OffsetPagination; -/** - * Request to start a login flow - */ -export interface LoginRequest { - /** - * Proxy selection. Provide either id or name. The proxy must belong to the - * caller's org. - */ - proxy?: LoginRequest.Proxy; - - /** - * If provided, saves credentials under this name upon successful login - */ - save_credential_as?: string; -} - -export namespace LoginRequest { - /** - * Proxy selection. Provide either id or name. The proxy must belong to the - * caller's org. - */ - export interface Proxy { - /** - * Proxy ID - */ - id?: string; - - /** - * Proxy name - */ - name?: string; - } -} - /** * Response from starting a login flow */ @@ -232,6 +193,12 @@ export interface ManagedAuth { */ profile_name: string; + /** + * Whether credentials are saved after every successful login. One-time codes + * (TOTP, SMS, etc.) are not saved. + */ + save_credentials: boolean; + /** * Current authentication status of the managed profile */ @@ -360,6 +327,11 @@ export interface ManagedAuth { */ post_login_url?: string; + /** + * ID of the proxy associated with this connection, if any. + */ + proxy_id?: string; + /** * SSO provider being used (e.g., google, github, microsoft) */ @@ -552,6 +524,12 @@ export interface ManagedAuthCreateRequest { * caller's org. */ proxy?: ManagedAuthCreateRequest.Proxy; + + /** + * Whether to save credentials after every successful login. Defaults to true. + * One-time codes (TOTP, SMS, etc.) are not saved. + */ + save_credentials?: boolean; } export namespace ManagedAuthCreateRequest { @@ -602,13 +580,14 @@ export namespace ManagedAuthCreateRequest { } /** - * Request to submit field values for login + * Request to submit field values, click an SSO button, or select an MFA method. + * Provide exactly one of fields, sso_button_selector, or mfa_option_id. */ export interface SubmitFieldsRequest { /** * Map of field name to value */ - fields: { [key: string]: string }; + fields?: { [key: string]: string }; /** * Optional MFA option ID if user selected an MFA method @@ -867,6 +846,12 @@ export interface ConnectionCreateParams { * caller's org. */ proxy?: ConnectionCreateParams.Proxy; + + /** + * Whether to save credentials after every successful login. Defaults to true. + * One-time codes (TOTP, SMS, etc.) are not saved. + */ + save_credentials?: boolean; } export namespace ConnectionCreateParams { @@ -934,11 +919,6 @@ export interface ConnectionLoginParams { * caller's org. */ proxy?: ConnectionLoginParams.Proxy; - - /** - * If provided, saves credentials under this name upon successful login - */ - save_credential_as?: string; } export namespace ConnectionLoginParams { @@ -963,7 +943,7 @@ export interface ConnectionSubmitParams { /** * Map of field name to value */ - fields: { [key: string]: string }; + fields?: { [key: string]: string }; /** * Optional MFA option ID if user selected an MFA method @@ -978,7 +958,6 @@ export interface ConnectionSubmitParams { export declare namespace Connections { export { - type LoginRequest as LoginRequest, type LoginResponse as LoginResponse, type ManagedAuth as ManagedAuth, type ManagedAuthCreateRequest as ManagedAuthCreateRequest, diff --git a/src/resources/auth/index.ts b/src/resources/auth/index.ts index 4debc7e9..d71236bb 100644 --- a/src/resources/auth/index.ts +++ b/src/resources/auth/index.ts @@ -3,7 +3,6 @@ export { Auth } from './auth'; export { Connections, - type LoginRequest, type LoginResponse, type ManagedAuth, type ManagedAuthCreateRequest, diff --git a/src/resources/credentials.ts b/src/resources/credentials.ts index 2f384a7b..98b7df8a 100644 --- a/src/resources/credentials.ts +++ b/src/resources/credentials.ts @@ -177,6 +177,11 @@ export interface Credential { */ has_totp_secret?: boolean; + /** + * Whether this credential has stored values (email, password, etc.) + */ + has_values?: boolean; + /** * If set, indicates this credential should be used with the specified SSO provider * (e.g., google, github, microsoft). When the target site has a matching SSO diff --git a/tests/api-resources/auth/connections.test.ts b/tests/api-resources/auth/connections.test.ts index 20e5bd45..21dae74e 100644 --- a/tests/api-resources/auth/connections.test.ts +++ b/tests/api-resources/auth/connections.test.ts @@ -38,6 +38,7 @@ describe('resource connections', () => { health_check_interval: 3600, login_url: 'https://netflix.com/login', proxy: { id: 'id', name: 'name' }, + save_credentials: true, }); }); @@ -123,20 +124,15 @@ describe('resource connections', () => { await expect( client.auth.connections.login( 'id', - { - proxy: { id: 'id', name: 'name' }, - save_credential_as: 'my-netflix-login', - }, + { proxy: { id: 'id', name: 'name' } }, { path: '/_stainless_unknown_path' }, ), ).rejects.toThrow(Kernel.NotFoundError); }); // Prism tests are disabled - test.skip('submit: only required params', async () => { - const responsePromise = client.auth.connections.submit('id', { - fields: { email: 'user@example.com', password: 'secret' }, - }); + test.skip('submit', async () => { + const responsePromise = client.auth.connections.submit('id', {}); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -145,13 +141,4 @@ describe('resource connections', () => { expect(dataAndResponse.data).toBe(response); expect(dataAndResponse.response).toBe(rawResponse); }); - - // Prism tests are disabled - test.skip('submit: required and optional params', async () => { - const response = await client.auth.connections.submit('id', { - fields: { email: 'user@example.com', password: 'secret' }, - mfa_option_id: 'sms', - sso_button_selector: "xpath=//button[contains(text(), 'Continue with Google')]", - }); - }); }); From b067febb3327a8da3aa9001759d7456faea7493a Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 11 Feb 2026 11:07:41 +0000 Subject: [PATCH 288/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 47582228..53ecb865 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.32.0" + ".": "0.33.0" } diff --git a/package.json b/package.json index c05a3e85..a61f6b27 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.32.0", + "version": "0.33.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index b413d151..dc173dd4 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.32.0'; // x-release-please-version +export const VERSION = '0.33.0'; // x-release-please-version From aceb4502c1aa562994443956302cb9facc9dc95a Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 12 Feb 2026 03:18:29 +0000 Subject: [PATCH 289/551] chore(internal): avoid type checking errors with ts-reset --- src/client.ts | 2 +- src/core/streaming.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/client.ts b/src/client.ts index 765bc7a4..47edbb26 100644 --- a/src/client.ts +++ b/src/client.ts @@ -568,7 +568,7 @@ export class Kernel { loggerFor(this).info(`${responseInfo} - ${retryMessage}`); const errText = await response.text().catch((err: any) => castToError(err).message); - const errJSON = safeJSON(errText); + const errJSON = safeJSON(errText) as any; const errMessage = errJSON ? undefined : errText; loggerFor(this).debug( diff --git a/src/core/streaming.ts b/src/core/streaming.ts index a24bcfec..85b7259b 100644 --- a/src/core/streaming.ts +++ b/src/core/streaming.ts @@ -46,7 +46,7 @@ export class Stream implements AsyncIterable { try { for await (const sse of _iterSSEMessages(response, controller)) { try { - yield JSON.parse(sse.data); + yield JSON.parse(sse.data) as Item; } catch (e) { logger.error(`Could not parse message into JSON:`, sse.data); logger.error(`From chunk:`, sse.raw); @@ -102,7 +102,7 @@ export class Stream implements AsyncIterable { try { for await (const line of iterLines()) { if (done) continue; - if (line) yield JSON.parse(line); + if (line) yield JSON.parse(line) as Item; } done = true; } catch (e) { From 314600dffae4f93309f01d604f677cdf707131c4 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 12 Feb 2026 18:00:29 +0000 Subject: [PATCH 290/551] feat: Add error_code field to ManagedAuthSession and related components --- .stats.yml | 4 ++-- src/resources/auth/connections.ts | 10 ++++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 00007d67..f7218213 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 100 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-82fd51be8dc9b6ad425425f9eb747dd337df494a030d03d37f101e2236c85548.yml -openapi_spec_hash: ab396816e2b7da9938d42ec5a41cc8e1 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-b7d469021adcd1493f74dad38746ffa3817dcf86a0a12561a88eb554824e3ffb.yml +openapi_spec_hash: 4134c95bf3012dca38797ca56d62395b config_hash: 27c0ea01aeb797a1767af139851c5b66 diff --git a/src/resources/auth/connections.ts b/src/resources/auth/connections.ts index e6fdcbaa..6a418460 100644 --- a/src/resources/auth/connections.ts +++ b/src/resources/auth/connections.ts @@ -250,6 +250,11 @@ export interface ManagedAuth { */ discovered_fields?: Array | null; + /** + * Machine-readable error code (present when flow_status=failed) + */ + error_code?: string | null; + /** * Error message (present when flow_status=failed) */ @@ -648,6 +653,11 @@ export namespace ConnectionFollowResponse { */ discovered_fields?: Array; + /** + * Machine-readable error code (present when flow_status=FAILED). + */ + error_code?: string; + /** * Error message (present when flow_status=FAILED). */ From 5f2ce797a1cbfecaf3a9391527c51a8cfd4e41ca Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 13 Feb 2026 22:14:35 +0000 Subject: [PATCH 291/551] feat: Allow arbitrary viewport dimensions --- .stats.yml | 4 +- src/resources/browser-pools.ts | 56 ++++++++++++------------ src/resources/browsers/browsers.ts | 70 +++++++++++++++--------------- src/resources/invocations.ts | 14 +++--- src/resources/shared.ts | 14 +++--- 5 files changed, 79 insertions(+), 79 deletions(-) diff --git a/.stats.yml b/.stats.yml index f7218213..264b8c9d 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 100 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-b7d469021adcd1493f74dad38746ffa3817dcf86a0a12561a88eb554824e3ffb.yml -openapi_spec_hash: 4134c95bf3012dca38797ca56d62395b +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-47ee6a2b624baddb41a681feff758bf1893cd3d65edf3ab51219ebe4d942932b.yml +openapi_spec_hash: 76178c41ede593e76bfacb176057d2f0 config_hash: 27c0ea01aeb797a1767af139851c5b66 diff --git a/src/resources/browser-pools.ts b/src/resources/browser-pools.ts index ac2a128b..6192e483 100644 --- a/src/resources/browser-pools.ts +++ b/src/resources/browser-pools.ts @@ -240,13 +240,13 @@ export namespace BrowserPool { /** * Initial browser window size in pixels with optional refresh rate. If omitted, - * image defaults apply (1920x1080@25). Only specific viewport configurations are - * supported. The server will reject unsupported combinations. Supported - * resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25, 1440x900@25, - * 1280x800@60, 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will - * be automatically determined from the width and height if they match a supported - * configuration exactly. Note: Higher resolutions may affect the responsiveness of - * live view browser + * image defaults apply (1920x1080@25). Arbitrary viewport dimensions are accepted, + * but the following configurations are known-good and fully tested: 2560x1440@10, + * 1920x1080@25, 1920x1200@25, 1440x900@25, 1280x800@60, 1024x768@60, 1200x800@60. + * Viewports outside this list may exhibit unstable live view or recording + * behavior. If refresh_rate is not provided, it will be automatically determined + * based on the resolution (higher resolutions use lower refresh rates to keep + * bandwidth reasonable). */ viewport?: Shared.BrowserViewport; } @@ -319,13 +319,13 @@ export interface BrowserPoolAcquireResponse { /** * Initial browser window size in pixels with optional refresh rate. If omitted, - * image defaults apply (1920x1080@25). Only specific viewport configurations are - * supported. The server will reject unsupported combinations. Supported - * resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25, 1440x900@25, - * 1280x800@60, 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will - * be automatically determined from the width and height if they match a supported - * configuration exactly. Note: Higher resolutions may affect the responsiveness of - * live view browser + * image defaults apply (1920x1080@25). Arbitrary viewport dimensions are accepted, + * but the following configurations are known-good and fully tested: 2560x1440@10, + * 1920x1080@25, 1920x1200@25, 1440x900@25, 1280x800@60, 1024x768@60, 1200x800@60. + * Viewports outside this list may exhibit unstable live view or recording + * behavior. If refresh_rate is not provided, it will be automatically determined + * based on the resolution (higher resolutions use lower refresh rates to keep + * bandwidth reasonable). */ viewport?: Shared.BrowserViewport; } @@ -391,13 +391,13 @@ export interface BrowserPoolCreateParams { /** * Initial browser window size in pixels with optional refresh rate. If omitted, - * image defaults apply (1920x1080@25). Only specific viewport configurations are - * supported. The server will reject unsupported combinations. Supported - * resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25, 1440x900@25, - * 1280x800@60, 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will - * be automatically determined from the width and height if they match a supported - * configuration exactly. Note: Higher resolutions may affect the responsiveness of - * live view browser + * image defaults apply (1920x1080@25). Arbitrary viewport dimensions are accepted, + * but the following configurations are known-good and fully tested: 2560x1440@10, + * 1920x1080@25, 1920x1200@25, 1440x900@25, 1280x800@60, 1024x768@60, 1200x800@60. + * Viewports outside this list may exhibit unstable live view or recording + * behavior. If refresh_rate is not provided, it will be automatically determined + * based on the resolution (higher resolutions use lower refresh rates to keep + * bandwidth reasonable). */ viewport?: Shared.BrowserViewport; } @@ -469,13 +469,13 @@ export interface BrowserPoolUpdateParams { /** * Initial browser window size in pixels with optional refresh rate. If omitted, - * image defaults apply (1920x1080@25). Only specific viewport configurations are - * supported. The server will reject unsupported combinations. Supported - * resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25, 1440x900@25, - * 1280x800@60, 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will - * be automatically determined from the width and height if they match a supported - * configuration exactly. Note: Higher resolutions may affect the responsiveness of - * live view browser + * image defaults apply (1920x1080@25). Arbitrary viewport dimensions are accepted, + * but the following configurations are known-good and fully tested: 2560x1440@10, + * 1920x1080@25, 1920x1200@25, 1440x900@25, 1280x800@60, 1024x768@60, 1200x800@60. + * Viewports outside this list may exhibit unstable live view or recording + * behavior. If refresh_rate is not provided, it will be automatically determined + * based on the resolution (higher resolutions use lower refresh rates to keep + * bandwidth reasonable). */ viewport?: Shared.BrowserViewport; } diff --git a/src/resources/browsers/browsers.ts b/src/resources/browsers/browsers.ts index c335cac0..3a6f855b 100644 --- a/src/resources/browsers/browsers.ts +++ b/src/resources/browsers/browsers.ts @@ -315,13 +315,13 @@ export interface BrowserCreateResponse { /** * Initial browser window size in pixels with optional refresh rate. If omitted, - * image defaults apply (1920x1080@25). Only specific viewport configurations are - * supported. The server will reject unsupported combinations. Supported - * resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25, 1440x900@25, - * 1280x800@60, 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will - * be automatically determined from the width and height if they match a supported - * configuration exactly. Note: Higher resolutions may affect the responsiveness of - * live view browser + * image defaults apply (1920x1080@25). Arbitrary viewport dimensions are accepted, + * but the following configurations are known-good and fully tested: 2560x1440@10, + * 1920x1080@25, 1920x1200@25, 1440x900@25, 1280x800@60, 1024x768@60, 1200x800@60. + * Viewports outside this list may exhibit unstable live view or recording + * behavior. If refresh_rate is not provided, it will be automatically determined + * based on the resolution (higher resolutions use lower refresh rates to keep + * bandwidth reasonable). */ viewport?: Shared.BrowserViewport; } @@ -391,13 +391,13 @@ export interface BrowserRetrieveResponse { /** * Initial browser window size in pixels with optional refresh rate. If omitted, - * image defaults apply (1920x1080@25). Only specific viewport configurations are - * supported. The server will reject unsupported combinations. Supported - * resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25, 1440x900@25, - * 1280x800@60, 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will - * be automatically determined from the width and height if they match a supported - * configuration exactly. Note: Higher resolutions may affect the responsiveness of - * live view browser + * image defaults apply (1920x1080@25). Arbitrary viewport dimensions are accepted, + * but the following configurations are known-good and fully tested: 2560x1440@10, + * 1920x1080@25, 1920x1200@25, 1440x900@25, 1280x800@60, 1024x768@60, 1200x800@60. + * Viewports outside this list may exhibit unstable live view or recording + * behavior. If refresh_rate is not provided, it will be automatically determined + * based on the resolution (higher resolutions use lower refresh rates to keep + * bandwidth reasonable). */ viewport?: Shared.BrowserViewport; } @@ -467,13 +467,13 @@ export interface BrowserUpdateResponse { /** * Initial browser window size in pixels with optional refresh rate. If omitted, - * image defaults apply (1920x1080@25). Only specific viewport configurations are - * supported. The server will reject unsupported combinations. Supported - * resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25, 1440x900@25, - * 1280x800@60, 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will - * be automatically determined from the width and height if they match a supported - * configuration exactly. Note: Higher resolutions may affect the responsiveness of - * live view browser + * image defaults apply (1920x1080@25). Arbitrary viewport dimensions are accepted, + * but the following configurations are known-good and fully tested: 2560x1440@10, + * 1920x1080@25, 1920x1200@25, 1440x900@25, 1280x800@60, 1024x768@60, 1200x800@60. + * Viewports outside this list may exhibit unstable live view or recording + * behavior. If refresh_rate is not provided, it will be automatically determined + * based on the resolution (higher resolutions use lower refresh rates to keep + * bandwidth reasonable). */ viewport?: Shared.BrowserViewport; } @@ -543,13 +543,13 @@ export interface BrowserListResponse { /** * Initial browser window size in pixels with optional refresh rate. If omitted, - * image defaults apply (1920x1080@25). Only specific viewport configurations are - * supported. The server will reject unsupported combinations. Supported - * resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25, 1440x900@25, - * 1280x800@60, 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will - * be automatically determined from the width and height if they match a supported - * configuration exactly. Note: Higher resolutions may affect the responsiveness of - * live view browser + * image defaults apply (1920x1080@25). Arbitrary viewport dimensions are accepted, + * but the following configurations are known-good and fully tested: 2560x1440@10, + * 1920x1080@25, 1920x1200@25, 1440x900@25, 1280x800@60, 1024x768@60, 1200x800@60. + * Viewports outside this list may exhibit unstable live view or recording + * behavior. If refresh_rate is not provided, it will be automatically determined + * based on the resolution (higher resolutions use lower refresh rates to keep + * bandwidth reasonable). */ viewport?: Shared.BrowserViewport; } @@ -613,13 +613,13 @@ export interface BrowserCreateParams { /** * Initial browser window size in pixels with optional refresh rate. If omitted, - * image defaults apply (1920x1080@25). Only specific viewport configurations are - * supported. The server will reject unsupported combinations. Supported - * resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25, 1440x900@25, - * 1280x800@60, 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will - * be automatically determined from the width and height if they match a supported - * configuration exactly. Note: Higher resolutions may affect the responsiveness of - * live view browser + * image defaults apply (1920x1080@25). Arbitrary viewport dimensions are accepted, + * but the following configurations are known-good and fully tested: 2560x1440@10, + * 1920x1080@25, 1920x1200@25, 1440x900@25, 1280x800@60, 1024x768@60, 1200x800@60. + * Viewports outside this list may exhibit unstable live view or recording + * behavior. If refresh_rate is not provided, it will be automatically determined + * based on the resolution (higher resolutions use lower refresh rates to keep + * bandwidth reasonable). */ viewport?: Shared.BrowserViewport; } diff --git a/src/resources/invocations.ts b/src/resources/invocations.ts index d8883bb6..edf604ea 100644 --- a/src/resources/invocations.ts +++ b/src/resources/invocations.ts @@ -479,13 +479,13 @@ export namespace InvocationListBrowsersResponse { /** * Initial browser window size in pixels with optional refresh rate. If omitted, - * image defaults apply (1920x1080@25). Only specific viewport configurations are - * supported. The server will reject unsupported combinations. Supported - * resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25, 1440x900@25, - * 1280x800@60, 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will - * be automatically determined from the width and height if they match a supported - * configuration exactly. Note: Higher resolutions may affect the responsiveness of - * live view browser + * image defaults apply (1920x1080@25). Arbitrary viewport dimensions are accepted, + * but the following configurations are known-good and fully tested: 2560x1440@10, + * 1920x1080@25, 1920x1200@25, 1440x900@25, 1280x800@60, 1024x768@60, 1200x800@60. + * Viewports outside this list may exhibit unstable live view or recording + * behavior. If refresh_rate is not provided, it will be automatically determined + * based on the resolution (higher resolutions use lower refresh rates to keep + * bandwidth reasonable). */ viewport?: Shared.BrowserViewport; } diff --git a/src/resources/shared.ts b/src/resources/shared.ts index 600b53dd..14f7905b 100644 --- a/src/resources/shared.ts +++ b/src/resources/shared.ts @@ -53,13 +53,13 @@ export interface BrowserProfile { /** * Initial browser window size in pixels with optional refresh rate. If omitted, - * image defaults apply (1920x1080@25). Only specific viewport configurations are - * supported. The server will reject unsupported combinations. Supported - * resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25, 1440x900@25, - * 1280x800@60, 1024x768@60, 1200x800@60 If refresh_rate is not provided, it will - * be automatically determined from the width and height if they match a supported - * configuration exactly. Note: Higher resolutions may affect the responsiveness of - * live view browser + * image defaults apply (1920x1080@25). Arbitrary viewport dimensions are accepted, + * but the following configurations are known-good and fully tested: 2560x1440@10, + * 1920x1080@25, 1920x1200@25, 1440x900@25, 1280x800@60, 1024x768@60, 1200x800@60. + * Viewports outside this list may exhibit unstable live view or recording + * behavior. If refresh_rate is not provided, it will be automatically determined + * based on the resolution (higher resolutions use lower refresh rates to keep + * bandwidth reasonable). */ export interface BrowserViewport { /** From d774c413d18ea0c199d5800e25466278f67b2d0c Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 18 Feb 2026 03:20:13 +0000 Subject: [PATCH 292/551] chore(internal/client): fix form-urlencoded requests --- src/client.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/client.ts b/src/client.ts index 47edbb26..1798df30 100644 --- a/src/client.ts +++ b/src/client.ts @@ -841,6 +841,14 @@ export class Kernel { (Symbol.iterator in body && 'next' in body && typeof body.next === 'function')) ) { return { bodyHeaders: undefined, body: Shims.ReadableStreamFrom(body as AsyncIterable) }; + } else if ( + typeof body === 'object' && + headers.values.get('content-type') === 'application/x-www-form-urlencoded' + ) { + return { + bodyHeaders: { 'content-type': 'application/x-www-form-urlencoded' }, + body: this.stringifyQuery(body as Record), + }; } else { return this.#encoder({ body, headers }); } From e4f7782e4816e4c755778d1ba31e17ee7f762332 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 18 Feb 2026 19:47:31 +0000 Subject: [PATCH 293/551] feat: Neil/kernel 873 templates v4 --- .stats.yml | 4 ++-- src/resources/shared.ts | 12 ++++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 264b8c9d..1c121c21 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 100 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-47ee6a2b624baddb41a681feff758bf1893cd3d65edf3ab51219ebe4d942932b.yml -openapi_spec_hash: 76178c41ede593e76bfacb176057d2f0 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-2b77b2efd4d25aaa264cbd6fcb0e43f82d14ce5a4bd6fb1e3859be440868685a.yml +openapi_spec_hash: 299be31ecb4a96dcd54d4d902a716e68 config_hash: 27c0ea01aeb797a1767af139851c5b66 diff --git a/src/resources/shared.ts b/src/resources/shared.ts index 14f7905b..0c26a74e 100644 --- a/src/resources/shared.ts +++ b/src/resources/shared.ts @@ -8,6 +8,18 @@ export interface AppAction { * Name of the action */ name: string; + + /** + * JSON Schema (draft-07) describing the expected input payload. Null if schema + * could not be automatically generated. + */ + input_schema?: { [key: string]: unknown } | null; + + /** + * JSON Schema (draft-07) describing the expected output payload. Null if schema + * could not be automatically generated. + */ + output_schema?: { [key: string]: unknown } | null; } /** From 5c9d9115572a04cbd3b8b34de2551f60d4144676 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 18 Feb 2026 19:56:00 +0000 Subject: [PATCH 294/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 53ecb865..8878352c 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.33.0" + ".": "0.34.0" } diff --git a/package.json b/package.json index a61f6b27..2b2cdc90 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.33.0", + "version": "0.34.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index dc173dd4..48199984 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.33.0'; // x-release-please-version +export const VERSION = '0.34.0'; // x-release-please-version From a36bbec2f6349c2cf26f18e90c60e9da836cd86b Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 18 Feb 2026 20:16:50 +0000 Subject: [PATCH 295/551] feat: GPU pools --- .stats.yml | 4 +-- src/resources/browser-pools.ts | 5 ++++ src/resources/browsers/browsers.ts | 26 +++++++++++++++++++ src/resources/invocations.ts | 5 ++++ tests/api-resources/browsers/browsers.test.ts | 1 + 5 files changed, 39 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 1c121c21..92d7f1dc 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 100 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-2b77b2efd4d25aaa264cbd6fcb0e43f82d14ce5a4bd6fb1e3859be440868685a.yml -openapi_spec_hash: 299be31ecb4a96dcd54d4d902a716e68 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-a0f1d08e6f62a74de2aac5c25e592494abdd59f2cfca2842c5810927554faee0.yml +openapi_spec_hash: ebd8bf67b7bb371cf4b4fa68b967cab5 config_hash: 27c0ea01aeb797a1767af139851c5b66 diff --git a/src/resources/browser-pools.ts b/src/resources/browser-pools.ts index 6192e483..e71d7be1 100644 --- a/src/resources/browser-pools.ts +++ b/src/resources/browser-pools.ts @@ -296,6 +296,11 @@ export interface BrowserPoolAcquireResponse { */ deleted_at?: string; + /** + * Whether the browser session has hardware-accelerated GPU rendering. + */ + gpu?: boolean; + /** * Whether the browser session is running in kiosk mode. */ diff --git a/src/resources/browsers/browsers.ts b/src/resources/browsers/browsers.ts index 3a6f855b..bc1d4818 100644 --- a/src/resources/browsers/browsers.ts +++ b/src/resources/browsers/browsers.ts @@ -292,6 +292,11 @@ export interface BrowserCreateResponse { */ deleted_at?: string; + /** + * Whether the browser session has hardware-accelerated GPU rendering. + */ + gpu?: boolean; + /** * Whether the browser session is running in kiosk mode. */ @@ -368,6 +373,11 @@ export interface BrowserRetrieveResponse { */ deleted_at?: string; + /** + * Whether the browser session has hardware-accelerated GPU rendering. + */ + gpu?: boolean; + /** * Whether the browser session is running in kiosk mode. */ @@ -444,6 +454,11 @@ export interface BrowserUpdateResponse { */ deleted_at?: string; + /** + * Whether the browser session has hardware-accelerated GPU rendering. + */ + gpu?: boolean; + /** * Whether the browser session is running in kiosk mode. */ @@ -520,6 +535,11 @@ export interface BrowserListResponse { */ deleted_at?: string; + /** + * Whether the browser session has hardware-accelerated GPU rendering. + */ + gpu?: boolean; + /** * Whether the browser session is running in kiosk mode. */ @@ -560,6 +580,12 @@ export interface BrowserCreateParams { */ extensions?: Array; + /** + * If true, launches a hardware-accelerated browser with GPU rendering. Requires + * Start-Up or Enterprise plan. + */ + gpu?: boolean; + /** * If true, launches the browser using a headless image (no VNC/GUI). Defaults to * false. diff --git a/src/resources/invocations.ts b/src/resources/invocations.ts index edf604ea..d75c9f39 100644 --- a/src/resources/invocations.ts +++ b/src/resources/invocations.ts @@ -456,6 +456,11 @@ export namespace InvocationListBrowsersResponse { */ deleted_at?: string; + /** + * Whether the browser session has hardware-accelerated GPU rendering. + */ + gpu?: boolean; + /** * Whether the browser session is running in kiosk mode. */ diff --git a/tests/api-resources/browsers/browsers.test.ts b/tests/api-resources/browsers/browsers.test.ts index 51fecec7..585f57b5 100644 --- a/tests/api-resources/browsers/browsers.test.ts +++ b/tests/api-resources/browsers/browsers.test.ts @@ -27,6 +27,7 @@ describe('resource browsers', () => { client.browsers.create( { extensions: [{ id: 'id', name: 'name' }], + gpu: false, headless: false, invocation_id: 'rr33xuugxj9h0bkf1rdt2bet', kiosk_mode: true, From 41354259f9ba5d8d7275c6b2b7aa0ecc9c6aba6e Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 19 Feb 2026 19:20:32 +0000 Subject: [PATCH 296/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 8878352c..3a39fd8c 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.34.0" + ".": "0.35.0" } diff --git a/package.json b/package.json index 2b2cdc90..c535a3f8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.34.0", + "version": "0.35.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 48199984..3f1d4329 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.34.0'; // x-release-please-version +export const VERSION = '0.35.0'; // x-release-please-version From a28a3c44ff5e801d852efb189c491f958c6cf5dd Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 20 Feb 2026 03:24:37 +0000 Subject: [PATCH 297/551] chore(internal): remove mock server code --- scripts/mock | 41 ----------------------------------------- scripts/test | 46 ---------------------------------------------- 2 files changed, 87 deletions(-) delete mode 100755 scripts/mock diff --git a/scripts/mock b/scripts/mock deleted file mode 100755 index 0b28f6ea..00000000 --- a/scripts/mock +++ /dev/null @@ -1,41 +0,0 @@ -#!/usr/bin/env bash - -set -e - -cd "$(dirname "$0")/.." - -if [[ -n "$1" && "$1" != '--'* ]]; then - URL="$1" - shift -else - URL="$(grep 'openapi_spec_url' .stats.yml | cut -d' ' -f2)" -fi - -# Check if the URL is empty -if [ -z "$URL" ]; then - echo "Error: No OpenAPI spec path/url provided or found in .stats.yml" - exit 1 -fi - -echo "==> Starting mock server with URL ${URL}" - -# Run prism mock on the given spec -if [ "$1" == "--daemon" ]; then - npm exec --package=@stainless-api/prism-cli@5.15.0 -- prism mock "$URL" &> .prism.log & - - # Wait for server to come online - echo -n "Waiting for server" - while ! grep -q "✖ fatal\|Prism is listening" ".prism.log" ; do - echo -n "." - sleep 0.1 - done - - if grep -q "✖ fatal" ".prism.log"; then - cat .prism.log - exit 1 - fi - - echo -else - npm exec --package=@stainless-api/prism-cli@5.15.0 -- prism mock "$URL" -fi diff --git a/scripts/test b/scripts/test index 7bce0516..548da9bb 100755 --- a/scripts/test +++ b/scripts/test @@ -4,53 +4,7 @@ set -e cd "$(dirname "$0")/.." -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[0;33m' -NC='\033[0m' # No Color -function prism_is_running() { - curl --silent "http://localhost:4010" >/dev/null 2>&1 -} - -kill_server_on_port() { - pids=$(lsof -t -i tcp:"$1" || echo "") - if [ "$pids" != "" ]; then - kill "$pids" - echo "Stopped $pids." - fi -} - -function is_overriding_api_base_url() { - [ -n "$TEST_API_BASE_URL" ] -} - -if ! is_overriding_api_base_url && ! prism_is_running ; then - # When we exit this script, make sure to kill the background mock server process - trap 'kill_server_on_port 4010' EXIT - - # Start the dev server - ./scripts/mock --daemon -fi - -if is_overriding_api_base_url ; then - echo -e "${GREEN}✔ Running tests against ${TEST_API_BASE_URL}${NC}" - echo -elif ! prism_is_running ; then - echo -e "${RED}ERROR:${NC} The test suite will not run without a mock Prism server" - echo -e "running against your OpenAPI spec." - echo - echo -e "To run the server, pass in the path or url of your OpenAPI" - echo -e "spec to the prism command:" - echo - echo -e " \$ ${YELLOW}npm exec --package=@stainless-api/prism-cli@5.15.0 -- prism mock path/to/your.openapi.yml${NC}" - echo - - exit 1 -else - echo -e "${GREEN}✔ Mock prism server is running with your OpenAPI spec${NC}" - echo -fi echo "==> Running tests" ./node_modules/.bin/jest "$@" From 068b5904814ab5b189a8983fa5ddedfb5429a5af Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 20 Feb 2026 03:26:24 +0000 Subject: [PATCH 298/551] chore: update mock server docs --- CONTRIBUTING.md | 6 --- tests/api-resources/apps.test.ts | 4 +- tests/api-resources/auth/connections.test.ts | 20 +++++----- tests/api-resources/browser-pools.test.ts | 24 +++++------ tests/api-resources/browsers/browsers.test.ts | 24 +++++------ tests/api-resources/browsers/computer.test.ts | 34 ++++++++-------- tests/api-resources/browsers/fs/fs.test.ts | 40 +++++++++---------- tests/api-resources/browsers/fs/watch.test.ts | 12 +++--- tests/api-resources/browsers/logs.test.ts | 4 +- .../api-resources/browsers/playwright.test.ts | 4 +- tests/api-resources/browsers/process.test.ts | 28 ++++++------- tests/api-resources/browsers/replays.test.ts | 10 ++--- .../credential-providers.test.ts | 16 ++++---- tests/api-resources/credentials.test.ts | 16 ++++---- tests/api-resources/deployments.test.ts | 12 +++--- tests/api-resources/extensions.test.ts | 8 ++-- tests/api-resources/invocations.test.ts | 22 +++++----- tests/api-resources/profiles.test.ts | 8 ++-- tests/api-resources/proxies.test.ts | 12 +++--- 19 files changed, 149 insertions(+), 155 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 30dc1266..1455d3cb 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -65,12 +65,6 @@ $ pnpm link -—global @onkernel/sdk ## Running tests -Most tests require you to [set up a mock server](https://github.com/stoplightio/prism) against the OpenAPI spec to run the tests. - -```sh -$ npx prism mock path/to/your/openapi.yml -``` - ```sh $ yarn run test ``` diff --git a/tests/api-resources/apps.test.ts b/tests/api-resources/apps.test.ts index d1a35f28..07b6bf0e 100644 --- a/tests/api-resources/apps.test.ts +++ b/tests/api-resources/apps.test.ts @@ -8,7 +8,7 @@ const client = new Kernel({ }); describe('resource apps', () => { - // Prism tests are disabled + // Mock server tests are disabled test.skip('list', async () => { const responsePromise = client.apps.list(); const rawResponse = await responsePromise.asResponse(); @@ -20,7 +20,7 @@ describe('resource apps', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('list: 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( diff --git a/tests/api-resources/auth/connections.test.ts b/tests/api-resources/auth/connections.test.ts index 21dae74e..6153b3f3 100644 --- a/tests/api-resources/auth/connections.test.ts +++ b/tests/api-resources/auth/connections.test.ts @@ -8,7 +8,7 @@ const client = new Kernel({ }); describe('resource connections', () => { - // Prism tests are disabled + // Mock server tests are disabled test.skip('create: only required params', async () => { const responsePromise = client.auth.connections.create({ domain: 'netflix.com', @@ -23,7 +23,7 @@ describe('resource connections', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('create: required and optional params', async () => { const response = await client.auth.connections.create({ domain: 'netflix.com', @@ -42,7 +42,7 @@ describe('resource connections', () => { }); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('retrieve', async () => { const responsePromise = client.auth.connections.retrieve('id'); const rawResponse = await responsePromise.asResponse(); @@ -54,7 +54,7 @@ describe('resource connections', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('list', async () => { const responsePromise = client.auth.connections.list(); const rawResponse = await responsePromise.asResponse(); @@ -66,7 +66,7 @@ describe('resource connections', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('list: 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( @@ -82,7 +82,7 @@ describe('resource connections', () => { ).rejects.toThrow(Kernel.NotFoundError); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('delete', async () => { const responsePromise = client.auth.connections.delete('id'); const rawResponse = await responsePromise.asResponse(); @@ -94,7 +94,7 @@ describe('resource connections', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism doesn't support text/event-stream responses + // Mock server doesn't support text/event-stream responses test.skip('follow', async () => { const responsePromise = client.auth.connections.follow('id'); const rawResponse = await responsePromise.asResponse(); @@ -106,7 +106,7 @@ describe('resource connections', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('login', async () => { const responsePromise = client.auth.connections.login('id'); const rawResponse = await responsePromise.asResponse(); @@ -118,7 +118,7 @@ describe('resource connections', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('login: 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( @@ -130,7 +130,7 @@ describe('resource connections', () => { ).rejects.toThrow(Kernel.NotFoundError); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('submit', async () => { const responsePromise = client.auth.connections.submit('id', {}); const rawResponse = await responsePromise.asResponse(); diff --git a/tests/api-resources/browser-pools.test.ts b/tests/api-resources/browser-pools.test.ts index 97737bbb..a3239d79 100644 --- a/tests/api-resources/browser-pools.test.ts +++ b/tests/api-resources/browser-pools.test.ts @@ -8,7 +8,7 @@ const client = new Kernel({ }); describe('resource browserPools', () => { - // Prism tests are disabled + // Mock server tests are disabled test.skip('create: only required params', async () => { const responsePromise = client.browserPools.create({ size: 10 }); const rawResponse = await responsePromise.asResponse(); @@ -20,7 +20,7 @@ describe('resource browserPools', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('create: required and optional params', async () => { const response = await client.browserPools.create({ size: 10, @@ -45,7 +45,7 @@ describe('resource browserPools', () => { }); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('retrieve', async () => { const responsePromise = client.browserPools.retrieve('id_or_name'); const rawResponse = await responsePromise.asResponse(); @@ -57,7 +57,7 @@ describe('resource browserPools', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('update: only required params', async () => { const responsePromise = client.browserPools.update('id_or_name', { size: 10 }); const rawResponse = await responsePromise.asResponse(); @@ -69,7 +69,7 @@ describe('resource browserPools', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('update: required and optional params', async () => { const response = await client.browserPools.update('id_or_name', { size: 10, @@ -95,7 +95,7 @@ describe('resource browserPools', () => { }); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('list', async () => { const responsePromise = client.browserPools.list(); const rawResponse = await responsePromise.asResponse(); @@ -107,7 +107,7 @@ describe('resource browserPools', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('delete', async () => { const responsePromise = client.browserPools.delete('id_or_name'); const rawResponse = await responsePromise.asResponse(); @@ -119,7 +119,7 @@ describe('resource browserPools', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('delete: 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( @@ -127,7 +127,7 @@ describe('resource browserPools', () => { ).rejects.toThrow(Kernel.NotFoundError); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('acquire', async () => { const responsePromise = client.browserPools.acquire('id_or_name', {}); const rawResponse = await responsePromise.asResponse(); @@ -139,7 +139,7 @@ describe('resource browserPools', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('flush', async () => { const responsePromise = client.browserPools.flush('id_or_name'); const rawResponse = await responsePromise.asResponse(); @@ -151,7 +151,7 @@ describe('resource browserPools', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('release: only required params', async () => { const responsePromise = client.browserPools.release('id_or_name', { session_id: 'ts8iy3sg25ibheguyni2lg9t', @@ -165,7 +165,7 @@ describe('resource browserPools', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('release: required and optional params', async () => { const response = await client.browserPools.release('id_or_name', { session_id: 'ts8iy3sg25ibheguyni2lg9t', diff --git a/tests/api-resources/browsers/browsers.test.ts b/tests/api-resources/browsers/browsers.test.ts index 585f57b5..6778382f 100644 --- a/tests/api-resources/browsers/browsers.test.ts +++ b/tests/api-resources/browsers/browsers.test.ts @@ -8,7 +8,7 @@ const client = new Kernel({ }); describe('resource browsers', () => { - // Prism tests are disabled + // Mock server tests are disabled test.skip('create', async () => { const responsePromise = client.browsers.create(); const rawResponse = await responsePromise.asResponse(); @@ -20,7 +20,7 @@ describe('resource browsers', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('create: 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( @@ -51,7 +51,7 @@ describe('resource browsers', () => { ).rejects.toThrow(Kernel.NotFoundError); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('retrieve', async () => { const responsePromise = client.browsers.retrieve('htzv5orfit78e1m2biiifpbv'); const rawResponse = await responsePromise.asResponse(); @@ -63,7 +63,7 @@ describe('resource browsers', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('retrieve: 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( @@ -75,7 +75,7 @@ describe('resource browsers', () => { ).rejects.toThrow(Kernel.NotFoundError); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('update', async () => { const responsePromise = client.browsers.update('htzv5orfit78e1m2biiifpbv', {}); const rawResponse = await responsePromise.asResponse(); @@ -87,7 +87,7 @@ describe('resource browsers', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('list', async () => { const responsePromise = client.browsers.list(); const rawResponse = await responsePromise.asResponse(); @@ -99,7 +99,7 @@ describe('resource browsers', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('list: 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( @@ -115,7 +115,7 @@ describe('resource browsers', () => { ).rejects.toThrow(Kernel.NotFoundError); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('delete: only required params', async () => { const responsePromise = client.browsers.delete({ persistent_id: 'persistent_id' }); const rawResponse = await responsePromise.asResponse(); @@ -127,12 +127,12 @@ describe('resource browsers', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('delete: required and optional params', async () => { const response = await client.browsers.delete({ persistent_id: 'persistent_id' }); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('deleteByID', async () => { const responsePromise = client.browsers.deleteByID('htzv5orfit78e1m2biiifpbv'); const rawResponse = await responsePromise.asResponse(); @@ -144,7 +144,7 @@ describe('resource browsers', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('loadExtensions: only required params', async () => { const responsePromise = client.browsers.loadExtensions('id', { extensions: [{ name: 'name', zip_file: await toFile(Buffer.from('# my file contents'), 'README.md') }], @@ -158,7 +158,7 @@ describe('resource browsers', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('loadExtensions: required and optional params', async () => { const response = await client.browsers.loadExtensions('id', { extensions: [{ name: 'name', zip_file: await toFile(Buffer.from('# my file contents'), 'README.md') }], diff --git a/tests/api-resources/browsers/computer.test.ts b/tests/api-resources/browsers/computer.test.ts index dbc78316..a0a4923e 100644 --- a/tests/api-resources/browsers/computer.test.ts +++ b/tests/api-resources/browsers/computer.test.ts @@ -8,7 +8,7 @@ const client = new Kernel({ }); describe('resource computer', () => { - // Prism tests are disabled + // Mock server tests are disabled test.skip('batch: only required params', async () => { const responsePromise = client.browsers.computer.batch('id', { actions: [{ type: 'click_mouse' }] }); const rawResponse = await responsePromise.asResponse(); @@ -20,7 +20,7 @@ describe('resource computer', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('batch: required and optional params', async () => { const response = await client.browsers.computer.batch('id', { actions: [ @@ -88,7 +88,7 @@ describe('resource computer', () => { ).rejects.toThrow(Kernel.NotFoundError); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('clickMouse: only required params', async () => { const responsePromise = client.browsers.computer.clickMouse('id', { x: 0, y: 0 }); const rawResponse = await responsePromise.asResponse(); @@ -100,7 +100,7 @@ describe('resource computer', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('clickMouse: required and optional params', async () => { const response = await client.browsers.computer.clickMouse('id', { x: 0, @@ -112,7 +112,7 @@ describe('resource computer', () => { }); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('dragMouse: only required params', async () => { const responsePromise = client.browsers.computer.dragMouse('id', { path: [ @@ -129,7 +129,7 @@ describe('resource computer', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('dragMouse: required and optional params', async () => { const response = await client.browsers.computer.dragMouse('id', { path: [ @@ -144,7 +144,7 @@ describe('resource computer', () => { }); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('getMousePosition', async () => { const responsePromise = client.browsers.computer.getMousePosition('id'); const rawResponse = await responsePromise.asResponse(); @@ -156,7 +156,7 @@ describe('resource computer', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('moveMouse: only required params', async () => { const responsePromise = client.browsers.computer.moveMouse('id', { x: 0, y: 0 }); const rawResponse = await responsePromise.asResponse(); @@ -168,7 +168,7 @@ describe('resource computer', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('moveMouse: required and optional params', async () => { const response = await client.browsers.computer.moveMouse('id', { x: 0, @@ -177,7 +177,7 @@ describe('resource computer', () => { }); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('pressKey: only required params', async () => { const responsePromise = client.browsers.computer.pressKey('id', { keys: ['string'] }); const rawResponse = await responsePromise.asResponse(); @@ -189,7 +189,7 @@ describe('resource computer', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('pressKey: required and optional params', async () => { const response = await client.browsers.computer.pressKey('id', { keys: ['string'], @@ -198,7 +198,7 @@ describe('resource computer', () => { }); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('scroll: only required params', async () => { const responsePromise = client.browsers.computer.scroll('id', { x: 0, y: 0 }); const rawResponse = await responsePromise.asResponse(); @@ -210,7 +210,7 @@ describe('resource computer', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('scroll: required and optional params', async () => { const response = await client.browsers.computer.scroll('id', { x: 0, @@ -221,7 +221,7 @@ describe('resource computer', () => { }); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('setCursorVisibility: only required params', async () => { const responsePromise = client.browsers.computer.setCursorVisibility('id', { hidden: true }); const rawResponse = await responsePromise.asResponse(); @@ -233,12 +233,12 @@ describe('resource computer', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('setCursorVisibility: required and optional params', async () => { const response = await client.browsers.computer.setCursorVisibility('id', { hidden: true }); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('typeText: only required params', async () => { const responsePromise = client.browsers.computer.typeText('id', { text: 'text' }); const rawResponse = await responsePromise.asResponse(); @@ -250,7 +250,7 @@ describe('resource computer', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('typeText: required and optional params', async () => { const response = await client.browsers.computer.typeText('id', { text: 'text', delay: 0 }); }); diff --git a/tests/api-resources/browsers/fs/fs.test.ts b/tests/api-resources/browsers/fs/fs.test.ts index 92a0c9ce..ad9eee2d 100644 --- a/tests/api-resources/browsers/fs/fs.test.ts +++ b/tests/api-resources/browsers/fs/fs.test.ts @@ -8,7 +8,7 @@ const client = new Kernel({ }); describe('resource fs', () => { - // Prism tests are disabled + // Mock server tests are disabled test.skip('createDirectory: only required params', async () => { const responsePromise = client.browsers.fs.createDirectory('id', { path: '/J!' }); const rawResponse = await responsePromise.asResponse(); @@ -20,12 +20,12 @@ describe('resource fs', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('createDirectory: required and optional params', async () => { const response = await client.browsers.fs.createDirectory('id', { path: '/J!', mode: '0611' }); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('deleteDirectory: only required params', async () => { const responsePromise = client.browsers.fs.deleteDirectory('id', { path: '/J!' }); const rawResponse = await responsePromise.asResponse(); @@ -37,12 +37,12 @@ describe('resource fs', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('deleteDirectory: required and optional params', async () => { const response = await client.browsers.fs.deleteDirectory('id', { path: '/J!' }); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('deleteFile: only required params', async () => { const responsePromise = client.browsers.fs.deleteFile('id', { path: '/J!' }); const rawResponse = await responsePromise.asResponse(); @@ -54,7 +54,7 @@ describe('resource fs', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('deleteFile: required and optional params', async () => { const response = await client.browsers.fs.deleteFile('id', { path: '/J!' }); }); @@ -63,7 +63,7 @@ describe('resource fs', () => { const response = await client.browsers.fs.downloadDirZip('id', { path: '/J!' }); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('fileInfo: only required params', async () => { const responsePromise = client.browsers.fs.fileInfo('id', { path: '/J!' }); const rawResponse = await responsePromise.asResponse(); @@ -75,12 +75,12 @@ describe('resource fs', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('fileInfo: required and optional params', async () => { const response = await client.browsers.fs.fileInfo('id', { path: '/J!' }); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('listFiles: only required params', async () => { const responsePromise = client.browsers.fs.listFiles('id', { path: '/J!' }); const rawResponse = await responsePromise.asResponse(); @@ -92,12 +92,12 @@ describe('resource fs', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('listFiles: required and optional params', async () => { const response = await client.browsers.fs.listFiles('id', { path: '/J!' }); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('move: only required params', async () => { const responsePromise = client.browsers.fs.move('id', { dest_path: '/J!', src_path: '/J!' }); const rawResponse = await responsePromise.asResponse(); @@ -109,7 +109,7 @@ describe('resource fs', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('move: required and optional params', async () => { const response = await client.browsers.fs.move('id', { dest_path: '/J!', src_path: '/J!' }); }); @@ -118,7 +118,7 @@ describe('resource fs', () => { const response = await client.browsers.fs.readFile('id', { path: '/J!' }); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('setFilePermissions: only required params', async () => { const responsePromise = client.browsers.fs.setFilePermissions('id', { mode: '0611', path: '/J!' }); const rawResponse = await responsePromise.asResponse(); @@ -130,7 +130,7 @@ describe('resource fs', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('setFilePermissions: required and optional params', async () => { const response = await client.browsers.fs.setFilePermissions('id', { mode: '0611', @@ -140,7 +140,7 @@ describe('resource fs', () => { }); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('upload: only required params', async () => { const responsePromise = client.browsers.fs.upload('id', { files: [{ dest_path: '/J!', file: await toFile(Buffer.from('# my file contents'), 'README.md') }], @@ -154,14 +154,14 @@ describe('resource fs', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('upload: required and optional params', async () => { const response = await client.browsers.fs.upload('id', { files: [{ dest_path: '/J!', file: await toFile(Buffer.from('# my file contents'), 'README.md') }], }); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('uploadZip: only required params', async () => { const responsePromise = client.browsers.fs.uploadZip('id', { dest_path: '/J!', @@ -176,7 +176,7 @@ describe('resource fs', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('uploadZip: required and optional params', async () => { const response = await client.browsers.fs.uploadZip('id', { dest_path: '/J!', @@ -184,7 +184,7 @@ describe('resource fs', () => { }); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('writeFile: only required params', async () => { const responsePromise = client.browsers.fs.writeFile( 'id', @@ -200,7 +200,7 @@ describe('resource fs', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('writeFile: required and optional params', async () => { const response = await client.browsers.fs.writeFile( 'id', diff --git a/tests/api-resources/browsers/fs/watch.test.ts b/tests/api-resources/browsers/fs/watch.test.ts index 47ddfb80..57afd6d6 100644 --- a/tests/api-resources/browsers/fs/watch.test.ts +++ b/tests/api-resources/browsers/fs/watch.test.ts @@ -8,7 +8,7 @@ const client = new Kernel({ }); describe('resource watch', () => { - // Prism doesn't support text/event-stream responses + // Mock server doesn't support text/event-stream responses test.skip('events: only required params', async () => { const responsePromise = client.browsers.fs.watch.events('watch_id', { id: 'id' }); const rawResponse = await responsePromise.asResponse(); @@ -20,12 +20,12 @@ describe('resource watch', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism doesn't support text/event-stream responses + // Mock server doesn't support text/event-stream responses test.skip('events: required and optional params', async () => { const response = await client.browsers.fs.watch.events('watch_id', { id: 'id' }); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('start: only required params', async () => { const responsePromise = client.browsers.fs.watch.start('id', { path: 'path' }); const rawResponse = await responsePromise.asResponse(); @@ -37,12 +37,12 @@ describe('resource watch', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('start: required and optional params', async () => { const response = await client.browsers.fs.watch.start('id', { path: 'path', recursive: true }); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('stop: only required params', async () => { const responsePromise = client.browsers.fs.watch.stop('watch_id', { id: 'id' }); const rawResponse = await responsePromise.asResponse(); @@ -54,7 +54,7 @@ describe('resource watch', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('stop: required and optional params', async () => { const response = await client.browsers.fs.watch.stop('watch_id', { id: 'id' }); }); diff --git a/tests/api-resources/browsers/logs.test.ts b/tests/api-resources/browsers/logs.test.ts index 0fa405ec..377b5158 100644 --- a/tests/api-resources/browsers/logs.test.ts +++ b/tests/api-resources/browsers/logs.test.ts @@ -8,7 +8,7 @@ const client = new Kernel({ }); describe('resource logs', () => { - // Prism doesn't support text/event-stream responses + // Mock server doesn't support text/event-stream responses test.skip('stream: only required params', async () => { const responsePromise = client.browsers.logs.stream('id', { source: 'path' }); const rawResponse = await responsePromise.asResponse(); @@ -20,7 +20,7 @@ describe('resource logs', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism doesn't support text/event-stream responses + // Mock server doesn't support text/event-stream responses test.skip('stream: required and optional params', async () => { const response = await client.browsers.logs.stream('id', { source: 'path', diff --git a/tests/api-resources/browsers/playwright.test.ts b/tests/api-resources/browsers/playwright.test.ts index 5c45947d..8b16eec9 100644 --- a/tests/api-resources/browsers/playwright.test.ts +++ b/tests/api-resources/browsers/playwright.test.ts @@ -8,7 +8,7 @@ const client = new Kernel({ }); describe('resource playwright', () => { - // Prism tests are disabled + // Mock server tests are disabled test.skip('execute: only required params', async () => { const responsePromise = client.browsers.playwright.execute('id', { code: 'code' }); const rawResponse = await responsePromise.asResponse(); @@ -20,7 +20,7 @@ describe('resource playwright', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('execute: required and optional params', async () => { const response = await client.browsers.playwright.execute('id', { code: 'code', timeout_sec: 1 }); }); diff --git a/tests/api-resources/browsers/process.test.ts b/tests/api-resources/browsers/process.test.ts index c608e246..104fce1c 100644 --- a/tests/api-resources/browsers/process.test.ts +++ b/tests/api-resources/browsers/process.test.ts @@ -8,7 +8,7 @@ const client = new Kernel({ }); describe('resource process', () => { - // Prism tests are disabled + // Mock server tests are disabled test.skip('exec: only required params', async () => { const responsePromise = client.browsers.process.exec('id', { command: 'command' }); const rawResponse = await responsePromise.asResponse(); @@ -20,7 +20,7 @@ describe('resource process', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('exec: required and optional params', async () => { const response = await client.browsers.process.exec('id', { command: 'command', @@ -33,7 +33,7 @@ describe('resource process', () => { }); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('kill: only required params', async () => { const responsePromise = client.browsers.process.kill('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', { id: 'id', @@ -48,7 +48,7 @@ describe('resource process', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('kill: required and optional params', async () => { const response = await client.browsers.process.kill('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', { id: 'id', @@ -56,7 +56,7 @@ describe('resource process', () => { }); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('resize: only required params', async () => { const responsePromise = client.browsers.process.resize('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', { id: 'id', @@ -72,7 +72,7 @@ describe('resource process', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('resize: required and optional params', async () => { const response = await client.browsers.process.resize('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', { id: 'id', @@ -81,7 +81,7 @@ describe('resource process', () => { }); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('spawn: only required params', async () => { const responsePromise = client.browsers.process.spawn('id', { command: 'command' }); const rawResponse = await responsePromise.asResponse(); @@ -93,7 +93,7 @@ describe('resource process', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('spawn: required and optional params', async () => { const response = await client.browsers.process.spawn('id', { command: 'command', @@ -109,7 +109,7 @@ describe('resource process', () => { }); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('status: only required params', async () => { const responsePromise = client.browsers.process.status('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', { id: 'id', @@ -123,14 +123,14 @@ describe('resource process', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('status: required and optional params', async () => { const response = await client.browsers.process.status('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', { id: 'id', }); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('stdin: only required params', async () => { const responsePromise = client.browsers.process.stdin('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', { id: 'id', @@ -145,7 +145,7 @@ describe('resource process', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('stdin: required and optional params', async () => { const response = await client.browsers.process.stdin('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', { id: 'id', @@ -153,7 +153,7 @@ describe('resource process', () => { }); }); - // Prism doesn't support text/event-stream responses + // Mock server doesn't support text/event-stream responses test.skip('stdoutStream: only required params', async () => { const responsePromise = client.browsers.process.stdoutStream('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', { id: 'id', @@ -167,7 +167,7 @@ describe('resource process', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism doesn't support text/event-stream responses + // Mock server doesn't support text/event-stream responses test.skip('stdoutStream: required and optional params', async () => { const response = await client.browsers.process.stdoutStream('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', { id: 'id', diff --git a/tests/api-resources/browsers/replays.test.ts b/tests/api-resources/browsers/replays.test.ts index d0ee498b..827bc09f 100644 --- a/tests/api-resources/browsers/replays.test.ts +++ b/tests/api-resources/browsers/replays.test.ts @@ -8,7 +8,7 @@ const client = new Kernel({ }); describe('resource replays', () => { - // Prism tests are disabled + // Mock server tests are disabled test.skip('list', async () => { const responsePromise = client.browsers.replays.list('id'); const rawResponse = await responsePromise.asResponse(); @@ -24,7 +24,7 @@ describe('resource replays', () => { const response = await client.browsers.replays.download('replay_id', { id: 'id' }); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('start', async () => { const responsePromise = client.browsers.replays.start('id'); const rawResponse = await responsePromise.asResponse(); @@ -36,7 +36,7 @@ describe('resource replays', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled 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( @@ -48,7 +48,7 @@ describe('resource replays', () => { ).rejects.toThrow(Kernel.NotFoundError); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('stop: only required params', async () => { const responsePromise = client.browsers.replays.stop('replay_id', { id: 'id' }); const rawResponse = await responsePromise.asResponse(); @@ -60,7 +60,7 @@ describe('resource replays', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('stop: required and optional params', async () => { const response = await client.browsers.replays.stop('replay_id', { id: 'id' }); }); diff --git a/tests/api-resources/credential-providers.test.ts b/tests/api-resources/credential-providers.test.ts index 5327b203..439b9a1a 100644 --- a/tests/api-resources/credential-providers.test.ts +++ b/tests/api-resources/credential-providers.test.ts @@ -8,7 +8,7 @@ const client = new Kernel({ }); describe('resource credentialProviders', () => { - // Prism tests are disabled + // Mock server tests are disabled test.skip('create: only required params', async () => { const responsePromise = client.credentialProviders.create({ token: 'ops_eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...', @@ -24,7 +24,7 @@ describe('resource credentialProviders', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('create: required and optional params', async () => { const response = await client.credentialProviders.create({ token: 'ops_eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...', @@ -34,7 +34,7 @@ describe('resource credentialProviders', () => { }); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('retrieve', async () => { const responsePromise = client.credentialProviders.retrieve('id'); const rawResponse = await responsePromise.asResponse(); @@ -46,7 +46,7 @@ describe('resource credentialProviders', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('update', async () => { const responsePromise = client.credentialProviders.update('id', {}); const rawResponse = await responsePromise.asResponse(); @@ -58,7 +58,7 @@ describe('resource credentialProviders', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('list', async () => { const responsePromise = client.credentialProviders.list(); const rawResponse = await responsePromise.asResponse(); @@ -70,7 +70,7 @@ describe('resource credentialProviders', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('delete', async () => { const responsePromise = client.credentialProviders.delete('id'); const rawResponse = await responsePromise.asResponse(); @@ -82,7 +82,7 @@ describe('resource credentialProviders', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('listItems', async () => { const responsePromise = client.credentialProviders.listItems('id'); const rawResponse = await responsePromise.asResponse(); @@ -94,7 +94,7 @@ describe('resource credentialProviders', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('test', async () => { const responsePromise = client.credentialProviders.test('id'); const rawResponse = await responsePromise.asResponse(); diff --git a/tests/api-resources/credentials.test.ts b/tests/api-resources/credentials.test.ts index d825b4e0..11ab0da6 100644 --- a/tests/api-resources/credentials.test.ts +++ b/tests/api-resources/credentials.test.ts @@ -8,7 +8,7 @@ const client = new Kernel({ }); describe('resource credentials', () => { - // Prism tests are disabled + // Mock server tests are disabled test.skip('create: only required params', async () => { const responsePromise = client.credentials.create({ domain: 'netflix.com', @@ -24,7 +24,7 @@ describe('resource credentials', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('create: required and optional params', async () => { const response = await client.credentials.create({ domain: 'netflix.com', @@ -35,7 +35,7 @@ describe('resource credentials', () => { }); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('retrieve', async () => { const responsePromise = client.credentials.retrieve('id_or_name'); const rawResponse = await responsePromise.asResponse(); @@ -47,7 +47,7 @@ describe('resource credentials', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('update', async () => { const responsePromise = client.credentials.update('id_or_name', {}); const rawResponse = await responsePromise.asResponse(); @@ -59,7 +59,7 @@ describe('resource credentials', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('list', async () => { const responsePromise = client.credentials.list(); const rawResponse = await responsePromise.asResponse(); @@ -71,7 +71,7 @@ describe('resource credentials', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('list: 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( @@ -86,7 +86,7 @@ describe('resource credentials', () => { ).rejects.toThrow(Kernel.NotFoundError); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('delete', async () => { const responsePromise = client.credentials.delete('id_or_name'); const rawResponse = await responsePromise.asResponse(); @@ -98,7 +98,7 @@ describe('resource credentials', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('totpCode', async () => { const responsePromise = client.credentials.totpCode('id_or_name'); const rawResponse = await responsePromise.asResponse(); diff --git a/tests/api-resources/deployments.test.ts b/tests/api-resources/deployments.test.ts index b3f0c201..460c76a5 100644 --- a/tests/api-resources/deployments.test.ts +++ b/tests/api-resources/deployments.test.ts @@ -8,7 +8,7 @@ const client = new Kernel({ }); describe('resource deployments', () => { - // Prism tests are disabled + // Mock server tests are disabled test.skip('create', async () => { const responsePromise = client.deployments.create({}); const rawResponse = await responsePromise.asResponse(); @@ -20,7 +20,7 @@ describe('resource deployments', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('retrieve', async () => { const responsePromise = client.deployments.retrieve('id'); const rawResponse = await responsePromise.asResponse(); @@ -32,7 +32,7 @@ describe('resource deployments', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('list', async () => { const responsePromise = client.deployments.list(); const rawResponse = await responsePromise.asResponse(); @@ -44,7 +44,7 @@ describe('resource deployments', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('list: 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( @@ -59,7 +59,7 @@ describe('resource deployments', () => { ).rejects.toThrow(Kernel.NotFoundError); }); - // Prism doesn't support text/event-stream responses + // Mock server doesn't support text/event-stream responses test.skip('follow', async () => { const responsePromise = client.deployments.follow('id'); const rawResponse = await responsePromise.asResponse(); @@ -71,7 +71,7 @@ describe('resource deployments', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism doesn't support text/event-stream responses + // Mock server doesn't support text/event-stream responses test.skip('follow: 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( diff --git a/tests/api-resources/extensions.test.ts b/tests/api-resources/extensions.test.ts index 515415fe..8a537407 100644 --- a/tests/api-resources/extensions.test.ts +++ b/tests/api-resources/extensions.test.ts @@ -8,7 +8,7 @@ const client = new Kernel({ }); describe('resource extensions', () => { - // Prism tests are disabled + // Mock server tests are disabled test.skip('list', async () => { const responsePromise = client.extensions.list(); const rawResponse = await responsePromise.asResponse(); @@ -20,7 +20,7 @@ describe('resource extensions', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('delete', async () => { const responsePromise = client.extensions.delete('id_or_name'); const rawResponse = await responsePromise.asResponse(); @@ -36,7 +36,7 @@ describe('resource extensions', () => { const response = await client.extensions.downloadFromChromeStore({ url: 'url', os: 'win' }); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('upload: only required params', async () => { const responsePromise = client.extensions.upload({ file: await toFile(Buffer.from('# my file contents'), 'README.md'), @@ -50,7 +50,7 @@ describe('resource extensions', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('upload: required and optional params', async () => { const response = await client.extensions.upload({ file: await toFile(Buffer.from('# my file contents'), 'README.md'), diff --git a/tests/api-resources/invocations.test.ts b/tests/api-resources/invocations.test.ts index cb7750a2..19ea81fb 100644 --- a/tests/api-resources/invocations.test.ts +++ b/tests/api-resources/invocations.test.ts @@ -8,7 +8,7 @@ const client = new Kernel({ }); describe('resource invocations', () => { - // Prism tests are disabled + // Mock server tests are disabled test.skip('create: only required params', async () => { const responsePromise = client.invocations.create({ action_name: 'analyze', @@ -24,7 +24,7 @@ describe('resource invocations', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('create: required and optional params', async () => { const response = await client.invocations.create({ action_name: 'analyze', @@ -36,7 +36,7 @@ describe('resource invocations', () => { }); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('retrieve', async () => { const responsePromise = client.invocations.retrieve('rr33xuugxj9h0bkf1rdt2bet'); const rawResponse = await responsePromise.asResponse(); @@ -48,7 +48,7 @@ describe('resource invocations', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('update: only required params', async () => { const responsePromise = client.invocations.update('id', { status: 'succeeded' }); const rawResponse = await responsePromise.asResponse(); @@ -60,12 +60,12 @@ describe('resource invocations', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('update: required and optional params', async () => { const response = await client.invocations.update('id', { status: 'succeeded', output: 'output' }); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('list', async () => { const responsePromise = client.invocations.list(); const rawResponse = await responsePromise.asResponse(); @@ -77,7 +77,7 @@ describe('resource invocations', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('list: 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( @@ -97,7 +97,7 @@ describe('resource invocations', () => { ).rejects.toThrow(Kernel.NotFoundError); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('deleteBrowsers', async () => { const responsePromise = client.invocations.deleteBrowsers('id'); const rawResponse = await responsePromise.asResponse(); @@ -109,7 +109,7 @@ describe('resource invocations', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism doesn't support text/event-stream responses + // Mock server doesn't support text/event-stream responses test.skip('follow', async () => { const responsePromise = client.invocations.follow('id'); const rawResponse = await responsePromise.asResponse(); @@ -121,7 +121,7 @@ describe('resource invocations', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism doesn't support text/event-stream responses + // Mock server doesn't support text/event-stream responses test.skip('follow: 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( @@ -133,7 +133,7 @@ describe('resource invocations', () => { ).rejects.toThrow(Kernel.NotFoundError); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('listBrowsers', async () => { const responsePromise = client.invocations.listBrowsers('id'); const rawResponse = await responsePromise.asResponse(); diff --git a/tests/api-resources/profiles.test.ts b/tests/api-resources/profiles.test.ts index 9fe686a5..3fd42093 100644 --- a/tests/api-resources/profiles.test.ts +++ b/tests/api-resources/profiles.test.ts @@ -8,7 +8,7 @@ const client = new Kernel({ }); describe('resource profiles', () => { - // Prism tests are disabled + // Mock server tests are disabled test.skip('create', async () => { const responsePromise = client.profiles.create({}); const rawResponse = await responsePromise.asResponse(); @@ -20,7 +20,7 @@ describe('resource profiles', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('retrieve', async () => { const responsePromise = client.profiles.retrieve('id_or_name'); const rawResponse = await responsePromise.asResponse(); @@ -32,7 +32,7 @@ describe('resource profiles', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('list', async () => { const responsePromise = client.profiles.list(); const rawResponse = await responsePromise.asResponse(); @@ -44,7 +44,7 @@ describe('resource profiles', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('delete', async () => { const responsePromise = client.profiles.delete('id_or_name'); const rawResponse = await responsePromise.asResponse(); diff --git a/tests/api-resources/proxies.test.ts b/tests/api-resources/proxies.test.ts index 1086c4fe..aa1f0529 100644 --- a/tests/api-resources/proxies.test.ts +++ b/tests/api-resources/proxies.test.ts @@ -8,7 +8,7 @@ const client = new Kernel({ }); describe('resource proxies', () => { - // Prism tests are disabled + // Mock server tests are disabled test.skip('create: only required params', async () => { const responsePromise = client.proxies.create({ type: 'datacenter' }); const rawResponse = await responsePromise.asResponse(); @@ -20,7 +20,7 @@ describe('resource proxies', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('create: required and optional params', async () => { const response = await client.proxies.create({ type: 'datacenter', @@ -30,7 +30,7 @@ describe('resource proxies', () => { }); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('retrieve', async () => { const responsePromise = client.proxies.retrieve('id'); const rawResponse = await responsePromise.asResponse(); @@ -42,7 +42,7 @@ describe('resource proxies', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('list', async () => { const responsePromise = client.proxies.list(); const rawResponse = await responsePromise.asResponse(); @@ -54,7 +54,7 @@ describe('resource proxies', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('delete', async () => { const responsePromise = client.proxies.delete('id'); const rawResponse = await responsePromise.asResponse(); @@ -66,7 +66,7 @@ describe('resource proxies', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled + // Mock server tests are disabled test.skip('check', async () => { const responsePromise = client.proxies.check('id'); const rawResponse = await responsePromise.asResponse(); From 8ca29abae61b378bab1e8e1c46bf91240b999a01 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 20 Feb 2026 03:27:50 +0000 Subject: [PATCH 299/551] chore(test): update skip reason message --- tests/api-resources/auth/connections.test.ts | 2 +- tests/api-resources/browsers/fs/watch.test.ts | 4 ++-- tests/api-resources/browsers/logs.test.ts | 4 ++-- tests/api-resources/browsers/process.test.ts | 4 ++-- tests/api-resources/deployments.test.ts | 4 ++-- tests/api-resources/invocations.test.ts | 4 ++-- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/tests/api-resources/auth/connections.test.ts b/tests/api-resources/auth/connections.test.ts index 6153b3f3..1c60d631 100644 --- a/tests/api-resources/auth/connections.test.ts +++ b/tests/api-resources/auth/connections.test.ts @@ -94,7 +94,7 @@ describe('resource connections', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Mock server doesn't support text/event-stream responses + // Mock server tests are disabled test.skip('follow', async () => { const responsePromise = client.auth.connections.follow('id'); const rawResponse = await responsePromise.asResponse(); diff --git a/tests/api-resources/browsers/fs/watch.test.ts b/tests/api-resources/browsers/fs/watch.test.ts index 57afd6d6..5d98d0f9 100644 --- a/tests/api-resources/browsers/fs/watch.test.ts +++ b/tests/api-resources/browsers/fs/watch.test.ts @@ -8,7 +8,7 @@ const client = new Kernel({ }); describe('resource watch', () => { - // Mock server doesn't support text/event-stream responses + // Mock server tests are disabled test.skip('events: only required params', async () => { const responsePromise = client.browsers.fs.watch.events('watch_id', { id: 'id' }); const rawResponse = await responsePromise.asResponse(); @@ -20,7 +20,7 @@ describe('resource watch', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Mock server doesn't support text/event-stream responses + // Mock server tests are disabled test.skip('events: required and optional params', async () => { const response = await client.browsers.fs.watch.events('watch_id', { id: 'id' }); }); diff --git a/tests/api-resources/browsers/logs.test.ts b/tests/api-resources/browsers/logs.test.ts index 377b5158..893d9aa7 100644 --- a/tests/api-resources/browsers/logs.test.ts +++ b/tests/api-resources/browsers/logs.test.ts @@ -8,7 +8,7 @@ const client = new Kernel({ }); describe('resource logs', () => { - // Mock server doesn't support text/event-stream responses + // Mock server tests are disabled test.skip('stream: only required params', async () => { const responsePromise = client.browsers.logs.stream('id', { source: 'path' }); const rawResponse = await responsePromise.asResponse(); @@ -20,7 +20,7 @@ describe('resource logs', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Mock server doesn't support text/event-stream responses + // Mock server tests are disabled test.skip('stream: required and optional params', async () => { const response = await client.browsers.logs.stream('id', { source: 'path', diff --git a/tests/api-resources/browsers/process.test.ts b/tests/api-resources/browsers/process.test.ts index 104fce1c..fda1a924 100644 --- a/tests/api-resources/browsers/process.test.ts +++ b/tests/api-resources/browsers/process.test.ts @@ -153,7 +153,7 @@ describe('resource process', () => { }); }); - // Mock server doesn't support text/event-stream responses + // Mock server tests are disabled test.skip('stdoutStream: only required params', async () => { const responsePromise = client.browsers.process.stdoutStream('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', { id: 'id', @@ -167,7 +167,7 @@ describe('resource process', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Mock server doesn't support text/event-stream responses + // Mock server tests are disabled test.skip('stdoutStream: required and optional params', async () => { const response = await client.browsers.process.stdoutStream('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', { id: 'id', diff --git a/tests/api-resources/deployments.test.ts b/tests/api-resources/deployments.test.ts index 460c76a5..7980b320 100644 --- a/tests/api-resources/deployments.test.ts +++ b/tests/api-resources/deployments.test.ts @@ -59,7 +59,7 @@ describe('resource deployments', () => { ).rejects.toThrow(Kernel.NotFoundError); }); - // Mock server doesn't support text/event-stream responses + // Mock server tests are disabled test.skip('follow', async () => { const responsePromise = client.deployments.follow('id'); const rawResponse = await responsePromise.asResponse(); @@ -71,7 +71,7 @@ describe('resource deployments', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Mock server doesn't support text/event-stream responses + // Mock server tests are disabled test.skip('follow: 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( diff --git a/tests/api-resources/invocations.test.ts b/tests/api-resources/invocations.test.ts index 19ea81fb..d1915b2e 100644 --- a/tests/api-resources/invocations.test.ts +++ b/tests/api-resources/invocations.test.ts @@ -109,7 +109,7 @@ describe('resource invocations', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Mock server doesn't support text/event-stream responses + // Mock server tests are disabled test.skip('follow', async () => { const responsePromise = client.invocations.follow('id'); const rawResponse = await responsePromise.asResponse(); @@ -121,7 +121,7 @@ describe('resource invocations', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Mock server doesn't support text/event-stream responses + // Mock server tests are disabled test.skip('follow: 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( From 8a4276a0294ac7e94fc1d8987a438c9b08c223ff Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 21 Feb 2026 18:10:34 +0000 Subject: [PATCH 300/551] feat: Add DELETE /deployments/{id} API endpoint --- .stats.yml | 8 ++++---- api.md | 1 + src/resources/deployments.ts | 16 ++++++++++++++++ tests/api-resources/deployments.test.ts | 12 ++++++++++++ 4 files changed, 33 insertions(+), 4 deletions(-) diff --git a/.stats.yml b/.stats.yml index 92d7f1dc..be750ebe 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 100 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-a0f1d08e6f62a74de2aac5c25e592494abdd59f2cfca2842c5810927554faee0.yml -openapi_spec_hash: ebd8bf67b7bb371cf4b4fa68b967cab5 -config_hash: 27c0ea01aeb797a1767af139851c5b66 +configured_endpoints: 101 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-bbc3dbdd0410eb315cfaeb21aad9f85e4a7f92ac55526ebb702a8bee343c2ab7.yml +openapi_spec_hash: 60a5134c45a8f3a217e128d4e3335cae +config_hash: 147340811dd6fbb9c2d80515a7e31f9a diff --git a/api.md b/api.md index 4aaf7c31..1e492561 100644 --- a/api.md +++ b/api.md @@ -27,6 +27,7 @@ Methods: - client.deployments.create({ ...params }) -> DeploymentCreateResponse - client.deployments.retrieve(id) -> DeploymentRetrieveResponse - client.deployments.list({ ...params }) -> DeploymentListResponsesOffsetPagination +- client.deployments.delete(id) -> void - client.deployments.follow(id, { ...params }) -> DeploymentFollowResponse # Apps diff --git a/src/resources/deployments.ts b/src/resources/deployments.ts index c297548e..09f17f59 100644 --- a/src/resources/deployments.ts +++ b/src/resources/deployments.ts @@ -63,6 +63,22 @@ export class Deployments extends APIResource { }); } + /** + * Stops a running deployment and marks it for deletion. If the deployment is + * already in a terminal state (stopped or failed), returns immediately. + * + * @example + * ```ts + * await client.deployments.delete('id'); + * ``` + */ + delete(id: string, options?: RequestOptions): APIPromise { + return this._client.delete(path`/deployments/${id}`, { + ...options, + headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), + }); + } + /** * Establishes a Server-Sent Events (SSE) stream that delivers real-time logs and * status updates for a deployment. The stream terminates automatically once the diff --git a/tests/api-resources/deployments.test.ts b/tests/api-resources/deployments.test.ts index 7980b320..5fd67347 100644 --- a/tests/api-resources/deployments.test.ts +++ b/tests/api-resources/deployments.test.ts @@ -59,6 +59,18 @@ describe('resource deployments', () => { ).rejects.toThrow(Kernel.NotFoundError); }); + // Mock server tests are disabled + test.skip('delete', async () => { + const responsePromise = client.deployments.delete('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); + }); + // Mock server tests are disabled test.skip('follow', async () => { const responsePromise = client.deployments.follow('id'); From 71286f60dd0dcb0cbeb77e0c82d2e0e85ee20f0d Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 21 Feb 2026 18:23:56 +0000 Subject: [PATCH 301/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 3a39fd8c..93c546c8 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.35.0" + ".": "0.36.0" } diff --git a/package.json b/package.json index c535a3f8..ef454c53 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.35.0", + "version": "0.36.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 3f1d4329..018dddd7 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.35.0'; // x-release-please-version +export const VERSION = '0.36.0'; // x-release-please-version From 9857cf22f4a7628e4f9f5cf544357fcc2191fc28 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 21 Feb 2026 20:54:03 +0000 Subject: [PATCH 302/551] feat: Add version filter to GET /deployments endpoint --- .stats.yml | 4 ++-- src/resources/deployments.ts | 7 ++++++- tests/api-resources/deployments.test.ts | 1 + 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/.stats.yml b/.stats.yml index be750ebe..c875efdd 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 101 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-bbc3dbdd0410eb315cfaeb21aad9f85e4a7f92ac55526ebb702a8bee343c2ab7.yml -openapi_spec_hash: 60a5134c45a8f3a217e128d4e3335cae +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-ea5c9cb25c29fa5a8758bbf8732eb306783bb6f13b4df29bf1ad5ad3cb32da1e.yml +openapi_spec_hash: 597031840469b011f5cf22a4d8b9d750 config_hash: 147340811dd6fbb9c2d80515a7e31f9a diff --git a/src/resources/deployments.ts b/src/resources/deployments.ts index 09f17f59..5f277da9 100644 --- a/src/resources/deployments.ts +++ b/src/resources/deployments.ts @@ -43,7 +43,7 @@ export class Deployments extends APIResource { } /** - * List deployments. Optionally filter by application name. + * List deployments. Optionally filter by application name and version. * * @example * ```ts @@ -461,6 +461,11 @@ export interface DeploymentListParams extends OffsetPaginationParams { * Filter results by application name. */ app_name?: string; + + /** + * Filter results by application version. Requires app_name to be set. + */ + app_version?: string; } export interface DeploymentFollowParams { diff --git a/tests/api-resources/deployments.test.ts b/tests/api-resources/deployments.test.ts index 5fd67347..3405cc89 100644 --- a/tests/api-resources/deployments.test.ts +++ b/tests/api-resources/deployments.test.ts @@ -51,6 +51,7 @@ describe('resource deployments', () => { client.deployments.list( { app_name: 'app_name', + app_version: 'app_version', limit: 1, offset: 0, }, From d5f38966ed2b0175ce56a90438c70b170c377128 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 21 Feb 2026 20:57:39 +0000 Subject: [PATCH 303/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 93c546c8..ae5e906b 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.36.0" + ".": "0.36.1" } diff --git a/package.json b/package.json index ef454c53..8672d5c1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.36.0", + "version": "0.36.1", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 018dddd7..918ad99e 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.36.0'; // x-release-please-version +export const VERSION = '0.36.1'; // x-release-please-version From e3c779634fd7f7f3e82782182edcb6658c303c00 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sun, 22 Feb 2026 03:07:22 +0000 Subject: [PATCH 304/551] fix(internal): skip tests that depend on mock server --- tests/api-resources/browsers/computer.test.ts | 3 ++- tests/api-resources/browsers/fs/fs.test.ts | 6 ++++-- tests/api-resources/browsers/replays.test.ts | 3 ++- tests/api-resources/extensions.test.ts | 3 ++- 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/tests/api-resources/browsers/computer.test.ts b/tests/api-resources/browsers/computer.test.ts index a0a4923e..36b388bf 100644 --- a/tests/api-resources/browsers/computer.test.ts +++ b/tests/api-resources/browsers/computer.test.ts @@ -70,7 +70,8 @@ describe('resource computer', () => { }); }); - test('captureScreenshot: request options and params are passed correctly', async () => { + // Mock server tests are disabled + test.skip('captureScreenshot: 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.computer.captureScreenshot( diff --git a/tests/api-resources/browsers/fs/fs.test.ts b/tests/api-resources/browsers/fs/fs.test.ts index ad9eee2d..086e98f7 100644 --- a/tests/api-resources/browsers/fs/fs.test.ts +++ b/tests/api-resources/browsers/fs/fs.test.ts @@ -59,7 +59,8 @@ describe('resource fs', () => { const response = await client.browsers.fs.deleteFile('id', { path: '/J!' }); }); - test('downloadDirZip: required and optional params', async () => { + // Mock server tests are disabled + test.skip('downloadDirZip: required and optional params', async () => { const response = await client.browsers.fs.downloadDirZip('id', { path: '/J!' }); }); @@ -114,7 +115,8 @@ describe('resource fs', () => { const response = await client.browsers.fs.move('id', { dest_path: '/J!', src_path: '/J!' }); }); - test('readFile: required and optional params', async () => { + // Mock server tests are disabled + test.skip('readFile: required and optional params', async () => { const response = await client.browsers.fs.readFile('id', { path: '/J!' }); }); diff --git a/tests/api-resources/browsers/replays.test.ts b/tests/api-resources/browsers/replays.test.ts index 827bc09f..bd985e5a 100644 --- a/tests/api-resources/browsers/replays.test.ts +++ b/tests/api-resources/browsers/replays.test.ts @@ -20,7 +20,8 @@ describe('resource replays', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - test('download: required and optional params', async () => { + // Mock server tests are disabled + test.skip('download: required and optional params', async () => { const response = await client.browsers.replays.download('replay_id', { id: 'id' }); }); diff --git a/tests/api-resources/extensions.test.ts b/tests/api-resources/extensions.test.ts index 8a537407..65c2ef37 100644 --- a/tests/api-resources/extensions.test.ts +++ b/tests/api-resources/extensions.test.ts @@ -32,7 +32,8 @@ describe('resource extensions', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - test('downloadFromChromeStore: required and optional params', async () => { + // Mock server tests are disabled + test.skip('downloadFromChromeStore: required and optional params', async () => { const response = await client.extensions.downloadFromChromeStore({ url: 'url', os: 'win' }); }); From dda4f5a7eabd383598d441478c115847ae95fc0c Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 23 Feb 2026 16:39:11 +0000 Subject: [PATCH 305/551] feat: Neil/kernel 1017 profile pagination query parameter --- .stats.yml | 6 +++--- api.md | 6 +----- src/client.ts | 4 ++-- src/resources/browsers/browsers.ts | 2 ++ src/resources/browsers/index.ts | 1 + src/resources/index.ts | 3 ++- src/resources/profiles.ts | 22 +++++++++++++++++----- tests/api-resources/profiles.test.ts | 15 +++++++++++++++ 8 files changed, 43 insertions(+), 16 deletions(-) diff --git a/.stats.yml b/.stats.yml index c875efdd..b154e7ae 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 101 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-ea5c9cb25c29fa5a8758bbf8732eb306783bb6f13b4df29bf1ad5ad3cb32da1e.yml -openapi_spec_hash: 597031840469b011f5cf22a4d8b9d750 -config_hash: 147340811dd6fbb9c2d80515a7e31f9a +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-fc4a441d80d9a26574ef8af390a0c76265f5d4190daf90a04b6b353b128bbd97.yml +openapi_spec_hash: 192987649d3797c3a80e6ef201667b64 +config_hash: 8af430e19f4af86c05f2987241cae72f diff --git a/api.md b/api.md index 1e492561..a29d404f 100644 --- a/api.md +++ b/api.md @@ -192,15 +192,11 @@ Methods: # Profiles -Types: - -- ProfileListResponse - Methods: - client.profiles.create({ ...params }) -> Profile - client.profiles.retrieve(idOrName) -> Profile -- client.profiles.list() -> ProfileListResponse +- client.profiles.list({ ...params }) -> ProfilesOffsetPagination - client.profiles.delete(idOrName) -> void - client.profiles.download(idOrName) -> Response diff --git a/src/client.ts b/src/client.ts index 1798df30..1c260a2a 100644 --- a/src/client.ts +++ b/src/client.ts @@ -87,7 +87,7 @@ import { InvocationUpdateResponse, Invocations, } from './resources/invocations'; -import { ProfileCreateParams, ProfileListResponse, Profiles } from './resources/profiles'; +import { ProfileCreateParams, ProfileListParams, Profiles } from './resources/profiles'; import { Proxies, ProxyCheckResponse, @@ -962,8 +962,8 @@ export declare namespace Kernel { export { Profiles as Profiles, - type ProfileListResponse as ProfileListResponse, type ProfileCreateParams as ProfileCreateParams, + type ProfileListParams as ProfileListParams, }; export { Auth as Auth }; diff --git a/src/resources/browsers/browsers.ts b/src/resources/browsers/browsers.ts index bc1d4818..87c2fdcf 100644 --- a/src/resources/browsers/browsers.ts +++ b/src/resources/browsers/browsers.ts @@ -209,6 +209,8 @@ export class Browsers extends APIResource { export type BrowserListResponsesOffsetPagination = OffsetPagination; +export type ProfilesOffsetPagination = OffsetPagination; + /** * @deprecated DEPRECATED: Use timeout_seconds (up to 72 hours) and Profiles * instead. diff --git a/src/resources/browsers/index.ts b/src/resources/browsers/index.ts index 178d54f5..1f4ef2be 100644 --- a/src/resources/browsers/index.ts +++ b/src/resources/browsers/index.ts @@ -14,6 +14,7 @@ export { type BrowserListParams, type BrowserDeleteParams, type BrowserLoadExtensionsParams, + type ProfilesOffsetPagination, type BrowserListResponsesOffsetPagination, } from './browsers'; export { diff --git a/src/resources/index.ts b/src/resources/index.ts index da81ceca..dcf5550b 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -33,6 +33,7 @@ export { type BrowserListParams, type BrowserDeleteParams, type BrowserLoadExtensionsParams, + type ProfilesOffsetPagination, type BrowserListResponsesOffsetPagination, } from './browsers/browsers'; export { @@ -92,7 +93,7 @@ export { type InvocationFollowParams, type InvocationListResponsesOffsetPagination, } from './invocations'; -export { Profiles, type ProfileListResponse, type ProfileCreateParams } from './profiles'; +export { Profiles, type ProfileCreateParams, type ProfileListParams } from './profiles'; export { Proxies, type ProxyCreateResponse, diff --git a/src/resources/profiles.ts b/src/resources/profiles.ts index 774f7641..2a3c613d 100644 --- a/src/resources/profiles.ts +++ b/src/resources/profiles.ts @@ -2,7 +2,9 @@ import { APIResource } from '../core/resource'; import * as BrowsersAPI from './browsers/browsers'; +import { ProfilesOffsetPagination } from './browsers/browsers'; import { APIPromise } from '../core/api-promise'; +import { OffsetPagination, type OffsetPaginationParams, PagePromise } from '../core/pagination'; import { buildHeaders } from '../internal/headers'; import { RequestOptions } from '../internal/request-options'; import { path } from '../internal/utils/path'; @@ -26,8 +28,11 @@ export class Profiles extends APIResource { /** * List profiles with optional filtering and pagination. */ - list(options?: RequestOptions): APIPromise { - return this._client.get('/profiles', options); + list( + query: ProfileListParams | null | undefined = {}, + options?: RequestOptions, + ): PagePromise { + return this._client.getAPIList('/profiles', OffsetPagination, { query, ...options }); } /** @@ -53,8 +58,6 @@ export class Profiles extends APIResource { } } -export type ProfileListResponse = Array; - export interface ProfileCreateParams { /** * Optional name of the profile. Must be unique within the organization. @@ -62,6 +65,15 @@ export interface ProfileCreateParams { name?: string; } +export interface ProfileListParams extends OffsetPaginationParams { + /** + * Search profiles by name or ID. + */ + query?: string; +} + export declare namespace Profiles { - export { type ProfileListResponse as ProfileListResponse, type ProfileCreateParams as ProfileCreateParams }; + export { type ProfileCreateParams as ProfileCreateParams, type ProfileListParams as ProfileListParams }; } + +export { type ProfilesOffsetPagination }; diff --git a/tests/api-resources/profiles.test.ts b/tests/api-resources/profiles.test.ts index 3fd42093..0bbb5574 100644 --- a/tests/api-resources/profiles.test.ts +++ b/tests/api-resources/profiles.test.ts @@ -44,6 +44,21 @@ describe('resource profiles', () => { expect(dataAndResponse.response).toBe(rawResponse); }); + // Mock server tests are disabled + test.skip('list: 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.profiles.list( + { + limit: 1, + offset: 0, + query: 'query', + }, + { path: '/_stainless_unknown_path' }, + ), + ).rejects.toThrow(Kernel.NotFoundError); + }); + // Mock server tests are disabled test.skip('delete', async () => { const responsePromise = client.profiles.delete('id_or_name'); From 6e87a3039113dc280882210c3e06f06fdaf0c1c7 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 23 Feb 2026 17:15:36 +0000 Subject: [PATCH 306/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index ae5e906b..05b60243 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.36.1" + ".": "0.37.0" } diff --git a/package.json b/package.json index 8672d5c1..6a1f68df 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.36.1", + "version": "0.37.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 918ad99e..16bacf66 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.36.1'; // x-release-please-version +export const VERSION = '0.37.0'; // x-release-please-version From 1624025e144bac27123af5a93306d2b547f22b11 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 24 Feb 2026 03:32:55 +0000 Subject: [PATCH 307/551] fix(docs/contributing): correct pnpm link command --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1455d3cb..dc97d15c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -60,7 +60,7 @@ $ yarn link @onkernel/sdk # With pnpm $ pnpm link --global $ cd ../my-package -$ pnpm link -—global @onkernel/sdk +$ pnpm link --global @onkernel/sdk ``` ## Running tests From 41c6f4e744947b3c1ec06d2c90156ead4878c7cf Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 25 Feb 2026 18:23:09 +0000 Subject: [PATCH 308/551] feat: Neil/kernel 1029 past session search --- .stats.yml | 6 +++--- src/resources/browsers/browsers.ts | 5 +++++ tests/api-resources/browsers/browsers.test.ts | 1 + 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/.stats.yml b/.stats.yml index b154e7ae..3e385c42 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 101 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-fc4a441d80d9a26574ef8af390a0c76265f5d4190daf90a04b6b353b128bbd97.yml -openapi_spec_hash: 192987649d3797c3a80e6ef201667b64 -config_hash: 8af430e19f4af86c05f2987241cae72f +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-9462b3d8f055f8bda06da65583f5aa09a17d35254c5983796d8e84ebb3c62c47.yml +openapi_spec_hash: 1914dd35b8e0e5a21ccec91eac2a616d +config_hash: c6b88eea9a15840f26130eb8ed3b42a0 diff --git a/src/resources/browsers/browsers.ts b/src/resources/browsers/browsers.ts index 87c2fdcf..34f21a52 100644 --- a/src/resources/browsers/browsers.ts +++ b/src/resources/browsers/browsers.ts @@ -685,6 +685,11 @@ export interface BrowserListParams extends OffsetPaginationParams { */ include_deleted?: boolean; + /** + * Search browsers by session ID, profile ID, or proxy ID. + */ + query?: string; + /** * Filter sessions by status. "active" returns only active sessions (default), * "deleted" returns only soft-deleted sessions, "all" returns both. diff --git a/tests/api-resources/browsers/browsers.test.ts b/tests/api-resources/browsers/browsers.test.ts index 6778382f..7647427a 100644 --- a/tests/api-resources/browsers/browsers.test.ts +++ b/tests/api-resources/browsers/browsers.test.ts @@ -108,6 +108,7 @@ describe('resource browsers', () => { include_deleted: true, limit: 1, offset: 0, + query: 'query', status: 'active', }, { path: '/_stainless_unknown_path' }, From 215d93f563734ba5fd65a738700b438376771003 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 25 Feb 2026 18:51:58 +0000 Subject: [PATCH 309/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 05b60243..bc86e4a2 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.37.0" + ".": "0.38.0" } diff --git a/package.json b/package.json index 6a1f68df..97ff455d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.37.0", + "version": "0.38.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 16bacf66..723001a9 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.37.0'; // x-release-please-version +export const VERSION = '0.38.0'; // x-release-please-version From d2f84f853c66312eabd468c69e6120ee94be55cb Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 25 Feb 2026 22:42:56 +0000 Subject: [PATCH 310/551] feat: Add proxy hostname bypass hosts --- .stats.yml | 4 ++-- src/resources/proxies.ts | 25 +++++++++++++++++++++++++ tests/api-resources/proxies.test.ts | 1 + 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 3e385c42..9538870c 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 101 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-9462b3d8f055f8bda06da65583f5aa09a17d35254c5983796d8e84ebb3c62c47.yml -openapi_spec_hash: 1914dd35b8e0e5a21ccec91eac2a616d +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-d53de581fcac5c3b06940fc93667b9cd2a6a60dd3674da7c1f47484b0f442bf8.yml +openapi_spec_hash: 177d0c537b7e5357c815bb64175e6484 config_hash: c6b88eea9a15840f26130eb8ed3b42a0 diff --git a/src/resources/proxies.ts b/src/resources/proxies.ts index f30203fb..7174a6f7 100644 --- a/src/resources/proxies.ts +++ b/src/resources/proxies.ts @@ -58,6 +58,11 @@ export interface ProxyCreateResponse { id?: string; + /** + * Hostnames that should bypass the parent proxy and connect directly. + */ + bypass_hosts?: Array; + /** * Configuration specific to the selected proxy `type`. */ @@ -283,6 +288,11 @@ export interface ProxyRetrieveResponse { id?: string; + /** + * Hostnames that should bypass the parent proxy and connect directly. + */ + bypass_hosts?: Array; + /** * Configuration specific to the selected proxy `type`. */ @@ -511,6 +521,11 @@ export namespace ProxyListResponse { id?: string; + /** + * Hostnames that should bypass the parent proxy and connect directly. + */ + bypass_hosts?: Array; + /** * Configuration specific to the selected proxy `type`. */ @@ -737,6 +752,11 @@ export interface ProxyCheckResponse { id?: string; + /** + * Hostnames that should bypass the parent proxy and connect directly. + */ + bypass_hosts?: Array; + /** * Configuration specific to the selected proxy `type`. */ @@ -957,6 +977,11 @@ export interface ProxyCreateParams { */ type: 'datacenter' | 'isp' | 'residential' | 'mobile' | 'custom'; + /** + * Hostnames that should bypass the parent proxy and connect directly. + */ + bypass_hosts?: Array; + /** * Configuration specific to the selected proxy `type`. */ diff --git a/tests/api-resources/proxies.test.ts b/tests/api-resources/proxies.test.ts index aa1f0529..237c7dc4 100644 --- a/tests/api-resources/proxies.test.ts +++ b/tests/api-resources/proxies.test.ts @@ -24,6 +24,7 @@ describe('resource proxies', () => { test.skip('create: required and optional params', async () => { const response = await client.proxies.create({ type: 'datacenter', + bypass_hosts: ['string'], config: { country: 'US' }, name: 'name', protocol: 'http', From df099e3bc0b3e2ea7c28bca844f4d63b3b625cc1 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 25 Feb 2026 22:45:17 +0000 Subject: [PATCH 311/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index bc86e4a2..418b49e9 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.38.0" + ".": "0.39.0" } diff --git a/package.json b/package.json index 97ff455d..468d3bd8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.38.0", + "version": "0.39.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 723001a9..5f972a92 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.38.0'; // x-release-please-version +export const VERSION = '0.39.0'; // x-release-please-version From e21107f8190e45c08b5f78648ab1c8f49bd7012f Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 26 Feb 2026 21:22:24 +0000 Subject: [PATCH 312/551] feat: show pool browsers in dashboard and API --- .stats.yml | 6 ++--- api.md | 1 + src/client.ts | 2 ++ src/resources/browser-pools.ts | 5 +++++ src/resources/browsers/browsers.ts | 36 ++++++++++++++++++++++++++++++ src/resources/browsers/index.ts | 1 + src/resources/index.ts | 1 + src/resources/invocations.ts | 5 +++++ 8 files changed, 54 insertions(+), 3 deletions(-) diff --git a/.stats.yml b/.stats.yml index 9538870c..49cb307e 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 101 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-d53de581fcac5c3b06940fc93667b9cd2a6a60dd3674da7c1f47484b0f442bf8.yml -openapi_spec_hash: 177d0c537b7e5357c815bb64175e6484 -config_hash: c6b88eea9a15840f26130eb8ed3b42a0 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-e6e88da6e6fffe12873a108ca33ebfbd59b85232078ab0e4dca5c8273c131053.yml +openapi_spec_hash: 4f22b8ec1d048cc74a751e3ab39b943c +config_hash: 6bac5bbe5d5fc26e0912e33f646adb14 diff --git a/api.md b/api.md index a29d404f..672004f7 100644 --- a/api.md +++ b/api.md @@ -67,6 +67,7 @@ Methods: Types: - BrowserPersistence +- BrowserPoolRef - Profile - BrowserCreateResponse - BrowserRetrieveResponse diff --git a/src/client.ts b/src/client.ts index 1c260a2a..cf295dc6 100644 --- a/src/client.ts +++ b/src/client.ts @@ -106,6 +106,7 @@ import { BrowserListResponsesOffsetPagination, BrowserLoadExtensionsParams, BrowserPersistence, + BrowserPoolRef, BrowserRetrieveParams, BrowserRetrieveResponse, BrowserUpdateParams, @@ -946,6 +947,7 @@ export declare namespace Kernel { export { Browsers as Browsers, type BrowserPersistence as BrowserPersistence, + type BrowserPoolRef as BrowserPoolRef, type Profile as Profile, type BrowserCreateResponse as BrowserCreateResponse, type BrowserRetrieveResponse as BrowserRetrieveResponse, diff --git a/src/resources/browser-pools.ts b/src/resources/browser-pools.ts index e71d7be1..a2544fa4 100644 --- a/src/resources/browser-pools.ts +++ b/src/resources/browser-pools.ts @@ -312,6 +312,11 @@ export interface BrowserPoolAcquireResponse { */ persistence?: BrowsersAPI.BrowserPersistence; + /** + * Browser pool this session was acquired from, if any. + */ + pool?: BrowsersAPI.BrowserPoolRef; + /** * Browser profile metadata. */ diff --git a/src/resources/browsers/browsers.ts b/src/resources/browsers/browsers.ts index 34f21a52..5d575766 100644 --- a/src/resources/browsers/browsers.ts +++ b/src/resources/browsers/browsers.ts @@ -222,6 +222,21 @@ export interface BrowserPersistence { id: string; } +/** + * Browser pool this session was acquired from, if any. + */ +export interface BrowserPoolRef { + /** + * Browser pool ID + */ + id: string; + + /** + * Browser pool name, if set + */ + name?: string; +} + /** * Browser profile metadata. */ @@ -310,6 +325,11 @@ export interface BrowserCreateResponse { */ persistence?: BrowserPersistence; + /** + * Browser pool this session was acquired from, if any. + */ + pool?: BrowserPoolRef; + /** * Browser profile metadata. */ @@ -391,6 +411,11 @@ export interface BrowserRetrieveResponse { */ persistence?: BrowserPersistence; + /** + * Browser pool this session was acquired from, if any. + */ + pool?: BrowserPoolRef; + /** * Browser profile metadata. */ @@ -472,6 +497,11 @@ export interface BrowserUpdateResponse { */ persistence?: BrowserPersistence; + /** + * Browser pool this session was acquired from, if any. + */ + pool?: BrowserPoolRef; + /** * Browser profile metadata. */ @@ -553,6 +583,11 @@ export interface BrowserListResponse { */ persistence?: BrowserPersistence; + /** + * Browser pool this session was acquired from, if any. + */ + pool?: BrowserPoolRef; + /** * Browser profile metadata. */ @@ -736,6 +771,7 @@ Browsers.Playwright = Playwright; export declare namespace Browsers { export { type BrowserPersistence as BrowserPersistence, + type BrowserPoolRef as BrowserPoolRef, type Profile as Profile, type BrowserCreateResponse as BrowserCreateResponse, type BrowserRetrieveResponse as BrowserRetrieveResponse, diff --git a/src/resources/browsers/index.ts b/src/resources/browsers/index.ts index 1f4ef2be..2a727dad 100644 --- a/src/resources/browsers/index.ts +++ b/src/resources/browsers/index.ts @@ -3,6 +3,7 @@ export { Browsers, type BrowserPersistence, + type BrowserPoolRef, type Profile, type BrowserCreateResponse, type BrowserRetrieveResponse, diff --git a/src/resources/index.ts b/src/resources/index.ts index dcf5550b..552043a8 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -22,6 +22,7 @@ export { export { Browsers, type BrowserPersistence, + type BrowserPoolRef, type Profile, type BrowserCreateResponse, type BrowserRetrieveResponse, diff --git a/src/resources/invocations.ts b/src/resources/invocations.ts index d75c9f39..1e5cb0f1 100644 --- a/src/resources/invocations.ts +++ b/src/resources/invocations.ts @@ -472,6 +472,11 @@ export namespace InvocationListBrowsersResponse { */ persistence?: BrowsersAPI.BrowserPersistence; + /** + * Browser pool this session was acquired from, if any. + */ + pool?: BrowsersAPI.BrowserPoolRef; + /** * Browser profile metadata. */ From 1b7ee2f81e67621a7dc9a50f16730c4c9b201532 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 26 Feb 2026 21:29:47 +0000 Subject: [PATCH 313/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 418b49e9..65078153 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.39.0" + ".": "0.40.0" } diff --git a/package.json b/package.json index 468d3bd8..7037bdd0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.39.0", + "version": "0.40.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 5f972a92..c17cceec 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.39.0'; // x-release-please-version +export const VERSION = '0.40.0'; // x-release-please-version From f28a7fcb6516c97318ed9bc2e5bbb350701f30ed Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 27 Feb 2026 00:47:11 +0000 Subject: [PATCH 314/551] feat: Return uptime_ms for deleted browser sessions --- .stats.yml | 6 +++--- api.md | 1 + src/client.ts | 2 ++ src/resources/browser-pools.ts | 5 +++++ src/resources/browsers/browsers.ts | 31 ++++++++++++++++++++++++++++++ src/resources/browsers/index.ts | 1 + src/resources/index.ts | 1 + src/resources/invocations.ts | 5 +++++ 8 files changed, 49 insertions(+), 3 deletions(-) diff --git a/.stats.yml b/.stats.yml index 49cb307e..4e3164c9 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 101 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-e6e88da6e6fffe12873a108ca33ebfbd59b85232078ab0e4dca5c8273c131053.yml -openapi_spec_hash: 4f22b8ec1d048cc74a751e3ab39b943c -config_hash: 6bac5bbe5d5fc26e0912e33f646adb14 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-586ddc36cd621b3705138de66a0e7d28d1c1485064aa85ce09ce24edb50003ef.yml +openapi_spec_hash: 8e8d4bd31e4920303e7ec9ce313fb1ec +config_hash: 81f143f4bee47ae7b0b8357551babadf diff --git a/api.md b/api.md index 672004f7..d791b834 100644 --- a/api.md +++ b/api.md @@ -68,6 +68,7 @@ Types: - BrowserPersistence - BrowserPoolRef +- BrowserUsage - Profile - BrowserCreateResponse - BrowserRetrieveResponse diff --git a/src/client.ts b/src/client.ts index cf295dc6..cb887e0a 100644 --- a/src/client.ts +++ b/src/client.ts @@ -111,6 +111,7 @@ import { BrowserRetrieveResponse, BrowserUpdateParams, BrowserUpdateResponse, + BrowserUsage, Browsers, Profile, } from './resources/browsers/browsers'; @@ -948,6 +949,7 @@ export declare namespace Kernel { Browsers as Browsers, type BrowserPersistence as BrowserPersistence, type BrowserPoolRef as BrowserPoolRef, + type BrowserUsage as BrowserUsage, type Profile as Profile, type BrowserCreateResponse as BrowserCreateResponse, type BrowserRetrieveResponse as BrowserRetrieveResponse, diff --git a/src/resources/browser-pools.ts b/src/resources/browser-pools.ts index a2544fa4..0494b0bb 100644 --- a/src/resources/browser-pools.ts +++ b/src/resources/browser-pools.ts @@ -327,6 +327,11 @@ export interface BrowserPoolAcquireResponse { */ proxy_id?: string; + /** + * Session usage metrics. + */ + usage?: BrowsersAPI.BrowserUsage; + /** * Initial browser window size in pixels with optional refresh rate. If omitted, * image defaults apply (1920x1080@25). Arbitrary viewport dimensions are accepted, diff --git a/src/resources/browsers/browsers.ts b/src/resources/browsers/browsers.ts index 5d575766..43503a58 100644 --- a/src/resources/browsers/browsers.ts +++ b/src/resources/browsers/browsers.ts @@ -237,6 +237,16 @@ export interface BrowserPoolRef { name?: string; } +/** + * Session usage metrics. + */ +export interface BrowserUsage { + /** + * Time in milliseconds the session was actively running. + */ + uptime_ms: number; +} + /** * Browser profile metadata. */ @@ -340,6 +350,11 @@ export interface BrowserCreateResponse { */ proxy_id?: string; + /** + * Session usage metrics. + */ + usage?: BrowserUsage; + /** * Initial browser window size in pixels with optional refresh rate. If omitted, * image defaults apply (1920x1080@25). Arbitrary viewport dimensions are accepted, @@ -426,6 +441,11 @@ export interface BrowserRetrieveResponse { */ proxy_id?: string; + /** + * Session usage metrics. + */ + usage?: BrowserUsage; + /** * Initial browser window size in pixels with optional refresh rate. If omitted, * image defaults apply (1920x1080@25). Arbitrary viewport dimensions are accepted, @@ -512,6 +532,11 @@ export interface BrowserUpdateResponse { */ proxy_id?: string; + /** + * Session usage metrics. + */ + usage?: BrowserUsage; + /** * Initial browser window size in pixels with optional refresh rate. If omitted, * image defaults apply (1920x1080@25). Arbitrary viewport dimensions are accepted, @@ -598,6 +623,11 @@ export interface BrowserListResponse { */ proxy_id?: string; + /** + * Session usage metrics. + */ + usage?: BrowserUsage; + /** * Initial browser window size in pixels with optional refresh rate. If omitted, * image defaults apply (1920x1080@25). Arbitrary viewport dimensions are accepted, @@ -772,6 +802,7 @@ export declare namespace Browsers { export { type BrowserPersistence as BrowserPersistence, type BrowserPoolRef as BrowserPoolRef, + type BrowserUsage as BrowserUsage, type Profile as Profile, type BrowserCreateResponse as BrowserCreateResponse, type BrowserRetrieveResponse as BrowserRetrieveResponse, diff --git a/src/resources/browsers/index.ts b/src/resources/browsers/index.ts index 2a727dad..44d503cb 100644 --- a/src/resources/browsers/index.ts +++ b/src/resources/browsers/index.ts @@ -4,6 +4,7 @@ export { Browsers, type BrowserPersistence, type BrowserPoolRef, + type BrowserUsage, type Profile, type BrowserCreateResponse, type BrowserRetrieveResponse, diff --git a/src/resources/index.ts b/src/resources/index.ts index 552043a8..18963e71 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -23,6 +23,7 @@ export { Browsers, type BrowserPersistence, type BrowserPoolRef, + type BrowserUsage, type Profile, type BrowserCreateResponse, type BrowserRetrieveResponse, diff --git a/src/resources/invocations.ts b/src/resources/invocations.ts index 1e5cb0f1..eb85200f 100644 --- a/src/resources/invocations.ts +++ b/src/resources/invocations.ts @@ -487,6 +487,11 @@ export namespace InvocationListBrowsersResponse { */ proxy_id?: string; + /** + * Session usage metrics. + */ + usage?: BrowsersAPI.BrowserUsage; + /** * Initial browser window size in pixels with optional refresh rate. If omitted, * image defaults apply (1920x1080@25). Arbitrary viewport dimensions are accepted, From 6c931bf87e54812be488804606d9c0d1f17312f0 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 27 Feb 2026 01:02:58 +0000 Subject: [PATCH 315/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 65078153..dbe1b2bf 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.40.0" + ".": "0.41.0" } diff --git a/package.json b/package.json index 7037bdd0..fa1d04a9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.40.0", + "version": "0.41.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index c17cceec..2f1576d5 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.40.0'; // x-release-please-version +export const VERSION = '0.41.0'; // x-release-please-version From 19d9d2ab02f89570efbd9ac62ccc1f1e730cff55 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 27 Feb 2026 04:10:16 +0000 Subject: [PATCH 316/551] chore(internal): move stringifyQuery implementation to internal function --- src/client.ts | 22 +++++----------------- src/internal/utils.ts | 1 + src/internal/utils/query.ts | 23 +++++++++++++++++++++++ tests/stringifyQuery.test.ts | 6 ++---- 4 files changed, 31 insertions(+), 21 deletions(-) create mode 100644 src/internal/utils/query.ts diff --git a/src/client.ts b/src/client.ts index cb887e0a..c6ffab72 100644 --- a/src/client.ts +++ b/src/client.ts @@ -11,6 +11,7 @@ import type { APIResponseProps } from './internal/parse'; import { getPlatformHeaders } from './internal/detect-platform'; import * as Shims from './internal/shims'; import * as Opts from './internal/request-options'; +import { stringifyQuery } from './internal/utils/query'; import { VERSION } from './version'; import * as Errors from './core/error'; import * as Pagination from './core/pagination'; @@ -335,21 +336,8 @@ export class Kernel { /** * Basic re-implementation of `qs.stringify` for primitive types. */ - protected stringifyQuery(query: Record): string { - return Object.entries(query) - .filter(([_, value]) => typeof value !== 'undefined') - .map(([key, value]) => { - if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') { - return `${encodeURIComponent(key)}=${encodeURIComponent(value)}`; - } - if (value === null) { - return `${encodeURIComponent(key)}=`; - } - throw new Errors.KernelError( - `Cannot stringify type ${typeof value}; Expected string, number, boolean, or null. If you need to pass nested query parameters, you can manually encode them, e.g. { query: { 'foo[key1]': value1, 'foo[key2]': value2 } }, and please open a GitHub issue requesting better support for your use case.`, - ); - }) - .join('&'); + protected stringifyQuery(query: object | Record): string { + return stringifyQuery(query); } private getUserAgent(): string { @@ -386,7 +374,7 @@ export class Kernel { } if (typeof query === 'object' && query && !Array.isArray(query)) { - url.search = this.stringifyQuery(query as Record); + url.search = this.stringifyQuery(query); } return url.toString(); @@ -849,7 +837,7 @@ export class Kernel { ) { return { bodyHeaders: { 'content-type': 'application/x-www-form-urlencoded' }, - body: this.stringifyQuery(body as Record), + body: this.stringifyQuery(body), }; } else { return this.#encoder({ body, headers }); diff --git a/src/internal/utils.ts b/src/internal/utils.ts index 3cbfacce..c591353b 100644 --- a/src/internal/utils.ts +++ b/src/internal/utils.ts @@ -6,3 +6,4 @@ export * from './utils/env'; export * from './utils/log'; export * from './utils/uuid'; export * from './utils/sleep'; +export * from './utils/query'; diff --git a/src/internal/utils/query.ts b/src/internal/utils/query.ts new file mode 100644 index 00000000..50550d3c --- /dev/null +++ b/src/internal/utils/query.ts @@ -0,0 +1,23 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { KernelError } from '../../core/error'; + +/** + * Basic re-implementation of `qs.stringify` for primitive types. + */ +export function stringifyQuery(query: object | Record) { + return Object.entries(query) + .filter(([_, value]) => typeof value !== 'undefined') + .map(([key, value]) => { + if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') { + return `${encodeURIComponent(key)}=${encodeURIComponent(value)}`; + } + if (value === null) { + return `${encodeURIComponent(key)}=`; + } + throw new KernelError( + `Cannot stringify type ${typeof value}; Expected string, number, boolean, or null. If you need to pass nested query parameters, you can manually encode them, e.g. { query: { 'foo[key1]': value1, 'foo[key2]': value2 } }, and please open a GitHub issue requesting better support for your use case.`, + ); + }) + .join('&'); +} diff --git a/tests/stringifyQuery.test.ts b/tests/stringifyQuery.test.ts index 1170f010..dedd39a7 100644 --- a/tests/stringifyQuery.test.ts +++ b/tests/stringifyQuery.test.ts @@ -1,8 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { Kernel } from '@onkernel/sdk'; - -const { stringifyQuery } = Kernel.prototype as any; +import { stringifyQuery } from '@onkernel/sdk/internal/utils/query'; describe(stringifyQuery, () => { for (const [input, expected] of [ @@ -15,7 +13,7 @@ describe(stringifyQuery, () => { 'e=f', )}=${encodeURIComponent('g&h')}`, ], - ]) { + ] as const) { it(`${JSON.stringify(input)} -> ${expected}`, () => { expect(stringifyQuery(input)).toEqual(expected); }); From 4db7047252df955c7cfaba08d770ec099f1d9a26 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 2 Mar 2026 21:41:22 +0000 Subject: [PATCH 317/551] feat: Neil/kernel 1052 deployments list endpoint --- .stats.yml | 4 ++-- src/resources/apps.ts | 5 +++++ tests/api-resources/apps.test.ts | 1 + 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 4e3164c9..d4eead98 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 101 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-586ddc36cd621b3705138de66a0e7d28d1c1485064aa85ce09ce24edb50003ef.yml -openapi_spec_hash: 8e8d4bd31e4920303e7ec9ce313fb1ec +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-a935c8aae21f8ddb83ea5e289034df12cbde88d432fa2b287629814bb3f58bb6.yml +openapi_spec_hash: df3189b9728372f01662a19c060bcbc5 config_hash: 81f143f4bee47ae7b0b8357551babadf diff --git a/src/resources/apps.ts b/src/resources/apps.ts index c523e2b6..6dbd7a09 100644 --- a/src/resources/apps.ts +++ b/src/resources/apps.ts @@ -65,6 +65,11 @@ export interface AppListParams extends OffsetPaginationParams { */ app_name?: string; + /** + * Search apps by name. + */ + query?: string; + /** * Filter results by version label. */ diff --git a/tests/api-resources/apps.test.ts b/tests/api-resources/apps.test.ts index 07b6bf0e..a27f4650 100644 --- a/tests/api-resources/apps.test.ts +++ b/tests/api-resources/apps.test.ts @@ -29,6 +29,7 @@ describe('resource apps', () => { app_name: 'app_name', limit: 1, offset: 0, + query: 'query', version: 'version', }, { path: '/_stainless_unknown_path' }, From e780ce471cce3bfdedd26938bde04495bcc9a3e7 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 2 Mar 2026 21:50:06 +0000 Subject: [PATCH 318/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index dbe1b2bf..57953081 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.41.0" + ".": "0.42.0" } diff --git a/package.json b/package.json index fa1d04a9..ce5e825a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.41.0", + "version": "0.42.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 2f1576d5..e0134176 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.41.0'; // x-release-please-version +export const VERSION = '0.42.0'; // x-release-please-version From 637f8da5917dd1b52a5b566607e06f7eb9740d7c Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 3 Mar 2026 03:49:10 +0000 Subject: [PATCH 319/551] chore(internal): codegen related update --- src/client.ts | 30 +++++++++++++++++++++++++++ src/resources/apps.ts | 3 +++ src/resources/auth/connections.ts | 3 +++ src/resources/browser-pools.ts | 3 +++ src/resources/browsers/browsers.ts | 3 +++ src/resources/browsers/fs/fs.ts | 3 +++ src/resources/browsers/fs/watch.ts | 3 +++ src/resources/browsers/logs.ts | 3 +++ src/resources/browsers/playwright.ts | 3 +++ src/resources/browsers/process.ts | 3 +++ src/resources/browsers/replays.ts | 3 +++ src/resources/credential-providers.ts | 3 +++ src/resources/credentials.ts | 3 +++ src/resources/deployments.ts | 3 +++ src/resources/extensions.ts | 3 +++ src/resources/invocations.ts | 3 +++ src/resources/profiles.ts | 3 +++ src/resources/proxies.ts | 3 +++ 18 files changed, 81 insertions(+) diff --git a/src/client.ts b/src/client.ts index c6ffab72..47a5bb19 100644 --- a/src/client.ts +++ b/src/client.ts @@ -863,16 +863,46 @@ export class Kernel { static toFile = Uploads.toFile; + /** + * Create and manage app deployments and stream deployment events. + */ deployments: API.Deployments = new API.Deployments(this); + /** + * List applications and versions. + */ apps: API.Apps = new API.Apps(this); + /** + * Invoke actions and stream or query invocation status and events. + */ invocations: API.Invocations = new API.Invocations(this); + /** + * Create and manage browser sessions. + */ browsers: API.Browsers = new API.Browsers(this); + /** + * Create, list, retrieve, and delete browser profiles. + */ profiles: API.Profiles = new API.Profiles(this); auth: API.Auth = new API.Auth(this); + /** + * Create and manage proxy configurations for routing browser traffic. + */ proxies: API.Proxies = new API.Proxies(this); + /** + * Create, list, retrieve, and delete browser extensions. + */ extensions: API.Extensions = new API.Extensions(this); + /** + * Create and manage browser pools for acquiring and releasing browsers. + */ browserPools: API.BrowserPools = new API.BrowserPools(this); + /** + * Create and manage credentials for authentication. + */ credentials: API.Credentials = new API.Credentials(this); + /** + * Configure external credential providers like 1Password. + */ credentialProviders: API.CredentialProviders = new API.CredentialProviders(this); } diff --git a/src/resources/apps.ts b/src/resources/apps.ts index 6dbd7a09..915193db 100644 --- a/src/resources/apps.ts +++ b/src/resources/apps.ts @@ -5,6 +5,9 @@ import * as Shared from './shared'; import { OffsetPagination, type OffsetPaginationParams, PagePromise } from '../core/pagination'; import { RequestOptions } from '../internal/request-options'; +/** + * List applications and versions. + */ export class Apps extends APIResource { /** * List applications. Optionally filter by app name and/or version label. diff --git a/src/resources/auth/connections.ts b/src/resources/auth/connections.ts index 6a418460..6f4dc1bf 100644 --- a/src/resources/auth/connections.ts +++ b/src/resources/auth/connections.ts @@ -9,6 +9,9 @@ import { buildHeaders } from '../../internal/headers'; import { RequestOptions } from '../../internal/request-options'; import { path } from '../../internal/utils/path'; +/** + * Create and manage auth connections for automated credential capture and login. + */ export class Connections extends APIResource { /** * Creates an auth connection for a profile and domain combination. Returns 409 diff --git a/src/resources/browser-pools.ts b/src/resources/browser-pools.ts index 0494b0bb..3dd44263 100644 --- a/src/resources/browser-pools.ts +++ b/src/resources/browser-pools.ts @@ -8,6 +8,9 @@ import { buildHeaders } from '../internal/headers'; import { RequestOptions } from '../internal/request-options'; import { path } from '../internal/utils/path'; +/** + * Create and manage browser pools for acquiring and releasing browsers. + */ export class BrowserPools extends APIResource { /** * Create a new browser pool with the specified configuration and size. diff --git a/src/resources/browsers/browsers.ts b/src/resources/browsers/browsers.ts index 43503a58..5c0e2c2b 100644 --- a/src/resources/browsers/browsers.ts +++ b/src/resources/browsers/browsers.ts @@ -74,6 +74,9 @@ import { RequestOptions } from '../../internal/request-options'; import { multipartFormRequestOptions } from '../../internal/uploads'; import { path } from '../../internal/utils/path'; +/** + * Create and manage browser sessions. + */ export class Browsers extends APIResource { replays: ReplaysAPI.Replays = new ReplaysAPI.Replays(this._client); fs: FsAPI.Fs = new FsAPI.Fs(this._client); diff --git a/src/resources/browsers/fs/fs.ts b/src/resources/browsers/fs/fs.ts index b6adb02e..4e03aa75 100644 --- a/src/resources/browsers/fs/fs.ts +++ b/src/resources/browsers/fs/fs.ts @@ -17,6 +17,9 @@ import { RequestOptions } from '../../../internal/request-options'; import { multipartFormRequestOptions } from '../../../internal/uploads'; import { path } from '../../../internal/utils/path'; +/** + * Read, write, and manage files on the browser instance. + */ export class Fs extends APIResource { watch: WatchAPI.Watch = new WatchAPI.Watch(this._client); diff --git a/src/resources/browsers/fs/watch.ts b/src/resources/browsers/fs/watch.ts index b0cc18c6..41b5b439 100644 --- a/src/resources/browsers/fs/watch.ts +++ b/src/resources/browsers/fs/watch.ts @@ -7,6 +7,9 @@ import { buildHeaders } from '../../../internal/headers'; import { RequestOptions } from '../../../internal/request-options'; import { path } from '../../../internal/utils/path'; +/** + * Read, write, and manage files on the browser instance. + */ export class Watch extends APIResource { /** * Stream filesystem events for a watch diff --git a/src/resources/browsers/logs.ts b/src/resources/browsers/logs.ts index 485f9d7c..13511b10 100644 --- a/src/resources/browsers/logs.ts +++ b/src/resources/browsers/logs.ts @@ -8,6 +8,9 @@ import { buildHeaders } from '../../internal/headers'; import { RequestOptions } from '../../internal/request-options'; import { path } from '../../internal/utils/path'; +/** + * Stream logs from the browser instance. + */ export class Logs extends APIResource { /** * Stream log files on the browser instance via SSE diff --git a/src/resources/browsers/playwright.ts b/src/resources/browsers/playwright.ts index bd99c520..022ccc7f 100644 --- a/src/resources/browsers/playwright.ts +++ b/src/resources/browsers/playwright.ts @@ -5,6 +5,9 @@ import { APIPromise } from '../../core/api-promise'; import { RequestOptions } from '../../internal/request-options'; import { path } from '../../internal/utils/path'; +/** + * Execute Playwright code against the browser instance. + */ export class Playwright extends APIResource { /** * Execute arbitrary Playwright code in a fresh execution context against the diff --git a/src/resources/browsers/process.ts b/src/resources/browsers/process.ts index a19f8b95..40e04f0a 100644 --- a/src/resources/browsers/process.ts +++ b/src/resources/browsers/process.ts @@ -7,6 +7,9 @@ import { buildHeaders } from '../../internal/headers'; import { RequestOptions } from '../../internal/request-options'; import { path } from '../../internal/utils/path'; +/** + * Execute and manage processes on the browser instance. + */ export class Process extends APIResource { /** * Execute a command synchronously diff --git a/src/resources/browsers/replays.ts b/src/resources/browsers/replays.ts index 208d8c37..7ac768d9 100644 --- a/src/resources/browsers/replays.ts +++ b/src/resources/browsers/replays.ts @@ -6,6 +6,9 @@ import { buildHeaders } from '../../internal/headers'; import { RequestOptions } from '../../internal/request-options'; import { path } from '../../internal/utils/path'; +/** + * Record and manage browser session video replays. + */ export class Replays extends APIResource { /** * List all replays for the specified browser session. diff --git a/src/resources/credential-providers.ts b/src/resources/credential-providers.ts index 42733a97..091015c6 100644 --- a/src/resources/credential-providers.ts +++ b/src/resources/credential-providers.ts @@ -6,6 +6,9 @@ import { buildHeaders } from '../internal/headers'; import { RequestOptions } from '../internal/request-options'; import { path } from '../internal/utils/path'; +/** + * Configure external credential providers like 1Password. + */ export class CredentialProviders extends APIResource { /** * Configure an external credential provider (e.g., 1Password) for automatic diff --git a/src/resources/credentials.ts b/src/resources/credentials.ts index 98b7df8a..5ae00211 100644 --- a/src/resources/credentials.ts +++ b/src/resources/credentials.ts @@ -7,6 +7,9 @@ import { buildHeaders } from '../internal/headers'; import { RequestOptions } from '../internal/request-options'; import { path } from '../internal/utils/path'; +/** + * Create and manage credentials for authentication. + */ export class Credentials extends APIResource { /** * Create a new credential for storing login information. diff --git a/src/resources/deployments.ts b/src/resources/deployments.ts index 5f277da9..8ea9843e 100644 --- a/src/resources/deployments.ts +++ b/src/resources/deployments.ts @@ -11,6 +11,9 @@ import { RequestOptions } from '../internal/request-options'; import { multipartFormRequestOptions } from '../internal/uploads'; import { path } from '../internal/utils/path'; +/** + * Create and manage app deployments and stream deployment events. + */ export class Deployments extends APIResource { /** * Create a new deployment. diff --git a/src/resources/extensions.ts b/src/resources/extensions.ts index 5697a075..b28eb86e 100644 --- a/src/resources/extensions.ts +++ b/src/resources/extensions.ts @@ -8,6 +8,9 @@ import { RequestOptions } from '../internal/request-options'; import { multipartFormRequestOptions } from '../internal/uploads'; import { path } from '../internal/utils/path'; +/** + * Create, list, retrieve, and delete browser extensions. + */ export class Extensions extends APIResource { /** * List extensions owned by the caller's organization. diff --git a/src/resources/invocations.ts b/src/resources/invocations.ts index eb85200f..b48c129f 100644 --- a/src/resources/invocations.ts +++ b/src/resources/invocations.ts @@ -10,6 +10,9 @@ import { buildHeaders } from '../internal/headers'; import { RequestOptions } from '../internal/request-options'; import { path } from '../internal/utils/path'; +/** + * Invoke actions and stream or query invocation status and events. + */ export class Invocations extends APIResource { /** * Invoke an action. diff --git a/src/resources/profiles.ts b/src/resources/profiles.ts index 2a3c613d..4b9345c2 100644 --- a/src/resources/profiles.ts +++ b/src/resources/profiles.ts @@ -9,6 +9,9 @@ import { buildHeaders } from '../internal/headers'; import { RequestOptions } from '../internal/request-options'; import { path } from '../internal/utils/path'; +/** + * Create, list, retrieve, and delete browser profiles. + */ export class Profiles extends APIResource { /** * Create a browser profile that can be used to load state into future browser diff --git a/src/resources/proxies.ts b/src/resources/proxies.ts index 7174a6f7..0e0d271e 100644 --- a/src/resources/proxies.ts +++ b/src/resources/proxies.ts @@ -6,6 +6,9 @@ import { buildHeaders } from '../internal/headers'; import { RequestOptions } from '../internal/request-options'; import { path } from '../internal/utils/path'; +/** + * Create and manage proxy configurations for routing browser traffic. + */ export class Proxies extends APIResource { /** * Create a new proxy configuration for the caller's organization. From 78218d31ec255556fb9baaedce4d3211e68697e7 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 3 Mar 2026 18:32:34 +0000 Subject: [PATCH 320/551] feat: [kernel-1028] add api clipboard support --- .stats.yml | 8 ++-- api.md | 3 ++ src/resources/browsers/browsers.ts | 4 ++ src/resources/browsers/computer.ts | 47 +++++++++++++++++++ src/resources/browsers/index.ts | 2 + tests/api-resources/browsers/computer.test.ts | 29 ++++++++++++ 6 files changed, 89 insertions(+), 4 deletions(-) diff --git a/.stats.yml b/.stats.yml index d4eead98..a08c103b 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 101 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-a935c8aae21f8ddb83ea5e289034df12cbde88d432fa2b287629814bb3f58bb6.yml -openapi_spec_hash: df3189b9728372f01662a19c060bcbc5 -config_hash: 81f143f4bee47ae7b0b8357551babadf +configured_endpoints: 103 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-f05b888046776a18dbffc1264a27c0256839d132066ef5f6e09ccf1bc505a8f7.yml +openapi_spec_hash: 646fce3982d3efbdb38004b0e4ac4d17 +config_hash: cff4d43372b6fa66b64e2d4150f6aa76 diff --git a/api.md b/api.md index d791b834..efe009c9 100644 --- a/api.md +++ b/api.md @@ -167,6 +167,7 @@ Methods: Types: - ComputerGetMousePositionResponse +- ComputerReadClipboardResponse - ComputerSetCursorVisibilityResponse Methods: @@ -178,9 +179,11 @@ Methods: - client.browsers.computer.getMousePosition(id) -> ComputerGetMousePositionResponse - client.browsers.computer.moveMouse(id, { ...params }) -> void - client.browsers.computer.pressKey(id, { ...params }) -> void +- client.browsers.computer.readClipboard(id) -> ComputerReadClipboardResponse - client.browsers.computer.scroll(id, { ...params }) -> void - client.browsers.computer.setCursorVisibility(id, { ...params }) -> ComputerSetCursorVisibilityResponse - client.browsers.computer.typeText(id, { ...params }) -> void +- client.browsers.computer.writeClipboard(id, { ...params }) -> void ## Playwright diff --git a/src/resources/browsers/browsers.ts b/src/resources/browsers/browsers.ts index 5c0e2c2b..2e1f8072 100644 --- a/src/resources/browsers/browsers.ts +++ b/src/resources/browsers/browsers.ts @@ -12,10 +12,12 @@ import { ComputerGetMousePositionResponse, ComputerMoveMouseParams, ComputerPressKeyParams, + ComputerReadClipboardResponse, ComputerScrollParams, ComputerSetCursorVisibilityParams, ComputerSetCursorVisibilityResponse, ComputerTypeTextParams, + ComputerWriteClipboardParams, } from './computer'; import * as LogsAPI from './logs'; import { LogStreamParams, Logs } from './logs'; @@ -870,6 +872,7 @@ export declare namespace Browsers { export { Computer as Computer, type ComputerGetMousePositionResponse as ComputerGetMousePositionResponse, + type ComputerReadClipboardResponse as ComputerReadClipboardResponse, type ComputerSetCursorVisibilityResponse as ComputerSetCursorVisibilityResponse, type ComputerBatchParams as ComputerBatchParams, type ComputerCaptureScreenshotParams as ComputerCaptureScreenshotParams, @@ -880,6 +883,7 @@ export declare namespace Browsers { type ComputerScrollParams as ComputerScrollParams, type ComputerSetCursorVisibilityParams as ComputerSetCursorVisibilityParams, type ComputerTypeTextParams as ComputerTypeTextParams, + type ComputerWriteClipboardParams as ComputerWriteClipboardParams, }; export { diff --git a/src/resources/browsers/computer.ts b/src/resources/browsers/computer.ts index 6b15782d..3165b880 100644 --- a/src/resources/browsers/computer.ts +++ b/src/resources/browsers/computer.ts @@ -142,6 +142,19 @@ export class Computer extends APIResource { }); } + /** + * Read text from the clipboard on the browser instance + * + * @example + * ```ts + * const response = + * await client.browsers.computer.readClipboard('id'); + * ``` + */ + readClipboard(id: string, options?: RequestOptions): APIPromise { + return this._client.post(path`/browsers/${id}/computer/clipboard/read`, options); + } + /** * Scroll the mouse wheel at a position on the host computer * @@ -194,6 +207,24 @@ export class Computer extends APIResource { headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), }); } + + /** + * Write text to the clipboard on the browser instance + * + * @example + * ```ts + * await client.browsers.computer.writeClipboard('id', { + * text: 'text', + * }); + * ``` + */ + writeClipboard(id: string, body: ComputerWriteClipboardParams, options?: RequestOptions): APIPromise { + return this._client.post(path`/browsers/${id}/computer/clipboard/write`, { + body, + ...options, + headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), + }); + } } export interface ComputerGetMousePositionResponse { @@ -208,6 +239,13 @@ export interface ComputerGetMousePositionResponse { y: number; } +export interface ComputerReadClipboardResponse { + /** + * Current clipboard text content + */ + text: string; +} + /** * Generic OK response. */ @@ -606,9 +644,17 @@ export interface ComputerTypeTextParams { delay?: number; } +export interface ComputerWriteClipboardParams { + /** + * Text to write to the system clipboard + */ + text: string; +} + export declare namespace Computer { export { type ComputerGetMousePositionResponse as ComputerGetMousePositionResponse, + type ComputerReadClipboardResponse as ComputerReadClipboardResponse, type ComputerSetCursorVisibilityResponse as ComputerSetCursorVisibilityResponse, type ComputerBatchParams as ComputerBatchParams, type ComputerCaptureScreenshotParams as ComputerCaptureScreenshotParams, @@ -619,5 +665,6 @@ export declare namespace Computer { type ComputerScrollParams as ComputerScrollParams, type ComputerSetCursorVisibilityParams as ComputerSetCursorVisibilityParams, type ComputerTypeTextParams as ComputerTypeTextParams, + type ComputerWriteClipboardParams as ComputerWriteClipboardParams, }; } diff --git a/src/resources/browsers/index.ts b/src/resources/browsers/index.ts index 44d503cb..4af2fb19 100644 --- a/src/resources/browsers/index.ts +++ b/src/resources/browsers/index.ts @@ -22,6 +22,7 @@ export { export { Computer, type ComputerGetMousePositionResponse, + type ComputerReadClipboardResponse, type ComputerSetCursorVisibilityResponse, type ComputerBatchParams, type ComputerCaptureScreenshotParams, @@ -32,6 +33,7 @@ export { type ComputerScrollParams, type ComputerSetCursorVisibilityParams, type ComputerTypeTextParams, + type ComputerWriteClipboardParams, } from './computer'; export { Fs, diff --git a/tests/api-resources/browsers/computer.test.ts b/tests/api-resources/browsers/computer.test.ts index 36b388bf..ec24670f 100644 --- a/tests/api-resources/browsers/computer.test.ts +++ b/tests/api-resources/browsers/computer.test.ts @@ -199,6 +199,18 @@ describe('resource computer', () => { }); }); + // Mock server tests are disabled + test.skip('readClipboard', async () => { + const responsePromise = client.browsers.computer.readClipboard('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); + }); + // Mock server tests are disabled test.skip('scroll: only required params', async () => { const responsePromise = client.browsers.computer.scroll('id', { x: 0, y: 0 }); @@ -255,4 +267,21 @@ describe('resource computer', () => { test.skip('typeText: required and optional params', async () => { const response = await client.browsers.computer.typeText('id', { text: 'text', delay: 0 }); }); + + // Mock server tests are disabled + test.skip('writeClipboard: only required params', async () => { + const responsePromise = client.browsers.computer.writeClipboard('id', { text: 'text' }); + 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); + }); + + // Mock server tests are disabled + test.skip('writeClipboard: required and optional params', async () => { + const response = await client.browsers.computer.writeClipboard('id', { text: 'text' }); + }); }); From 6f692a29b27d6f03fc571a802914f7fd3407560d Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 3 Mar 2026 22:37:29 +0000 Subject: [PATCH 321/551] feat: expose smooth mouse movement via public API --- .stats.yml | 4 ++-- src/resources/browsers/computer.ts | 22 +++++++++++++++++++ tests/api-resources/browsers/computer.test.ts | 4 ++++ 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index a08c103b..d2f972b9 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 103 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-f05b888046776a18dbffc1264a27c0256839d132066ef5f6e09ccf1bc505a8f7.yml -openapi_spec_hash: 646fce3982d3efbdb38004b0e4ac4d17 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-2ba004ce5444b5f8abe3bcf66fd7c6da394bc964e8b2bf197576841135a48046.yml +openapi_spec_hash: f156ea2ae35e4d148704c6e4ce051239 config_hash: cff4d43372b6fa66b64e2d4150f6aa76 diff --git a/src/resources/browsers/computer.ts b/src/resources/browsers/computer.ts index 3165b880..f5ed4d32 100644 --- a/src/resources/browsers/computer.ts +++ b/src/resources/browsers/computer.ts @@ -381,10 +381,21 @@ export namespace ComputerBatchParams { */ y: number; + /** + * Target total duration in milliseconds for the mouse movement when smooth=true. + * Omit for automatic timing based on distance. + */ + duration_ms?: number; + /** * Modifier keys to hold during the move */ hold_keys?: Array; + + /** + * Use human-like Bezier curve path instead of instant mouse movement. + */ + smooth?: boolean; } export interface PressKey { @@ -571,10 +582,21 @@ export interface ComputerMoveMouseParams { */ y: number; + /** + * Target total duration in milliseconds for the mouse movement when smooth=true. + * Omit for automatic timing based on distance. + */ + duration_ms?: number; + /** * Modifier keys to hold during the move */ hold_keys?: Array; + + /** + * Use human-like Bezier curve path instead of instant mouse movement. + */ + smooth?: boolean; } export interface ComputerPressKeyParams { diff --git a/tests/api-resources/browsers/computer.test.ts b/tests/api-resources/browsers/computer.test.ts index ec24670f..ffb2b7d3 100644 --- a/tests/api-resources/browsers/computer.test.ts +++ b/tests/api-resources/browsers/computer.test.ts @@ -48,7 +48,9 @@ describe('resource computer', () => { move_mouse: { x: 0, y: 0, + duration_ms: 50, hold_keys: ['string'], + smooth: true, }, press_key: { keys: ['string'], @@ -174,7 +176,9 @@ describe('resource computer', () => { const response = await client.browsers.computer.moveMouse('id', { x: 0, y: 0, + duration_ms: 50, hold_keys: ['string'], + smooth: true, }); }); From 591bf5bd0e400a9d4f196bbbbaa5d9aaf9184816 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 5 Mar 2026 15:43:04 +0000 Subject: [PATCH 322/551] feat: add force flag to viewport resize to bypass live view/recording check --- .stats.yml | 4 ++-- src/resources/browsers/browsers.ts | 17 ++++++++++++++++- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/.stats.yml b/.stats.yml index d2f972b9..e1ce185b 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 103 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-2ba004ce5444b5f8abe3bcf66fd7c6da394bc964e8b2bf197576841135a48046.yml -openapi_spec_hash: f156ea2ae35e4d148704c6e4ce051239 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-ef24d4bf172555bcbe8e3b432c644a25a1c6afd99c958a2eda8c3b1ea9568113.yml +openapi_spec_hash: b603c5a983e837928fa7d1100ed64fc9 config_hash: cff4d43372b6fa66b64e2d4150f6aa76 diff --git a/src/resources/browsers/browsers.ts b/src/resources/browsers/browsers.ts index 2e1f8072..c008731f 100644 --- a/src/resources/browsers/browsers.ts +++ b/src/resources/browsers/browsers.ts @@ -745,7 +745,22 @@ export interface BrowserUpdateParams { /** * Viewport configuration to apply to the browser session. */ - viewport?: Shared.BrowserViewport; + viewport?: BrowserUpdateParams.Viewport; +} + +export namespace BrowserUpdateParams { + /** + * Viewport configuration to apply to the browser session. + */ + export interface Viewport extends Shared.BrowserViewport { + /** + * If true, allow the viewport change even when a live view or recording/replay is + * active. Active recordings will be gracefully stopped and restarted at the new + * resolution as separate segments. If false (default), the resize is refused when + * a live view or recording is active. + */ + force?: boolean; + } } export interface BrowserListParams extends OffsetPaginationParams { From 46e3d6d00505a550137356f85434f6d7f21c8076 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 5 Mar 2026 16:05:11 +0000 Subject: [PATCH 323/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 57953081..cede7a52 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.42.0" + ".": "0.42.1" } diff --git a/package.json b/package.json index ce5e825a..18c8c5ed 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.42.0", + "version": "0.42.1", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index e0134176..7c38063a 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.42.0'; // x-release-please-version +export const VERSION = '0.42.1'; // x-release-please-version From 79a2d66d7457ad0abe71bdff083a1bc7a5112a1a Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 6 Mar 2026 03:41:36 +0000 Subject: [PATCH 324/551] chore(internal): codegen related update --- src/client.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/client.ts b/src/client.ts index 47a5bb19..6aafef4b 100644 --- a/src/client.ts +++ b/src/client.ts @@ -703,9 +703,9 @@ export class Kernel { } } - // If the API asks us to wait a certain amount of time (and it's a reasonable amount), - // just do what it says, but otherwise calculate a default - if (!(timeoutMillis && 0 <= timeoutMillis && timeoutMillis < 60 * 1000)) { + // If the API asks us to wait a certain amount of time, just do what it + // says, but otherwise calculate a default + if (timeoutMillis === undefined) { const maxRetries = options.maxRetries ?? this.maxRetries; timeoutMillis = this.calculateDefaultRetryTimeoutMillis(retriesRemaining, maxRetries); } From 653f5e8e000d921914057bcacbe8801e5ea1b44b Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 7 Mar 2026 15:44:41 +0000 Subject: [PATCH 325/551] chore(ci): skip uploading artifacts on stainless-internal branches --- .github/workflows/ci.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 230c4adf..95e91fd4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -55,14 +55,18 @@ jobs: run: ./scripts/build - name: Get GitHub OIDC Token - if: github.repository == 'stainless-sdks/kernel-typescript' + if: |- + github.repository == 'stainless-sdks/kernel-typescript' && + !startsWith(github.ref, 'refs/heads/stl/') id: github-oidc uses: actions/github-script@v8 with: script: core.setOutput('github_token', await core.getIDToken()); - name: Upload tarball - if: github.repository == 'stainless-sdks/kernel-typescript' + if: |- + github.repository == 'stainless-sdks/kernel-typescript' && + !startsWith(github.ref, 'refs/heads/stl/') env: URL: https://pkg.stainless.com/s AUTH: ${{ steps.github-oidc.outputs.github_token }} From d63bbce43109670084ff43d72f15583a1639334d Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 7 Mar 2026 15:46:41 +0000 Subject: [PATCH 326/551] chore: update placeholder string --- tests/api-resources/browsers/browsers.test.ts | 4 ++-- tests/api-resources/browsers/fs/fs.test.ts | 12 ++++++------ tests/api-resources/extensions.test.ts | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/tests/api-resources/browsers/browsers.test.ts b/tests/api-resources/browsers/browsers.test.ts index 7647427a..e4f99975 100644 --- a/tests/api-resources/browsers/browsers.test.ts +++ b/tests/api-resources/browsers/browsers.test.ts @@ -148,7 +148,7 @@ describe('resource browsers', () => { // Mock server tests are disabled test.skip('loadExtensions: only required params', async () => { const responsePromise = client.browsers.loadExtensions('id', { - extensions: [{ name: 'name', zip_file: await toFile(Buffer.from('# my file contents'), 'README.md') }], + extensions: [{ name: 'name', zip_file: await toFile(Buffer.from('Example data'), 'README.md') }], }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); @@ -162,7 +162,7 @@ describe('resource browsers', () => { // Mock server tests are disabled test.skip('loadExtensions: required and optional params', async () => { const response = await client.browsers.loadExtensions('id', { - extensions: [{ name: 'name', zip_file: await toFile(Buffer.from('# my file contents'), 'README.md') }], + extensions: [{ name: 'name', zip_file: await toFile(Buffer.from('Example data'), 'README.md') }], }); }); }); diff --git a/tests/api-resources/browsers/fs/fs.test.ts b/tests/api-resources/browsers/fs/fs.test.ts index 086e98f7..6dcd3dba 100644 --- a/tests/api-resources/browsers/fs/fs.test.ts +++ b/tests/api-resources/browsers/fs/fs.test.ts @@ -145,7 +145,7 @@ describe('resource fs', () => { // Mock server tests are disabled test.skip('upload: only required params', async () => { const responsePromise = client.browsers.fs.upload('id', { - files: [{ dest_path: '/J!', file: await toFile(Buffer.from('# my file contents'), 'README.md') }], + files: [{ dest_path: '/J!', file: await toFile(Buffer.from('Example data'), 'README.md') }], }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); @@ -159,7 +159,7 @@ describe('resource fs', () => { // Mock server tests are disabled test.skip('upload: required and optional params', async () => { const response = await client.browsers.fs.upload('id', { - files: [{ dest_path: '/J!', file: await toFile(Buffer.from('# my file contents'), 'README.md') }], + files: [{ dest_path: '/J!', file: await toFile(Buffer.from('Example data'), 'README.md') }], }); }); @@ -167,7 +167,7 @@ describe('resource fs', () => { test.skip('uploadZip: only required params', async () => { const responsePromise = client.browsers.fs.uploadZip('id', { dest_path: '/J!', - zip_file: await toFile(Buffer.from('# my file contents'), 'README.md'), + zip_file: await toFile(Buffer.from('Example data'), 'README.md'), }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); @@ -182,7 +182,7 @@ describe('resource fs', () => { test.skip('uploadZip: required and optional params', async () => { const response = await client.browsers.fs.uploadZip('id', { dest_path: '/J!', - zip_file: await toFile(Buffer.from('# my file contents'), 'README.md'), + zip_file: await toFile(Buffer.from('Example data'), 'README.md'), }); }); @@ -190,7 +190,7 @@ describe('resource fs', () => { test.skip('writeFile: only required params', async () => { const responsePromise = client.browsers.fs.writeFile( 'id', - await toFile(Buffer.from('# my file contents'), 'README.md'), + await toFile(Buffer.from('Example data'), 'README.md'), { path: '/J!' }, ); const rawResponse = await responsePromise.asResponse(); @@ -206,7 +206,7 @@ describe('resource fs', () => { test.skip('writeFile: required and optional params', async () => { const response = await client.browsers.fs.writeFile( 'id', - await toFile(Buffer.from('# my file contents'), 'README.md'), + await toFile(Buffer.from('Example data'), 'README.md'), { path: '/J!', mode: '0611' }, ); }); diff --git a/tests/api-resources/extensions.test.ts b/tests/api-resources/extensions.test.ts index 65c2ef37..9a00e8c4 100644 --- a/tests/api-resources/extensions.test.ts +++ b/tests/api-resources/extensions.test.ts @@ -40,7 +40,7 @@ describe('resource extensions', () => { // Mock server tests are disabled test.skip('upload: only required params', async () => { const responsePromise = client.extensions.upload({ - file: await toFile(Buffer.from('# my file contents'), 'README.md'), + file: await toFile(Buffer.from('Example data'), 'README.md'), }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); @@ -54,7 +54,7 @@ describe('resource extensions', () => { // Mock server tests are disabled test.skip('upload: required and optional params', async () => { const response = await client.extensions.upload({ - file: await toFile(Buffer.from('# my file contents'), 'README.md'), + file: await toFile(Buffer.from('Example data'), 'README.md'), name: 'name', }); }); From 32bb9958e46f10aa9b8186b2fbc5f403801f55d1 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 7 Mar 2026 15:50:11 +0000 Subject: [PATCH 327/551] fix(client): preserve URL params already embedded in path --- src/client.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/client.ts b/src/client.ts index 6aafef4b..540bec4a 100644 --- a/src/client.ts +++ b/src/client.ts @@ -369,8 +369,9 @@ export class Kernel { : new URL(baseURL + (baseURL.endsWith('/') && path.startsWith('/') ? path.slice(1) : path)); const defaultQuery = this.defaultQuery(); - if (!isEmptyObj(defaultQuery)) { - query = { ...defaultQuery, ...query }; + const pathQuery = Object.fromEntries(url.searchParams); + if (!isEmptyObj(defaultQuery) || !isEmptyObj(pathQuery)) { + query = { ...pathQuery, ...defaultQuery, ...query }; } if (typeof query === 'object' && query && !Array.isArray(query)) { From 2c1754b284bc7f9ce86506cc9b093a09b93be4a8 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 10 Mar 2026 02:30:11 +0000 Subject: [PATCH 328/551] chore(internal): update dependencies to address dependabot vulnerabilities --- package.json | 11 +++++++++++ yarn.lock | 39 ++++++--------------------------------- 2 files changed, 17 insertions(+), 33 deletions(-) diff --git a/package.json b/package.json index 18c8c5ed..e799fbf3 100644 --- a/package.json +++ b/package.json @@ -50,6 +50,17 @@ "typescript": "5.8.3", "typescript-eslint": "8.31.1" }, + "overrides": { + "minimatch": "^9.0.5" + }, + "pnpm": { + "overrides": { + "minimatch": "^9.0.5" + } + }, + "resolutions": { + "minimatch": "^9.0.5" + }, "exports": { ".": { "import": "./dist/index.mjs", diff --git a/yarn.lock b/yarn.lock index fc9f262b..078f09a8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1219,15 +1219,7 @@ baseline-browser-mapping@^2.9.0: resolved "https://registry.yarnpkg.com/baseline-browser-mapping/-/baseline-browser-mapping-2.9.14.tgz#3b6af0bc032445bca04de58caa9a87cfe921cbb3" integrity sha512-B0xUquLkiGLgHhpPBqvl7GWegWBUNuujQ6kXd/r1U38ElPT6Ok8KZ8e+FpUGEc2ZoRQUzq/aUnaKFc/svWUGSg== -brace-expansion@^1.1.7: - version "1.1.12" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.12.tgz#ab9b454466e5a8cc3a187beaad580412a9c5b843" - integrity sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg== - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - -brace-expansion@^2.0.1: +brace-expansion@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.2.tgz#54fc53237a613d854c7bd37463aad17df87214e7" integrity sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ== @@ -1395,11 +1387,6 @@ commander@^10.0.1: resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.1.tgz#881ee46b4f77d1c1dccc5823433aa39b022cbe06" integrity sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug== -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== - convert-source-map@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" @@ -2600,26 +2587,12 @@ mimic-fn@^2.1.0: resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== -minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" - integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== - dependencies: - brace-expansion "^1.1.7" - -minimatch@^5.0.1: - version "5.1.6" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96" - integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g== - dependencies: - brace-expansion "^2.0.1" - -minimatch@^9.0.4: - version "9.0.5" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.5.tgz#d74f9dd6b57d83d8e98cfb82133b03978bc929e5" - integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow== +minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.2, minimatch@^5.0.1, minimatch@^9.0.4, minimatch@^9.0.5: + version "9.0.9" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.9.tgz#9b0cb9fcb78087f6fd7eababe2511c4d3d60574e" + integrity sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg== dependencies: - brace-expansion "^2.0.1" + brace-expansion "^2.0.2" minimist@^1.2.6: version "1.2.6" From f8a63dd4cf8d6264e2d5b5d31bb7fc58f4249073 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 10 Mar 2026 16:06:00 +0000 Subject: [PATCH 329/551] feat: Add webdriver_ws_url and metro webdriver session proxy --- .stats.yml | 4 ++-- src/resources/browser-pools.ts | 5 +++++ src/resources/browsers/browsers.ts | 20 ++++++++++++++++++++ src/resources/invocations.ts | 5 +++++ 4 files changed, 32 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index e1ce185b..ae22a711 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 103 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-ef24d4bf172555bcbe8e3b432c644a25a1c6afd99c958a2eda8c3b1ea9568113.yml -openapi_spec_hash: b603c5a983e837928fa7d1100ed64fc9 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-bda5e58fa0bbd08761f27a1e0edbc602c44141ac9483bf6c96d52b7f4d10d9a7.yml +openapi_spec_hash: 10833b36358e8cda023e5bb0abeab0ba config_hash: cff4d43372b6fa66b64e2d4150f6aa76 diff --git a/src/resources/browser-pools.ts b/src/resources/browser-pools.ts index 3dd44263..16a8c723 100644 --- a/src/resources/browser-pools.ts +++ b/src/resources/browser-pools.ts @@ -288,6 +288,11 @@ export interface BrowserPoolAcquireResponse { */ timeout_seconds: number; + /** + * Websocket URL for WebDriver BiDi connections to the browser session + */ + webdriver_ws_url: string; + /** * Remote URL for live viewing the browser session. Only available for non-headless * browsers. diff --git a/src/resources/browsers/browsers.ts b/src/resources/browsers/browsers.ts index c008731f..756dbdd7 100644 --- a/src/resources/browsers/browsers.ts +++ b/src/resources/browsers/browsers.ts @@ -313,6 +313,11 @@ export interface BrowserCreateResponse { */ timeout_seconds: number; + /** + * Websocket URL for WebDriver BiDi connections to the browser session + */ + webdriver_ws_url: string; + /** * Remote URL for live viewing the browser session. Only available for non-headless * browsers. @@ -404,6 +409,11 @@ export interface BrowserRetrieveResponse { */ timeout_seconds: number; + /** + * Websocket URL for WebDriver BiDi connections to the browser session + */ + webdriver_ws_url: string; + /** * Remote URL for live viewing the browser session. Only available for non-headless * browsers. @@ -495,6 +505,11 @@ export interface BrowserUpdateResponse { */ timeout_seconds: number; + /** + * Websocket URL for WebDriver BiDi connections to the browser session + */ + webdriver_ws_url: string; + /** * Remote URL for live viewing the browser session. Only available for non-headless * browsers. @@ -586,6 +601,11 @@ export interface BrowserListResponse { */ timeout_seconds: number; + /** + * Websocket URL for WebDriver BiDi connections to the browser session + */ + webdriver_ws_url: string; + /** * Remote URL for live viewing the browser session. Only available for non-headless * browsers. diff --git a/src/resources/invocations.ts b/src/resources/invocations.ts index b48c129f..8699ffe5 100644 --- a/src/resources/invocations.ts +++ b/src/resources/invocations.ts @@ -448,6 +448,11 @@ export namespace InvocationListBrowsersResponse { */ timeout_seconds: number; + /** + * Websocket URL for WebDriver BiDi connections to the browser session + */ + webdriver_ws_url: string; + /** * Remote URL for live viewing the browser session. Only available for non-headless * browsers. From 20228e3fec736edc36b98770c418fb89e77162b4 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 10 Mar 2026 17:30:24 +0000 Subject: [PATCH 330/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index cede7a52..2ff8218f 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.42.1" + ".": "0.43.0" } diff --git a/package.json b/package.json index e799fbf3..df61d6cb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.42.1", + "version": "0.43.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 7c38063a..771efed7 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.42.1'; // x-release-please-version +export const VERSION = '0.43.0'; // x-release-please-version From 3ffa3ee3e819e6f2989dcfcac6b5fa28c9569865 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 10 Mar 2026 22:02:48 +0000 Subject: [PATCH 331/551] feat: expose smooth drag mouse movement via public API --- .stats.yml | 4 ++-- src/resources/browsers/computer.ts | 24 +++++++++++++++++++ tests/api-resources/browsers/computer.test.ts | 4 ++++ 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index ae22a711..81407436 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 103 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-bda5e58fa0bbd08761f27a1e0edbc602c44141ac9483bf6c96d52b7f4d10d9a7.yml -openapi_spec_hash: 10833b36358e8cda023e5bb0abeab0ba +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-e6936890166ce5b11abaccd511a43a8807e2abf96c1f542d4f8d94655ef27d1f.yml +openapi_spec_hash: 0146ecaea96d8136ef4a35cd04aacf22 config_hash: cff4d43372b6fa66b64e2d4150f6aa76 diff --git a/src/resources/browsers/computer.ts b/src/resources/browsers/computer.ts index f5ed4d32..b40f55a2 100644 --- a/src/resources/browsers/computer.ts +++ b/src/resources/browsers/computer.ts @@ -353,11 +353,23 @@ export namespace ComputerBatchParams { */ delay?: number; + /** + * Target total duration in milliseconds for the entire drag movement when + * smooth=true. Omit for automatic timing based on total path length. + */ + duration_ms?: number; + /** * Modifier keys to hold during the drag */ hold_keys?: Array; + /** + * Use human-like Bezier curves between path waypoints instead of linear + * interpolation. When true, steps_per_segment and step_delay_ms are ignored. + */ + smooth?: boolean; + /** * Delay in milliseconds between relative steps while dragging (not the initial * delay). @@ -554,11 +566,23 @@ export interface ComputerDragMouseParams { */ delay?: number; + /** + * Target total duration in milliseconds for the entire drag movement when + * smooth=true. Omit for automatic timing based on total path length. + */ + duration_ms?: number; + /** * Modifier keys to hold during the drag */ hold_keys?: Array; + /** + * Use human-like Bezier curves between path waypoints instead of linear + * interpolation. When true, steps_per_segment and step_delay_ms are ignored. + */ + smooth?: boolean; + /** * Delay in milliseconds between relative steps while dragging (not the initial * delay). diff --git a/tests/api-resources/browsers/computer.test.ts b/tests/api-resources/browsers/computer.test.ts index ffb2b7d3..807834d7 100644 --- a/tests/api-resources/browsers/computer.test.ts +++ b/tests/api-resources/browsers/computer.test.ts @@ -41,7 +41,9 @@ describe('resource computer', () => { ], button: 'left', delay: 0, + duration_ms: 50, hold_keys: ['string'], + smooth: true, step_delay_ms: 0, steps_per_segment: 1, }, @@ -141,7 +143,9 @@ describe('resource computer', () => { ], button: 'left', delay: 0, + duration_ms: 50, hold_keys: ['string'], + smooth: true, step_delay_ms: 0, steps_per_segment: 1, }); From c25911398ecd6fbfed1e65f899e85d2fecf95c65 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 12 Mar 2026 20:04:42 +0000 Subject: [PATCH 332/551] feat: Add GPU viewport presets and GPU encoder defaults --- .stats.yml | 4 +-- src/resources/browser-pools.ts | 40 +++++++++++++++++------- src/resources/browsers/browsers.ts | 50 +++++++++++++++++++++--------- src/resources/invocations.ts | 10 ++++-- src/resources/shared.ts | 10 ++++-- 5 files changed, 79 insertions(+), 35 deletions(-) diff --git a/.stats.yml b/.stats.yml index 81407436..904cb96c 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 103 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-e6936890166ce5b11abaccd511a43a8807e2abf96c1f542d4f8d94655ef27d1f.yml -openapi_spec_hash: 0146ecaea96d8136ef4a35cd04aacf22 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-95bb1cbe27cbed0339067fa133590e675b99cda4a9c04fad802a5b14563eb572.yml +openapi_spec_hash: 3a24e61711eedb9ea7bb7589a7df956f config_hash: cff4d43372b6fa66b64e2d4150f6aa76 diff --git a/src/resources/browser-pools.ts b/src/resources/browser-pools.ts index 16a8c723..bee14beb 100644 --- a/src/resources/browser-pools.ts +++ b/src/resources/browser-pools.ts @@ -243,9 +243,13 @@ export namespace BrowserPool { /** * Initial browser window size in pixels with optional refresh rate. If omitted, - * image defaults apply (1920x1080@25). Arbitrary viewport dimensions are accepted, - * but the following configurations are known-good and fully tested: 2560x1440@10, - * 1920x1080@25, 1920x1200@25, 1440x900@25, 1280x800@60, 1024x768@60, 1200x800@60. + * image defaults apply (1920x1080@25). For GPU images, the default is + * 1920x1080@60. Arbitrary viewport dimensions and refresh rates are accepted. + * Known-good presets include: 2560x1440@10, 1920x1080@25, 1920x1200@25, + * 1440x900@25, 1280x800@60, 1024x768@60, 1200x800@60. For GPU images, recommended + * presets use one of these resolutions with refresh rates 60, 30, 25, or 10: + * 800x600, 960x720, 1024x576, 1024x768, 1152x648, 1200x800, 1280x720, 1368x768, + * 1440x900, 1600x900, 1920x1080, 1920x1200, 390x844, 360x250, 768x1024, 800x1600. * Viewports outside this list may exhibit unstable live view or recording * behavior. If refresh_rate is not provided, it will be automatically determined * based on the resolution (higher resolutions use lower refresh rates to keep @@ -342,9 +346,13 @@ export interface BrowserPoolAcquireResponse { /** * Initial browser window size in pixels with optional refresh rate. If omitted, - * image defaults apply (1920x1080@25). Arbitrary viewport dimensions are accepted, - * but the following configurations are known-good and fully tested: 2560x1440@10, - * 1920x1080@25, 1920x1200@25, 1440x900@25, 1280x800@60, 1024x768@60, 1200x800@60. + * image defaults apply (1920x1080@25). For GPU images, the default is + * 1920x1080@60. Arbitrary viewport dimensions and refresh rates are accepted. + * Known-good presets include: 2560x1440@10, 1920x1080@25, 1920x1200@25, + * 1440x900@25, 1280x800@60, 1024x768@60, 1200x800@60. For GPU images, recommended + * presets use one of these resolutions with refresh rates 60, 30, 25, or 10: + * 800x600, 960x720, 1024x576, 1024x768, 1152x648, 1200x800, 1280x720, 1368x768, + * 1440x900, 1600x900, 1920x1080, 1920x1200, 390x844, 360x250, 768x1024, 800x1600. * Viewports outside this list may exhibit unstable live view or recording * behavior. If refresh_rate is not provided, it will be automatically determined * based on the resolution (higher resolutions use lower refresh rates to keep @@ -414,9 +422,13 @@ export interface BrowserPoolCreateParams { /** * Initial browser window size in pixels with optional refresh rate. If omitted, - * image defaults apply (1920x1080@25). Arbitrary viewport dimensions are accepted, - * but the following configurations are known-good and fully tested: 2560x1440@10, - * 1920x1080@25, 1920x1200@25, 1440x900@25, 1280x800@60, 1024x768@60, 1200x800@60. + * image defaults apply (1920x1080@25). For GPU images, the default is + * 1920x1080@60. Arbitrary viewport dimensions and refresh rates are accepted. + * Known-good presets include: 2560x1440@10, 1920x1080@25, 1920x1200@25, + * 1440x900@25, 1280x800@60, 1024x768@60, 1200x800@60. For GPU images, recommended + * presets use one of these resolutions with refresh rates 60, 30, 25, or 10: + * 800x600, 960x720, 1024x576, 1024x768, 1152x648, 1200x800, 1280x720, 1368x768, + * 1440x900, 1600x900, 1920x1080, 1920x1200, 390x844, 360x250, 768x1024, 800x1600. * Viewports outside this list may exhibit unstable live view or recording * behavior. If refresh_rate is not provided, it will be automatically determined * based on the resolution (higher resolutions use lower refresh rates to keep @@ -492,9 +504,13 @@ export interface BrowserPoolUpdateParams { /** * Initial browser window size in pixels with optional refresh rate. If omitted, - * image defaults apply (1920x1080@25). Arbitrary viewport dimensions are accepted, - * but the following configurations are known-good and fully tested: 2560x1440@10, - * 1920x1080@25, 1920x1200@25, 1440x900@25, 1280x800@60, 1024x768@60, 1200x800@60. + * image defaults apply (1920x1080@25). For GPU images, the default is + * 1920x1080@60. Arbitrary viewport dimensions and refresh rates are accepted. + * Known-good presets include: 2560x1440@10, 1920x1080@25, 1920x1200@25, + * 1440x900@25, 1280x800@60, 1024x768@60, 1200x800@60. For GPU images, recommended + * presets use one of these resolutions with refresh rates 60, 30, 25, or 10: + * 800x600, 960x720, 1024x576, 1024x768, 1152x648, 1200x800, 1280x720, 1368x768, + * 1440x900, 1600x900, 1920x1080, 1920x1200, 390x844, 360x250, 768x1024, 800x1600. * Viewports outside this list may exhibit unstable live view or recording * behavior. If refresh_rate is not provided, it will be automatically determined * based on the resolution (higher resolutions use lower refresh rates to keep diff --git a/src/resources/browsers/browsers.ts b/src/resources/browsers/browsers.ts index 756dbdd7..14256b8a 100644 --- a/src/resources/browsers/browsers.ts +++ b/src/resources/browsers/browsers.ts @@ -367,9 +367,13 @@ export interface BrowserCreateResponse { /** * Initial browser window size in pixels with optional refresh rate. If omitted, - * image defaults apply (1920x1080@25). Arbitrary viewport dimensions are accepted, - * but the following configurations are known-good and fully tested: 2560x1440@10, - * 1920x1080@25, 1920x1200@25, 1440x900@25, 1280x800@60, 1024x768@60, 1200x800@60. + * image defaults apply (1920x1080@25). For GPU images, the default is + * 1920x1080@60. Arbitrary viewport dimensions and refresh rates are accepted. + * Known-good presets include: 2560x1440@10, 1920x1080@25, 1920x1200@25, + * 1440x900@25, 1280x800@60, 1024x768@60, 1200x800@60. For GPU images, recommended + * presets use one of these resolutions with refresh rates 60, 30, 25, or 10: + * 800x600, 960x720, 1024x576, 1024x768, 1152x648, 1200x800, 1280x720, 1368x768, + * 1440x900, 1600x900, 1920x1080, 1920x1200, 390x844, 360x250, 768x1024, 800x1600. * Viewports outside this list may exhibit unstable live view or recording * behavior. If refresh_rate is not provided, it will be automatically determined * based on the resolution (higher resolutions use lower refresh rates to keep @@ -463,9 +467,13 @@ export interface BrowserRetrieveResponse { /** * Initial browser window size in pixels with optional refresh rate. If omitted, - * image defaults apply (1920x1080@25). Arbitrary viewport dimensions are accepted, - * but the following configurations are known-good and fully tested: 2560x1440@10, - * 1920x1080@25, 1920x1200@25, 1440x900@25, 1280x800@60, 1024x768@60, 1200x800@60. + * image defaults apply (1920x1080@25). For GPU images, the default is + * 1920x1080@60. Arbitrary viewport dimensions and refresh rates are accepted. + * Known-good presets include: 2560x1440@10, 1920x1080@25, 1920x1200@25, + * 1440x900@25, 1280x800@60, 1024x768@60, 1200x800@60. For GPU images, recommended + * presets use one of these resolutions with refresh rates 60, 30, 25, or 10: + * 800x600, 960x720, 1024x576, 1024x768, 1152x648, 1200x800, 1280x720, 1368x768, + * 1440x900, 1600x900, 1920x1080, 1920x1200, 390x844, 360x250, 768x1024, 800x1600. * Viewports outside this list may exhibit unstable live view or recording * behavior. If refresh_rate is not provided, it will be automatically determined * based on the resolution (higher resolutions use lower refresh rates to keep @@ -559,9 +567,13 @@ export interface BrowserUpdateResponse { /** * Initial browser window size in pixels with optional refresh rate. If omitted, - * image defaults apply (1920x1080@25). Arbitrary viewport dimensions are accepted, - * but the following configurations are known-good and fully tested: 2560x1440@10, - * 1920x1080@25, 1920x1200@25, 1440x900@25, 1280x800@60, 1024x768@60, 1200x800@60. + * image defaults apply (1920x1080@25). For GPU images, the default is + * 1920x1080@60. Arbitrary viewport dimensions and refresh rates are accepted. + * Known-good presets include: 2560x1440@10, 1920x1080@25, 1920x1200@25, + * 1440x900@25, 1280x800@60, 1024x768@60, 1200x800@60. For GPU images, recommended + * presets use one of these resolutions with refresh rates 60, 30, 25, or 10: + * 800x600, 960x720, 1024x576, 1024x768, 1152x648, 1200x800, 1280x720, 1368x768, + * 1440x900, 1600x900, 1920x1080, 1920x1200, 390x844, 360x250, 768x1024, 800x1600. * Viewports outside this list may exhibit unstable live view or recording * behavior. If refresh_rate is not provided, it will be automatically determined * based on the resolution (higher resolutions use lower refresh rates to keep @@ -655,9 +667,13 @@ export interface BrowserListResponse { /** * Initial browser window size in pixels with optional refresh rate. If omitted, - * image defaults apply (1920x1080@25). Arbitrary viewport dimensions are accepted, - * but the following configurations are known-good and fully tested: 2560x1440@10, - * 1920x1080@25, 1920x1200@25, 1440x900@25, 1280x800@60, 1024x768@60, 1200x800@60. + * image defaults apply (1920x1080@25). For GPU images, the default is + * 1920x1080@60. Arbitrary viewport dimensions and refresh rates are accepted. + * Known-good presets include: 2560x1440@10, 1920x1080@25, 1920x1200@25, + * 1440x900@25, 1280x800@60, 1024x768@60, 1200x800@60. For GPU images, recommended + * presets use one of these resolutions with refresh rates 60, 30, 25, or 10: + * 800x600, 960x720, 1024x576, 1024x768, 1152x648, 1200x800, 1280x720, 1368x768, + * 1440x900, 1600x900, 1920x1080, 1920x1200, 390x844, 360x250, 768x1024, 800x1600. * Viewports outside this list may exhibit unstable live view or recording * behavior. If refresh_rate is not provided, it will be automatically determined * based on the resolution (higher resolutions use lower refresh rates to keep @@ -731,9 +747,13 @@ export interface BrowserCreateParams { /** * Initial browser window size in pixels with optional refresh rate. If omitted, - * image defaults apply (1920x1080@25). Arbitrary viewport dimensions are accepted, - * but the following configurations are known-good and fully tested: 2560x1440@10, - * 1920x1080@25, 1920x1200@25, 1440x900@25, 1280x800@60, 1024x768@60, 1200x800@60. + * image defaults apply (1920x1080@25). For GPU images, the default is + * 1920x1080@60. Arbitrary viewport dimensions and refresh rates are accepted. + * Known-good presets include: 2560x1440@10, 1920x1080@25, 1920x1200@25, + * 1440x900@25, 1280x800@60, 1024x768@60, 1200x800@60. For GPU images, recommended + * presets use one of these resolutions with refresh rates 60, 30, 25, or 10: + * 800x600, 960x720, 1024x576, 1024x768, 1152x648, 1200x800, 1280x720, 1368x768, + * 1440x900, 1600x900, 1920x1080, 1920x1200, 390x844, 360x250, 768x1024, 800x1600. * Viewports outside this list may exhibit unstable live view or recording * behavior. If refresh_rate is not provided, it will be automatically determined * based on the resolution (higher resolutions use lower refresh rates to keep diff --git a/src/resources/invocations.ts b/src/resources/invocations.ts index 8699ffe5..389f357b 100644 --- a/src/resources/invocations.ts +++ b/src/resources/invocations.ts @@ -502,9 +502,13 @@ export namespace InvocationListBrowsersResponse { /** * Initial browser window size in pixels with optional refresh rate. If omitted, - * image defaults apply (1920x1080@25). Arbitrary viewport dimensions are accepted, - * but the following configurations are known-good and fully tested: 2560x1440@10, - * 1920x1080@25, 1920x1200@25, 1440x900@25, 1280x800@60, 1024x768@60, 1200x800@60. + * image defaults apply (1920x1080@25). For GPU images, the default is + * 1920x1080@60. Arbitrary viewport dimensions and refresh rates are accepted. + * Known-good presets include: 2560x1440@10, 1920x1080@25, 1920x1200@25, + * 1440x900@25, 1280x800@60, 1024x768@60, 1200x800@60. For GPU images, recommended + * presets use one of these resolutions with refresh rates 60, 30, 25, or 10: + * 800x600, 960x720, 1024x576, 1024x768, 1152x648, 1200x800, 1280x720, 1368x768, + * 1440x900, 1600x900, 1920x1080, 1920x1200, 390x844, 360x250, 768x1024, 800x1600. * Viewports outside this list may exhibit unstable live view or recording * behavior. If refresh_rate is not provided, it will be automatically determined * based on the resolution (higher resolutions use lower refresh rates to keep diff --git a/src/resources/shared.ts b/src/resources/shared.ts index 0c26a74e..8666f8a7 100644 --- a/src/resources/shared.ts +++ b/src/resources/shared.ts @@ -65,9 +65,13 @@ export interface BrowserProfile { /** * Initial browser window size in pixels with optional refresh rate. If omitted, - * image defaults apply (1920x1080@25). Arbitrary viewport dimensions are accepted, - * but the following configurations are known-good and fully tested: 2560x1440@10, - * 1920x1080@25, 1920x1200@25, 1440x900@25, 1280x800@60, 1024x768@60, 1200x800@60. + * image defaults apply (1920x1080@25). For GPU images, the default is + * 1920x1080@60. Arbitrary viewport dimensions and refresh rates are accepted. + * Known-good presets include: 2560x1440@10, 1920x1080@25, 1920x1200@25, + * 1440x900@25, 1280x800@60, 1024x768@60, 1200x800@60. For GPU images, recommended + * presets use one of these resolutions with refresh rates 60, 30, 25, or 10: + * 800x600, 960x720, 1024x576, 1024x768, 1152x648, 1200x800, 1280x720, 1368x768, + * 1440x900, 1600x900, 1920x1080, 1920x1200, 390x844, 360x250, 768x1024, 800x1600. * Viewports outside this list may exhibit unstable live view or recording * behavior. If refresh_rate is not provided, it will be automatically determined * based on the resolution (higher resolutions use lower refresh rates to keep From 3698d5c8ca99c9e197e58a9765f238f687fe5037 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 13 Mar 2026 13:26:11 +0000 Subject: [PATCH 333/551] feat: Adds description to OAS spec for docs about delta_x, delta_y --- .stats.yml | 4 ++-- src/resources/browsers/computer.ts | 12 ++++++++---- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/.stats.yml b/.stats.yml index 904cb96c..c129c7d3 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 103 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-95bb1cbe27cbed0339067fa133590e675b99cda4a9c04fad802a5b14563eb572.yml -openapi_spec_hash: 3a24e61711eedb9ea7bb7589a7df956f +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-aa981bcc44bf8382844c53b705f75eeac53fdc7cd828a9260755c5b4537ed966.yml +openapi_spec_hash: e78521a8956dc87b25c076e30600a95e config_hash: cff4d43372b6fa66b64e2d4150f6aa76 diff --git a/src/resources/browsers/computer.ts b/src/resources/browsers/computer.ts index b40f55a2..d67dac60 100644 --- a/src/resources/browsers/computer.ts +++ b/src/resources/browsers/computer.ts @@ -443,12 +443,14 @@ export namespace ComputerBatchParams { y: number; /** - * Horizontal scroll amount. Positive scrolls right, negative scrolls left. + * Horizontal scroll amount in xdotool "wheel units." Positive scrolls right, + * negative scrolls left. */ delta_x?: number; /** - * Vertical scroll amount. Positive scrolls down, negative scrolls up. + * Vertical scroll amount in xdotool "wheel units." Positive scrolls down, negative + * scrolls up. */ delta_y?: number; @@ -656,12 +658,14 @@ export interface ComputerScrollParams { y: number; /** - * Horizontal scroll amount. Positive scrolls right, negative scrolls left. + * Horizontal scroll amount in xdotool "wheel units." Positive scrolls right, + * negative scrolls left. */ delta_x?: number; /** - * Vertical scroll amount. Positive scrolls down, negative scrolls up. + * Vertical scroll amount in xdotool "wheel units." Positive scrolls down, negative + * scrolls up. */ delta_y?: number; From 8beba4c5ea7f4d0f55f6deda9137c09edd23f6af Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 16 Mar 2026 22:33:46 +0000 Subject: [PATCH 334/551] feat: Rename hardware acceleration UI/docs wording to GPU acceleration --- .stats.yml | 4 ++-- src/resources/browser-pools.ts | 2 +- src/resources/browsers/browsers.ts | 12 ++++++------ src/resources/invocations.ts | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.stats.yml b/.stats.yml index c129c7d3..663d1ab4 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 103 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-aa981bcc44bf8382844c53b705f75eeac53fdc7cd828a9260755c5b4537ed966.yml -openapi_spec_hash: e78521a8956dc87b25c076e30600a95e +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-f57c1468805aef5055a41e942a1ec374df98d58f1071b07c31e6496045e0d902.yml +openapi_spec_hash: a4848d54211d6c6330b5ddd08992035a config_hash: cff4d43372b6fa66b64e2d4150f6aa76 diff --git a/src/resources/browser-pools.ts b/src/resources/browser-pools.ts index bee14beb..17d36d3a 100644 --- a/src/resources/browser-pools.ts +++ b/src/resources/browser-pools.ts @@ -309,7 +309,7 @@ export interface BrowserPoolAcquireResponse { deleted_at?: string; /** - * Whether the browser session has hardware-accelerated GPU rendering. + * Whether GPU acceleration is enabled for the browser session. */ gpu?: boolean; diff --git a/src/resources/browsers/browsers.ts b/src/resources/browsers/browsers.ts index 14256b8a..0fa1308f 100644 --- a/src/resources/browsers/browsers.ts +++ b/src/resources/browsers/browsers.ts @@ -330,7 +330,7 @@ export interface BrowserCreateResponse { deleted_at?: string; /** - * Whether the browser session has hardware-accelerated GPU rendering. + * Whether GPU acceleration is enabled for the browser session. */ gpu?: boolean; @@ -430,7 +430,7 @@ export interface BrowserRetrieveResponse { deleted_at?: string; /** - * Whether the browser session has hardware-accelerated GPU rendering. + * Whether GPU acceleration is enabled for the browser session. */ gpu?: boolean; @@ -530,7 +530,7 @@ export interface BrowserUpdateResponse { deleted_at?: string; /** - * Whether the browser session has hardware-accelerated GPU rendering. + * Whether GPU acceleration is enabled for the browser session. */ gpu?: boolean; @@ -630,7 +630,7 @@ export interface BrowserListResponse { deleted_at?: string; /** - * Whether the browser session has hardware-accelerated GPU rendering. + * Whether GPU acceleration is enabled for the browser session. */ gpu?: boolean; @@ -689,8 +689,8 @@ export interface BrowserCreateParams { extensions?: Array; /** - * If true, launches a hardware-accelerated browser with GPU rendering. Requires - * Start-Up or Enterprise plan. + * If true, enables GPU acceleration for the browser session. Requires Start-Up or + * Enterprise plan. */ gpu?: boolean; diff --git a/src/resources/invocations.ts b/src/resources/invocations.ts index 389f357b..ab5f543d 100644 --- a/src/resources/invocations.ts +++ b/src/resources/invocations.ts @@ -465,7 +465,7 @@ export namespace InvocationListBrowsersResponse { deleted_at?: string; /** - * Whether the browser session has hardware-accelerated GPU rendering. + * Whether GPU acceleration is enabled for the browser session. */ gpu?: boolean; From 7fa28e4a4cc710834f7dafc46ee3e73dde744cc1 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 17 Mar 2026 05:06:36 +0000 Subject: [PATCH 335/551] chore(internal): tweak CI branches --- .github/workflows/ci.yml | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 95e91fd4..129e87b2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,12 +1,14 @@ name: CI on: push: - branches-ignore: - - 'generated' - - 'codegen/**' - - 'integrated/**' - - 'stl-preview-head/**' - - 'stl-preview-base/**' + branches: + - '**' + - '!integrated/**' + - '!stl-preview-head/**' + - '!stl-preview-base/**' + - '!generated' + - '!codegen/**' + - 'codegen/stl/**' pull_request: branches-ignore: - 'stl-preview-head/**' From 0df68f7da2354b1f5e3235084cf8b6cec5384331 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 17 Mar 2026 17:15:00 +0000 Subject: [PATCH 336/551] feat: Drop headless GPU support and disable pooling --- .stats.yml | 4 ++-- src/resources/browser-pools.ts | 3 ++- src/resources/browsers/browsers.ts | 14 +++++++++----- src/resources/invocations.ts | 3 ++- 4 files changed, 15 insertions(+), 9 deletions(-) diff --git a/.stats.yml b/.stats.yml index 663d1ab4..ad84265a 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 103 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-f57c1468805aef5055a41e942a1ec374df98d58f1071b07c31e6496045e0d902.yml -openapi_spec_hash: a4848d54211d6c6330b5ddd08992035a +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-17e50cf93d8052ff655c160fc0f156621d9029b041526d4e2e3317b13f80822f.yml +openapi_spec_hash: f7dadc8d93e77983936eb18a8080ce15 config_hash: cff4d43372b6fa66b64e2d4150f6aa76 diff --git a/src/resources/browser-pools.ts b/src/resources/browser-pools.ts index 17d36d3a..adae577d 100644 --- a/src/resources/browser-pools.ts +++ b/src/resources/browser-pools.ts @@ -309,7 +309,8 @@ export interface BrowserPoolAcquireResponse { deleted_at?: string; /** - * Whether GPU acceleration is enabled for the browser session. + * Whether GPU acceleration is enabled for the browser session (only supported for + * headful sessions). */ gpu?: boolean; diff --git a/src/resources/browsers/browsers.ts b/src/resources/browsers/browsers.ts index 0fa1308f..99b9d282 100644 --- a/src/resources/browsers/browsers.ts +++ b/src/resources/browsers/browsers.ts @@ -330,7 +330,8 @@ export interface BrowserCreateResponse { deleted_at?: string; /** - * Whether GPU acceleration is enabled for the browser session. + * Whether GPU acceleration is enabled for the browser session (only supported for + * headful sessions). */ gpu?: boolean; @@ -430,7 +431,8 @@ export interface BrowserRetrieveResponse { deleted_at?: string; /** - * Whether GPU acceleration is enabled for the browser session. + * Whether GPU acceleration is enabled for the browser session (only supported for + * headful sessions). */ gpu?: boolean; @@ -530,7 +532,8 @@ export interface BrowserUpdateResponse { deleted_at?: string; /** - * Whether GPU acceleration is enabled for the browser session. + * Whether GPU acceleration is enabled for the browser session (only supported for + * headful sessions). */ gpu?: boolean; @@ -630,7 +633,8 @@ export interface BrowserListResponse { deleted_at?: string; /** - * Whether GPU acceleration is enabled for the browser session. + * Whether GPU acceleration is enabled for the browser session (only supported for + * headful sessions). */ gpu?: boolean; @@ -690,7 +694,7 @@ export interface BrowserCreateParams { /** * If true, enables GPU acceleration for the browser session. Requires Start-Up or - * Enterprise plan. + * Enterprise plan and headless=false. */ gpu?: boolean; diff --git a/src/resources/invocations.ts b/src/resources/invocations.ts index ab5f543d..e5675740 100644 --- a/src/resources/invocations.ts +++ b/src/resources/invocations.ts @@ -465,7 +465,8 @@ export namespace InvocationListBrowsersResponse { deleted_at?: string; /** - * Whether GPU acceleration is enabled for the browser session. + * Whether GPU acceleration is enabled for the browser session (only supported for + * headful sessions). */ gpu?: boolean; From d0c66e0143e8e66f89347b2e82e4e7d3c09f6456 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 20 Mar 2026 19:33:16 +0000 Subject: [PATCH 337/551] feat: Enhance managed authentication with CUA support and new features --- .stats.yml | 8 +- api.md | 2 + src/resources/auth/auth.ts | 4 + src/resources/auth/connections.ts | 279 ++++++++++++++++++- src/resources/auth/index.ts | 2 + tests/api-resources/auth/connections.test.ts | 12 + 6 files changed, 297 insertions(+), 10 deletions(-) diff --git a/.stats.yml b/.stats.yml index ad84265a..be60802f 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 103 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-17e50cf93d8052ff655c160fc0f156621d9029b041526d4e2e3317b13f80822f.yml -openapi_spec_hash: f7dadc8d93e77983936eb18a8080ce15 -config_hash: cff4d43372b6fa66b64e2d4150f6aa76 +configured_endpoints: 104 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-bb2ac8e0d3a1c08e8afcbcbad7cb733d0f84bd22a8d233c1ec3100a01ee078ae.yml +openapi_spec_hash: a83f7d1c422c85d6dc6158af7afe1d09 +config_hash: 16e4457a0bb26e98a335a1c2a572290a diff --git a/api.md b/api.md index efe009c9..383b68be 100644 --- a/api.md +++ b/api.md @@ -214,6 +214,7 @@ Types: - LoginResponse - ManagedAuth - ManagedAuthCreateRequest +- ManagedAuthUpdateRequest - SubmitFieldsRequest - SubmitFieldsResponse - ConnectionFollowResponse @@ -222,6 +223,7 @@ Methods: - client.auth.connections.create({ ...params }) -> ManagedAuth - client.auth.connections.retrieve(id) -> ManagedAuth +- client.auth.connections.update(id, { ...params }) -> ManagedAuth - client.auth.connections.list({ ...params }) -> ManagedAuthsOffsetPagination - client.auth.connections.delete(id) -> void - client.auth.connections.follow(id) -> ConnectionFollowResponse diff --git a/src/resources/auth/auth.ts b/src/resources/auth/auth.ts index ee5d2fa4..ad3d8de0 100644 --- a/src/resources/auth/auth.ts +++ b/src/resources/auth/auth.ts @@ -8,10 +8,12 @@ import { ConnectionListParams, ConnectionLoginParams, ConnectionSubmitParams, + ConnectionUpdateParams, Connections, LoginResponse, ManagedAuth, ManagedAuthCreateRequest, + ManagedAuthUpdateRequest, ManagedAuthsOffsetPagination, SubmitFieldsRequest, SubmitFieldsResponse, @@ -29,11 +31,13 @@ export declare namespace Auth { type LoginResponse as LoginResponse, type ManagedAuth as ManagedAuth, type ManagedAuthCreateRequest as ManagedAuthCreateRequest, + type ManagedAuthUpdateRequest as ManagedAuthUpdateRequest, type SubmitFieldsRequest as SubmitFieldsRequest, type SubmitFieldsResponse as SubmitFieldsResponse, type ConnectionFollowResponse as ConnectionFollowResponse, type ManagedAuthsOffsetPagination as ManagedAuthsOffsetPagination, type ConnectionCreateParams as ConnectionCreateParams, + type ConnectionUpdateParams as ConnectionUpdateParams, type ConnectionListParams as ConnectionListParams, type ConnectionLoginParams as ConnectionLoginParams, type ConnectionSubmitParams as ConnectionSubmitParams, diff --git a/src/resources/auth/connections.ts b/src/resources/auth/connections.ts index 6f4dc1bf..55f35bf5 100644 --- a/src/resources/auth/connections.ts +++ b/src/resources/auth/connections.ts @@ -44,6 +44,21 @@ export class Connections extends APIResource { return this._client.get(path`/auth/connections/${id}`, options); } + /** + * Update an auth connection's configuration. Only the fields provided will be + * updated. + * + * @example + * ```ts + * const managedAuth = await client.auth.connections.update( + * 'id', + * ); + * ``` + */ + update(id: string, body: ConnectionUpdateParams, options?: RequestOptions): APIPromise { + return this._client.patch(path`/auth/connections/${id}`, { body, ...options }); + } + /** * List auth connections with optional filters for profile_name and domain. * @@ -340,6 +355,12 @@ export interface ManagedAuth { */ proxy_id?: string; + /** + * Non-MFA choices presented during the auth flow, such as account selection or org + * pickers (present when flow_step=awaiting_input). + */ + sign_in_options?: Array | null; + /** * SSO provider being used (e.g., google, github, microsoft) */ @@ -467,6 +488,27 @@ export namespace ManagedAuth { */ selector: string; } + + /** + * A non-MFA choice presented during the auth flow (e.g. account selection, org + * picker) + */ + export interface SignInOption { + /** + * Unique identifier for this option (used to submit selection back) + */ + id: string; + + /** + * Display text for the option + */ + label: string; + + /** + * Additional context such as email address or org name + */ + description?: string | null; + } } /** @@ -588,8 +630,96 @@ export namespace ManagedAuthCreateRequest { } /** - * Request to submit field values, click an SSO button, or select an MFA method. - * Provide exactly one of fields, sso_button_selector, or mfa_option_id. + * Request to update an auth connection's configuration + */ +export interface ManagedAuthUpdateRequest { + /** + * Additional domains valid for this auth flow (replaces existing list) + */ + allowed_domains?: Array; + + /** + * Reference to credentials for the auth connection. Use one of: + * + * - { name } for Kernel credentials + * - { provider, path } for external provider item + * - { provider, auto: true } for external provider domain lookup + */ + credential?: ManagedAuthUpdateRequest.Credential; + + /** + * Interval in seconds between automatic health checks + */ + health_check_interval?: number; + + /** + * Login page URL. Set to empty string to clear. + */ + login_url?: string; + + /** + * Proxy selection. Provide either id or name. The proxy must belong to the + * caller's org. + */ + proxy?: ManagedAuthUpdateRequest.Proxy; + + /** + * Whether to save credentials after every successful login + */ + save_credentials?: boolean; +} + +export namespace ManagedAuthUpdateRequest { + /** + * Reference to credentials for the auth connection. Use one of: + * + * - { name } for Kernel credentials + * - { provider, path } for external provider item + * - { provider, auto: true } for external provider domain lookup + */ + export interface Credential { + /** + * If true, lookup by domain from the specified provider + */ + auto?: boolean; + + /** + * Kernel credential name + */ + name?: string; + + /** + * Provider-specific path (e.g., "VaultName/ItemName" for 1Password) + */ + path?: string; + + /** + * External provider name (e.g., "my-1p") + */ + provider?: string; + } + + /** + * Proxy selection. Provide either id or name. The proxy must belong to the + * caller's org. + */ + export interface Proxy { + /** + * Proxy ID + */ + id?: string; + + /** + * Proxy name + */ + name?: string; + } +} + +/** + * Request to submit field values, click an SSO button, select an MFA method, or + * select a sign-in option. Provide exactly one of fields, sso_button_selector, + * sso_provider, mfa_option_id, or sign_in_option_id. */ export interface SubmitFieldsRequest { /** @@ -598,14 +728,26 @@ export interface SubmitFieldsRequest { fields?: { [key: string]: string }; /** - * Optional MFA option ID if user selected an MFA method + * The MFA method type to select (when mfa_options were returned) */ mfa_option_id?: string; /** - * Optional XPath selector if user chose to click an SSO button instead + * The sign-in option ID to select (when sign_in_options were returned) + */ + sign_in_option_id?: string; + + /** + * XPath selector for the SSO button to click (ODA). Use sso_provider instead for + * CUA. */ sso_button_selector?: string; + + /** + * SSO provider to click, matching the provider field from pending_sso_buttons + * (e.g., "google", "github"). Cannot be used with sso_button_selector. + */ + sso_provider?: string; } /** @@ -703,6 +845,12 @@ export namespace ConnectionFollowResponse { */ post_login_url?: string; + /** + * Non-MFA choices presented during the auth flow, such as account selection or org + * pickers (present when flow_step=AWAITING_INPUT). + */ + sign_in_options?: Array; + /** * Visible error message from the website (e.g., 'Incorrect password'). Present * when the website displays an error during login. @@ -796,6 +944,27 @@ export namespace ConnectionFollowResponse { */ selector: string; } + + /** + * A non-MFA choice presented during the auth flow (e.g. account selection, org + * picker) + */ + export interface SignInOption { + /** + * Unique identifier for this option (used to submit selection back) + */ + id: string; + + /** + * Display text for the option + */ + label: string; + + /** + * Additional context such as email address or org name + */ + description?: string | null; + } } } @@ -914,6 +1083,90 @@ export namespace ConnectionCreateParams { } } +export interface ConnectionUpdateParams { + /** + * Additional domains valid for this auth flow (replaces existing list) + */ + allowed_domains?: Array; + + /** + * Reference to credentials for the auth connection. Use one of: + * + * - { name } for Kernel credentials + * - { provider, path } for external provider item + * - { provider, auto: true } for external provider domain lookup + */ + credential?: ConnectionUpdateParams.Credential; + + /** + * Interval in seconds between automatic health checks + */ + health_check_interval?: number; + + /** + * Login page URL. Set to empty string to clear. + */ + login_url?: string; + + /** + * Proxy selection. Provide either id or name. The proxy must belong to the + * caller's org. + */ + proxy?: ConnectionUpdateParams.Proxy; + + /** + * Whether to save credentials after every successful login + */ + save_credentials?: boolean; +} + +export namespace ConnectionUpdateParams { + /** + * Reference to credentials for the auth connection. Use one of: + * + * - { name } for Kernel credentials + * - { provider, path } for external provider item + * - { provider, auto: true } for external provider domain lookup + */ + export interface Credential { + /** + * If true, lookup by domain from the specified provider + */ + auto?: boolean; + + /** + * Kernel credential name + */ + name?: string; + + /** + * Provider-specific path (e.g., "VaultName/ItemName" for 1Password) + */ + path?: string; + + /** + * External provider name (e.g., "my-1p") + */ + provider?: string; + } + + /** + * Proxy selection. Provide either id or name. The proxy must belong to the + * caller's org. + */ + export interface Proxy { + /** + * Proxy ID + */ + id?: string; + + /** + * Proxy name + */ + name?: string; + } +} + export interface ConnectionListParams extends OffsetPaginationParams { /** * Filter by domain @@ -959,14 +1212,26 @@ export interface ConnectionSubmitParams { fields?: { [key: string]: string }; /** - * Optional MFA option ID if user selected an MFA method + * The MFA method type to select (when mfa_options were returned) */ mfa_option_id?: string; /** - * Optional XPath selector if user chose to click an SSO button instead + * The sign-in option ID to select (when sign_in_options were returned) + */ + sign_in_option_id?: string; + + /** + * XPath selector for the SSO button to click (ODA). Use sso_provider instead for + * CUA. */ sso_button_selector?: string; + + /** + * SSO provider to click, matching the provider field from pending_sso_buttons + * (e.g., "google", "github"). Cannot be used with sso_button_selector. + */ + sso_provider?: string; } export declare namespace Connections { @@ -974,11 +1239,13 @@ export declare namespace Connections { type LoginResponse as LoginResponse, type ManagedAuth as ManagedAuth, type ManagedAuthCreateRequest as ManagedAuthCreateRequest, + type ManagedAuthUpdateRequest as ManagedAuthUpdateRequest, type SubmitFieldsRequest as SubmitFieldsRequest, type SubmitFieldsResponse as SubmitFieldsResponse, type ConnectionFollowResponse as ConnectionFollowResponse, type ManagedAuthsOffsetPagination as ManagedAuthsOffsetPagination, type ConnectionCreateParams as ConnectionCreateParams, + type ConnectionUpdateParams as ConnectionUpdateParams, type ConnectionListParams as ConnectionListParams, type ConnectionLoginParams as ConnectionLoginParams, type ConnectionSubmitParams as ConnectionSubmitParams, diff --git a/src/resources/auth/index.ts b/src/resources/auth/index.ts index d71236bb..a8a6bfef 100644 --- a/src/resources/auth/index.ts +++ b/src/resources/auth/index.ts @@ -6,10 +6,12 @@ export { type LoginResponse, type ManagedAuth, type ManagedAuthCreateRequest, + type ManagedAuthUpdateRequest, type SubmitFieldsRequest, type SubmitFieldsResponse, type ConnectionFollowResponse, type ConnectionCreateParams, + type ConnectionUpdateParams, type ConnectionListParams, type ConnectionLoginParams, type ConnectionSubmitParams, diff --git a/tests/api-resources/auth/connections.test.ts b/tests/api-resources/auth/connections.test.ts index 1c60d631..1d08c5c0 100644 --- a/tests/api-resources/auth/connections.test.ts +++ b/tests/api-resources/auth/connections.test.ts @@ -54,6 +54,18 @@ describe('resource connections', () => { expect(dataAndResponse.response).toBe(rawResponse); }); + // Mock server tests are disabled + test.skip('update', async () => { + const responsePromise = client.auth.connections.update('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); + }); + // Mock server tests are disabled test.skip('list', async () => { const responsePromise = client.auth.connections.list(); From 509401387b0048ac709d387a4bc2069e1ebae4f7 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 20 Mar 2026 19:36:23 +0000 Subject: [PATCH 338/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 2ff8218f..b470c2a9 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.43.0" + ".": "0.44.0" } diff --git a/package.json b/package.json index df61d6cb..48453dd3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.43.0", + "version": "0.44.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 771efed7..6a69b90d 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.43.0'; // x-release-please-version +export const VERSION = '0.44.0'; // x-release-please-version From 941bb34e601c53251022d23fc7fa4fc944c7fb31 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 24 Mar 2026 02:56:35 +0000 Subject: [PATCH 339/551] chore(internal): update gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 2412bb77..c85fe684 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ .prism.log +.stdy.log node_modules yarn-error.log codegen.log From b5fb9568f1c48f2323b1b38740cf83b05adba8da Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 25 Mar 2026 02:31:15 +0000 Subject: [PATCH 340/551] chore(ci): skip lint on metadata-only changes Note that we still want to run tests, as these depend on the metadata. --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 129e87b2..42341634 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,7 +19,7 @@ jobs: timeout-minutes: 10 name: lint runs-on: ${{ github.repository == 'stainless-sdks/kernel-typescript' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} - if: github.event_name == 'push' || github.event.pull_request.head.repo.fork + if: (github.event_name == 'push' || github.event.pull_request.head.repo.fork) && (github.event_name != 'push' || github.event.head_commit.message != 'codegen metadata') steps: - uses: actions/checkout@v6 @@ -38,7 +38,7 @@ jobs: timeout-minutes: 5 name: build runs-on: ${{ github.repository == 'stainless-sdks/kernel-typescript' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} - if: github.event_name == 'push' || github.event.pull_request.head.repo.fork + if: (github.event_name == 'push' || github.event.pull_request.head.repo.fork) && (github.event_name != 'push' || github.event.head_commit.message != 'codegen metadata') permissions: contents: read id-token: write From 6786d5bda3c1dee48f381896b2d85241201297ec Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 26 Mar 2026 14:39:08 +0000 Subject: [PATCH 341/551] feat: [kernel-1008] browser pools add custom policy --- .stats.yml | 4 ++-- src/resources/browser-pools.ts | 24 +++++++++++++++++++++++ tests/api-resources/browser-pools.test.ts | 2 ++ 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index be60802f..8a5c9d0b 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 104 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-bb2ac8e0d3a1c08e8afcbcbad7cb733d0f84bd22a8d233c1ec3100a01ee078ae.yml -openapi_spec_hash: a83f7d1c422c85d6dc6158af7afe1d09 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-aeb5ea5c2632fe7fd905d509bc6cbb06999d17c458ec44ffd713935ba5b848f9.yml +openapi_spec_hash: fef45a8569f1d3de04c86e95b1112665 config_hash: 16e4457a0bb26e98a335a1c2a572290a diff --git a/src/resources/browser-pools.ts b/src/resources/browser-pools.ts index adae577d..83a8e93f 100644 --- a/src/resources/browser-pools.ts +++ b/src/resources/browser-pools.ts @@ -190,6 +190,14 @@ export namespace BrowserPool { */ size: number; + /** + * Custom Chrome enterprise policy overrides applied to all browsers in this pool. + * Keys are Chrome enterprise policy names; values must match their expected types. + * Blocked: kernel-managed policies (extensions, proxy, CDP/automation). See + * https://chromeenterprise.google/policies/ + */ + chrome_policy?: { [key: string]: unknown }; + /** * List of browser extensions to load into the session. Provide each by id or name. */ @@ -370,6 +378,14 @@ export interface BrowserPoolCreateParams { */ size: number; + /** + * Custom Chrome enterprise policy overrides applied to all browsers in this pool. + * Keys are Chrome enterprise policy names; values must match their expected types. + * Blocked: kernel-managed policies (extensions, proxy, CDP/automation). See + * https://chromeenterprise.google/policies/ + */ + chrome_policy?: { [key: string]: unknown }; + /** * List of browser extensions to load into the session. Provide each by id or name. */ @@ -446,6 +462,14 @@ export interface BrowserPoolUpdateParams { */ size: number; + /** + * Custom Chrome enterprise policy overrides applied to all browsers in this pool. + * Keys are Chrome enterprise policy names; values must match their expected types. + * Blocked: kernel-managed policies (extensions, proxy, CDP/automation). See + * https://chromeenterprise.google/policies/ + */ + chrome_policy?: { [key: string]: unknown }; + /** * Whether to discard all idle browsers and rebuild the pool immediately. Defaults * to false. diff --git a/tests/api-resources/browser-pools.test.ts b/tests/api-resources/browser-pools.test.ts index a3239d79..4bc1157d 100644 --- a/tests/api-resources/browser-pools.test.ts +++ b/tests/api-resources/browser-pools.test.ts @@ -24,6 +24,7 @@ describe('resource browserPools', () => { test.skip('create: required and optional params', async () => { const response = await client.browserPools.create({ size: 10, + chrome_policy: { foo: 'bar' }, extensions: [{ id: 'id', name: 'name' }], fill_rate_per_minute: 0, headless: false, @@ -73,6 +74,7 @@ describe('resource browserPools', () => { test.skip('update: required and optional params', async () => { const response = await client.browserPools.update('id_or_name', { size: 10, + chrome_policy: { foo: 'bar' }, discard_all_idle: false, extensions: [{ id: 'id', name: 'name' }], fill_rate_per_minute: 0, From 1facce1a1e6c7ba6f97a6824f5415662c0acfd56 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 28 Mar 2026 04:02:28 +0000 Subject: [PATCH 342/551] chore(internal): codegen related update --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 078f09a8..e5e2a93b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1220,9 +1220,9 @@ baseline-browser-mapping@^2.9.0: integrity sha512-B0xUquLkiGLgHhpPBqvl7GWegWBUNuujQ6kXd/r1U38ElPT6Ok8KZ8e+FpUGEc2ZoRQUzq/aUnaKFc/svWUGSg== brace-expansion@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.2.tgz#54fc53237a613d854c7bd37463aad17df87214e7" - integrity sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ== + version "2.0.3" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.3.tgz#0493338bdd58e319b1039c67cf7ee439892c01d9" + integrity sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA== dependencies: balanced-match "^1.0.0" From 509971cee667b4468078e0f81d67fdc9f19592bd Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 30 Mar 2026 18:01:19 +0000 Subject: [PATCH 343/551] feat: Add disable_default_proxy for stealth browsers --- .stats.yml | 4 ++-- src/resources/browsers/browsers.ts | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 8a5c9d0b..8ed1b33b 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 104 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-aeb5ea5c2632fe7fd905d509bc6cbb06999d17c458ec44ffd713935ba5b848f9.yml -openapi_spec_hash: fef45a8569f1d3de04c86e95b1112665 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-20310988401243aa5c4a2e2ac6cba5dd90873fb7b83497a2d50c691352c0dd7b.yml +openapi_spec_hash: e19e650b4b2c8c8fde1f739c4aab6b33 config_hash: 16e4457a0bb26e98a335a1c2a572290a diff --git a/src/resources/browsers/browsers.ts b/src/resources/browsers/browsers.ts index 99b9d282..2330b599 100644 --- a/src/resources/browsers/browsers.ts +++ b/src/resources/browsers/browsers.ts @@ -774,6 +774,12 @@ export interface BrowserRetrieveParams { } export interface BrowserUpdateParams { + /** + * If true, stealth browsers connect directly instead of using the default stealth + * proxy. + */ + disable_default_proxy?: boolean; + /** * Profile to load into the browser session. Only allowed if the session does not * already have a profile loaded. From b74f8e62d501fcd94176884a8a53541a3fa96503 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 30 Mar 2026 18:23:10 +0000 Subject: [PATCH 344/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index b470c2a9..e564a448 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.44.0" + ".": "0.45.0" } diff --git a/package.json b/package.json index 48453dd3..2d0d426d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.44.0", + "version": "0.45.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 6a69b90d..27643a43 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.44.0'; // x-release-please-version +export const VERSION = '0.45.0'; // x-release-please-version From 0b218fd3507bf178044438b98f6a042dc16b50a9 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 1 Apr 2026 04:55:27 +0000 Subject: [PATCH 345/551] fix(internal): gitignore generated `oidc` dir --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index c85fe684..9487e48a 100644 --- a/.gitignore +++ b/.gitignore @@ -9,4 +9,4 @@ dist-deno /*.tgz .idea/ .eslintcache - +oidc From 995dd0410559c1a64e4e0672002b76ac19eccfd6 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 1 Apr 2026 23:18:08 +0000 Subject: [PATCH 346/551] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 8ed1b33b..1bda9d34 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 104 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-20310988401243aa5c4a2e2ac6cba5dd90873fb7b83497a2d50c691352c0dd7b.yml -openapi_spec_hash: e19e650b4b2c8c8fde1f739c4aab6b33 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-403eadeddcd92ecf5c0ada739fb59d73d829a9b463788a81ac3ed97d0cd3a64b.yml +openapi_spec_hash: 8fdd3a5bd5e035f0adeb72329c215ad7 config_hash: 16e4457a0bb26e98a335a1c2a572290a From 7a876dbe3a95bb3b7e8ae18dac41f969b70d0cc8 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 6 Apr 2026 18:48:33 +0000 Subject: [PATCH 347/551] feat: Add optional url parameter to proxy check endpoint --- .stats.yml | 4 ++-- api.md | 2 +- src/client.ts | 2 ++ src/resources/index.ts | 1 + src/resources/proxies.ts | 32 ++++++++++++++++++++++++++--- tests/api-resources/proxies.test.ts | 8 ++++++++ 6 files changed, 43 insertions(+), 6 deletions(-) diff --git a/.stats.yml b/.stats.yml index 1bda9d34..4bc313ec 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 104 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-403eadeddcd92ecf5c0ada739fb59d73d829a9b463788a81ac3ed97d0cd3a64b.yml -openapi_spec_hash: 8fdd3a5bd5e035f0adeb72329c215ad7 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-f7024f4171c7c4ec558de1c27f338b1089ffddd0d2dbfdb9bb9f9c2abe8f47bf.yml +openapi_spec_hash: ced43682b49e73a2862f99b49abb4fcd config_hash: 16e4457a0bb26e98a335a1c2a572290a diff --git a/api.md b/api.md index 383b68be..1d47fcbe 100644 --- a/api.md +++ b/api.md @@ -245,7 +245,7 @@ Methods: - client.proxies.retrieve(id) -> ProxyRetrieveResponse - client.proxies.list() -> ProxyListResponse - client.proxies.delete(id) -> void -- client.proxies.check(id) -> ProxyCheckResponse +- client.proxies.check(id, { ...params }) -> ProxyCheckResponse # Extensions diff --git a/src/client.ts b/src/client.ts index 540bec4a..7aa11825 100644 --- a/src/client.ts +++ b/src/client.ts @@ -91,6 +91,7 @@ import { import { ProfileCreateParams, ProfileListParams, Profiles } from './resources/profiles'; import { Proxies, + ProxyCheckParams, ProxyCheckResponse, ProxyCreateParams, ProxyCreateResponse, @@ -998,6 +999,7 @@ export declare namespace Kernel { type ProxyListResponse as ProxyListResponse, type ProxyCheckResponse as ProxyCheckResponse, type ProxyCreateParams as ProxyCreateParams, + type ProxyCheckParams as ProxyCheckParams, }; export { diff --git a/src/resources/index.ts b/src/resources/index.ts index 18963e71..a5b082c1 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -103,4 +103,5 @@ export { type ProxyListResponse, type ProxyCheckResponse, type ProxyCreateParams, + type ProxyCheckParams, } from './proxies'; diff --git a/src/resources/proxies.ts b/src/resources/proxies.ts index 0e0d271e..fdf7b923 100644 --- a/src/resources/proxies.ts +++ b/src/resources/proxies.ts @@ -42,10 +42,19 @@ export class Proxies extends APIResource { } /** - * Run a health check on the proxy to verify it's working. + * Run a health check on the proxy to verify it's working. Optionally specify a URL + * to test reachability against a specific target. For ISP and datacenter proxies, + * this reliably tests whether the target site is reachable from the proxy's stable + * exit IP. For residential and mobile proxies, the exit node varies between + * requests, so this validates proxy configuration and connectivity rather than + * guaranteeing site-specific reachability. */ - check(id: string, options?: RequestOptions): APIPromise { - return this._client.post(path`/proxies/${id}/check`, options); + check( + id: string, + body: ProxyCheckParams | null | undefined = {}, + options?: RequestOptions, + ): APIPromise { + return this._client.post(path`/proxies/${id}/check`, { body, ...options }); } } @@ -1183,6 +1192,22 @@ export namespace ProxyCreateParams { } } +export interface ProxyCheckParams { + /** + * An optional URL to test reachability against. If provided, the proxy check will + * test connectivity to this URL instead of the default test URLs. Only HTTP and + * HTTPS schemes are allowed, and the URL must resolve to a public IP address. For + * ISP and datacenter proxies, the exit IP is stable, so a successful check + * reliably indicates that subsequent browser sessions will reach the target site + * with the same IP. For residential and mobile proxies, the exit node changes + * between requests, so a successful check validates proxy configuration but does + * not guarantee that a subsequent browser session will use the same exit IP or + * reach the same site — it is useful for verifying credentials and connectivity, + * not for predicting site-specific behavior. + */ + url?: string; +} + export declare namespace Proxies { export { type ProxyCreateResponse as ProxyCreateResponse, @@ -1190,5 +1215,6 @@ export declare namespace Proxies { type ProxyListResponse as ProxyListResponse, type ProxyCheckResponse as ProxyCheckResponse, type ProxyCreateParams as ProxyCreateParams, + type ProxyCheckParams as ProxyCheckParams, }; } diff --git a/tests/api-resources/proxies.test.ts b/tests/api-resources/proxies.test.ts index 237c7dc4..63142f87 100644 --- a/tests/api-resources/proxies.test.ts +++ b/tests/api-resources/proxies.test.ts @@ -78,4 +78,12 @@ describe('resource proxies', () => { expect(dataAndResponse.data).toBe(response); expect(dataAndResponse.response).toBe(rawResponse); }); + + // Mock server tests are disabled + test.skip('check: 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.proxies.check('id', { url: 'url' }, { path: '/_stainless_unknown_path' }), + ).rejects.toThrow(Kernel.NotFoundError); + }); }); From de510f85d4e16c35d48d53bae28417278e457bec Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 6 Apr 2026 18:58:07 +0000 Subject: [PATCH 348/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index e564a448..ca683ed1 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.45.0" + ".": "0.46.0" } diff --git a/package.json b/package.json index 2d0d426d..88f7d134 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.45.0", + "version": "0.46.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 27643a43..e6f79609 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.45.0'; // x-release-please-version +export const VERSION = '0.46.0'; // x-release-please-version From 700cabd2e75fd1907e861caa5aa98e6d46425530 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 7 Apr 2026 01:40:34 +0000 Subject: [PATCH 349/551] feat: Include login_url in managed auth connection response --- .stats.yml | 4 ++-- src/resources/auth/connections.ts | 16 ++++++++++++---- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/.stats.yml b/.stats.yml index 4bc313ec..7f48513f 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 104 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-f7024f4171c7c4ec558de1c27f338b1089ffddd0d2dbfdb9bb9f9c2abe8f47bf.yml -openapi_spec_hash: ced43682b49e73a2862f99b49abb4fcd +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-ac10847d991ef8ed89124b5550922cb5726af2b4a4c3396ee6ff82938302fc25.yml +openapi_spec_hash: 0d902563108fe2461708c05336eab40a config_hash: 16e4457a0bb26e98a335a1c2a572290a diff --git a/src/resources/auth/connections.ts b/src/resources/auth/connections.ts index 55f35bf5..09ffe71e 100644 --- a/src/resources/auth/connections.ts +++ b/src/resources/auth/connections.ts @@ -14,8 +14,9 @@ import { path } from '../../internal/utils/path'; */ export class Connections extends APIResource { /** - * Creates an auth connection for a profile and domain combination. Returns 409 - * Conflict if an auth connection already exists for the given profile and domain. + * Creates an auth connection for a profile and domain combination. If the provided + * profile_name does not exist, it is created automatically. Returns 409 Conflict + * if an auth connection already exists for the given profile and domain. * * @example * ```ts @@ -334,6 +335,11 @@ export interface ManagedAuth { */ live_view_url?: string | null; + /** + * Optional login page URL to skip discovery + */ + login_url?: string; + /** * MFA method options (present when flow_step=awaiting_input and MFA selection * required) @@ -521,7 +527,8 @@ export interface ManagedAuthCreateRequest { domain: string; /** - * Name of the profile to manage authentication for + * Name of the profile to manage authentication for. If the profile does not exist, + * it is created automatically. */ profile_name: string; @@ -975,7 +982,8 @@ export interface ConnectionCreateParams { domain: string; /** - * Name of the profile to manage authentication for + * Name of the profile to manage authentication for. If the profile does not exist, + * it is created automatically. */ profile_name: string; From 9b45a440e08f038b52a14c568ff9c64c4a596b7f Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 7 Apr 2026 01:50:55 +0000 Subject: [PATCH 350/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index ca683ed1..3bafaeb4 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.46.0" + ".": "0.47.0" } diff --git a/package.json b/package.json index 88f7d134..7564d5d4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.46.0", + "version": "0.47.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index e6f79609..d84ba019 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.46.0'; // x-release-please-version +export const VERSION = '0.47.0'; // x-release-please-version From b5d5bc2600b87f4fd38db00e3f6569dd911a9084 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 8 Apr 2026 13:12:09 +0000 Subject: [PATCH 351/551] feat: [kernel-1116] add base_url field to browser session response --- .stats.yml | 4 ++-- src/resources/browser-pools.ts | 5 +++++ src/resources/browsers/browsers.ts | 20 ++++++++++++++++++++ src/resources/invocations.ts | 5 +++++ 4 files changed, 32 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 7f48513f..b81754a7 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 104 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-ac10847d991ef8ed89124b5550922cb5726af2b4a4c3396ee6ff82938302fc25.yml -openapi_spec_hash: 0d902563108fe2461708c05336eab40a +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-aee09720882ec1d78f845fee6ceecb0466c264629e4edecd3230406dd06d7983.yml +openapi_spec_hash: 438da0d38d169897595f301d82fa7e2c config_hash: 16e4457a0bb26e98a335a1c2a572290a diff --git a/src/resources/browser-pools.ts b/src/resources/browser-pools.ts index 83a8e93f..f587ded7 100644 --- a/src/resources/browser-pools.ts +++ b/src/resources/browser-pools.ts @@ -305,6 +305,11 @@ export interface BrowserPoolAcquireResponse { */ webdriver_ws_url: string; + /** + * Metro-API HTTP base URL for this browser session. + */ + base_url?: string; + /** * Remote URL for live viewing the browser session. Only available for non-headless * browsers. diff --git a/src/resources/browsers/browsers.ts b/src/resources/browsers/browsers.ts index 2330b599..2e1264b2 100644 --- a/src/resources/browsers/browsers.ts +++ b/src/resources/browsers/browsers.ts @@ -318,6 +318,11 @@ export interface BrowserCreateResponse { */ webdriver_ws_url: string; + /** + * Metro-API HTTP base URL for this browser session. + */ + base_url?: string; + /** * Remote URL for live viewing the browser session. Only available for non-headless * browsers. @@ -419,6 +424,11 @@ export interface BrowserRetrieveResponse { */ webdriver_ws_url: string; + /** + * Metro-API HTTP base URL for this browser session. + */ + base_url?: string; + /** * Remote URL for live viewing the browser session. Only available for non-headless * browsers. @@ -520,6 +530,11 @@ export interface BrowserUpdateResponse { */ webdriver_ws_url: string; + /** + * Metro-API HTTP base URL for this browser session. + */ + base_url?: string; + /** * Remote URL for live viewing the browser session. Only available for non-headless * browsers. @@ -621,6 +636,11 @@ export interface BrowserListResponse { */ webdriver_ws_url: string; + /** + * Metro-API HTTP base URL for this browser session. + */ + base_url?: string; + /** * Remote URL for live viewing the browser session. Only available for non-headless * browsers. diff --git a/src/resources/invocations.ts b/src/resources/invocations.ts index e5675740..430751b8 100644 --- a/src/resources/invocations.ts +++ b/src/resources/invocations.ts @@ -453,6 +453,11 @@ export namespace InvocationListBrowsersResponse { */ webdriver_ws_url: string; + /** + * Metro-API HTTP base URL for this browser session. + */ + base_url?: string; + /** * Remote URL for live viewing the browser session. Only available for non-headless * browsers. From 4d7e2d043c8d21eef36943165cf0463e5bbfbf96 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 8 Apr 2026 20:48:24 +0000 Subject: [PATCH 352/551] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index b81754a7..d184bbd0 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 104 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-aee09720882ec1d78f845fee6ceecb0466c264629e4edecd3230406dd06d7983.yml -openapi_spec_hash: 438da0d38d169897595f301d82fa7e2c +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-49a1a92e00d1eb87e91e8527275cb0705fce2edea30e70fea745f134dd451fbd.yml +openapi_spec_hash: 3aa6ab6939790f538332054162fbdedc config_hash: 16e4457a0bb26e98a335a1c2a572290a From b15e6b84789ca6f056a89e10ba6d57d5d3d0bc52 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 9 Apr 2026 06:04:11 +0000 Subject: [PATCH 353/551] chore(internal): codegen related update --- src/internal/utils/env.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/internal/utils/env.ts b/src/internal/utils/env.ts index 2d848007..cc5fa0fa 100644 --- a/src/internal/utils/env.ts +++ b/src/internal/utils/env.ts @@ -9,10 +9,10 @@ */ export const readEnv = (env: string): string | undefined => { if (typeof (globalThis as any).process !== 'undefined') { - return (globalThis as any).process.env?.[env]?.trim() ?? undefined; + return (globalThis as any).process.env?.[env]?.trim() || undefined; } if (typeof (globalThis as any).Deno !== 'undefined') { - return (globalThis as any).Deno.env?.get?.(env)?.trim(); + return (globalThis as any).Deno.env?.get?.(env)?.trim() || undefined; } return undefined; }; From 7f48e82bd2ff4bd430fddabfb1b4b54fb4075581 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 10 Apr 2026 02:14:36 +0000 Subject: [PATCH 354/551] chore: retrigger Stainless codegen for projects resource --- .stats.yml | 4 +- api.md | 28 +++ src/client.ts | 26 +++ src/resources/index.ts | 10 + src/resources/projects.ts | 3 + src/resources/projects/index.ts | 18 ++ src/resources/projects/limits.ts | 128 +++++++++++++ src/resources/projects/projects.ts | 179 ++++++++++++++++++ tests/api-resources/projects/limits.test.ts | 34 ++++ tests/api-resources/projects/projects.test.ts | 83 ++++++++ 10 files changed, 511 insertions(+), 2 deletions(-) create mode 100644 src/resources/projects.ts create mode 100644 src/resources/projects/index.ts create mode 100644 src/resources/projects/limits.ts create mode 100644 src/resources/projects/projects.ts create mode 100644 tests/api-resources/projects/limits.test.ts create mode 100644 tests/api-resources/projects/projects.test.ts diff --git a/.stats.yml b/.stats.yml index d184bbd0..db7b03c8 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 104 +configured_endpoints: 111 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-49a1a92e00d1eb87e91e8527275cb0705fce2edea30e70fea745f134dd451fbd.yml openapi_spec_hash: 3aa6ab6939790f538332054162fbdedc -config_hash: 16e4457a0bb26e98a335a1c2a572290a +config_hash: 9818dd634f87b677410eefd013d7a179 diff --git a/api.md b/api.md index 1d47fcbe..4f2faea0 100644 --- a/api.md +++ b/api.md @@ -299,6 +299,34 @@ Methods: - client.credentials.delete(idOrName) -> void - client.credentials.totpCode(idOrName) -> CredentialTotpCodeResponse +# Projects + +Types: + +- CreateProjectRequest +- Project +- UpdateProjectRequest + +Methods: + +- client.projects.create({ ...params }) -> Project +- client.projects.retrieve(id) -> Project +- client.projects.update(id, { ...params }) -> Project +- client.projects.list({ ...params }) -> ProjectsOffsetPagination +- client.projects.delete(id) -> void + +## Limits + +Types: + +- ProjectLimits +- UpdateProjectLimitsRequest + +Methods: + +- client.projects.limits.retrieve(id) -> ProjectLimits +- client.projects.limits.update(id, { ...params }) -> ProjectLimits + # CredentialProviders Types: diff --git a/src/client.ts b/src/client.ts index 7aa11825..c39f1161 100644 --- a/src/client.ts +++ b/src/client.ts @@ -117,6 +117,16 @@ import { Browsers, Profile, } from './resources/browsers/browsers'; +import { + CreateProjectRequest, + Project, + ProjectCreateParams, + ProjectListParams, + ProjectUpdateParams, + Projects, + ProjectsOffsetPagination, + UpdateProjectRequest, +} from './resources/projects/projects'; import { type Fetch } from './internal/builtin-types'; import { HeadersLike, NullableHeaders, buildHeaders } from './internal/headers'; import { FinalRequestOptions, RequestOptions } from './internal/request-options'; @@ -902,6 +912,10 @@ export class Kernel { * Create and manage credentials for authentication. */ credentials: API.Credentials = new API.Credentials(this); + /** + * Create and manage projects for resource isolation within an organization. + */ + projects: API.Projects = new API.Projects(this); /** * Configure external credential providers like 1Password. */ @@ -918,6 +932,7 @@ Kernel.Proxies = Proxies; Kernel.Extensions = Extensions; Kernel.BrowserPools = BrowserPools; Kernel.Credentials = Credentials; +Kernel.Projects = Projects; Kernel.CredentialProviders = CredentialProviders; export declare namespace Kernel { @@ -1034,6 +1049,17 @@ export declare namespace Kernel { type CredentialListParams as CredentialListParams, }; + export { + Projects as Projects, + type CreateProjectRequest as CreateProjectRequest, + type Project as Project, + type UpdateProjectRequest as UpdateProjectRequest, + type ProjectsOffsetPagination as ProjectsOffsetPagination, + type ProjectCreateParams as ProjectCreateParams, + type ProjectUpdateParams as ProjectUpdateParams, + type ProjectListParams as ProjectListParams, + }; + export { CredentialProviders as CredentialProviders, type CreateCredentialProviderRequest as CreateCredentialProviderRequest, diff --git a/src/resources/index.ts b/src/resources/index.ts index a5b082c1..312dbe0f 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -96,6 +96,16 @@ export { type InvocationListResponsesOffsetPagination, } from './invocations'; export { Profiles, type ProfileCreateParams, type ProfileListParams } from './profiles'; +export { + Projects, + type CreateProjectRequest, + type Project, + type UpdateProjectRequest, + type ProjectCreateParams, + type ProjectUpdateParams, + type ProjectListParams, + type ProjectsOffsetPagination, +} from './projects/projects'; export { Proxies, type ProxyCreateResponse, diff --git a/src/resources/projects.ts b/src/resources/projects.ts new file mode 100644 index 00000000..f9985fc3 --- /dev/null +++ b/src/resources/projects.ts @@ -0,0 +1,3 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export * from './projects/index'; diff --git a/src/resources/projects/index.ts b/src/resources/projects/index.ts new file mode 100644 index 00000000..7cbfa6a8 --- /dev/null +++ b/src/resources/projects/index.ts @@ -0,0 +1,18 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export { + Limits, + type ProjectLimits, + type UpdateProjectLimitsRequest, + type LimitUpdateParams, +} from './limits'; +export { + Projects, + type CreateProjectRequest, + type Project, + type UpdateProjectRequest, + type ProjectCreateParams, + type ProjectUpdateParams, + type ProjectListParams, + type ProjectsOffsetPagination, +} from './projects'; diff --git a/src/resources/projects/limits.ts b/src/resources/projects/limits.ts new file mode 100644 index 00000000..5475e4db --- /dev/null +++ b/src/resources/projects/limits.ts @@ -0,0 +1,128 @@ +// 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 { RequestOptions } from '../../internal/request-options'; +import { path } from '../../internal/utils/path'; + +/** + * Create and manage projects for resource isolation within an organization. + */ +export class Limits extends APIResource { + /** + * Get the resource limit overrides for a project. Null values mean no + * project-level cap (org limit applies). + * + * @example + * ```ts + * const projectLimits = await client.projects.limits.retrieve( + * 'id', + * ); + * ``` + */ + retrieve(id: string, options?: RequestOptions): APIPromise { + return this._client.get(path`/projects/${id}/limits`, options); + } + + /** + * Update resource limit overrides for a project. Only fields present in the + * request are modified. Set a field to 0 to remove that limit cap; omit a field to + * leave it unchanged. + * + * @example + * ```ts + * const projectLimits = await client.projects.limits.update( + * 'id', + * ); + * ``` + */ + update(id: string, body: LimitUpdateParams, options?: RequestOptions): APIPromise { + return this._client.patch(path`/projects/${id}/limits`, { body, ...options }); + } +} + +export interface ProjectLimits { + /** + * Maximum concurrent app invocations for this project. Null means no project-level + * cap. + */ + max_concurrent_invocations?: number | null; + + /** + * Maximum concurrent browser sessions for this project. Null means no + * project-level cap. + */ + max_concurrent_sessions?: number | null; + + /** + * Maximum persistent browser sessions for this project. Null means no + * project-level cap. + */ + max_persistent_sessions?: number | null; + + /** + * Maximum pooled sessions capacity for this project. Null means no project-level + * cap. + */ + max_pooled_sessions?: number | null; +} + +export interface UpdateProjectLimitsRequest { + /** + * Maximum concurrent app invocations for this project. Set to 0 to remove the cap; + * omit to leave unchanged. + */ + max_concurrent_invocations?: number | null; + + /** + * Maximum concurrent browser sessions for this project. Set to 0 to remove the + * cap; omit to leave unchanged. + */ + max_concurrent_sessions?: number | null; + + /** + * Maximum persistent browser sessions for this project. Set to 0 to remove the + * cap; omit to leave unchanged. + */ + max_persistent_sessions?: number | null; + + /** + * Maximum pooled sessions capacity for this project. Set to 0 to remove the cap; + * omit to leave unchanged. + */ + max_pooled_sessions?: number | null; +} + +export interface LimitUpdateParams { + /** + * Maximum concurrent app invocations for this project. Set to 0 to remove the cap; + * omit to leave unchanged. + */ + max_concurrent_invocations?: number | null; + + /** + * Maximum concurrent browser sessions for this project. Set to 0 to remove the + * cap; omit to leave unchanged. + */ + max_concurrent_sessions?: number | null; + + /** + * Maximum persistent browser sessions for this project. Set to 0 to remove the + * cap; omit to leave unchanged. + */ + max_persistent_sessions?: number | null; + + /** + * Maximum pooled sessions capacity for this project. Set to 0 to remove the cap; + * omit to leave unchanged. + */ + max_pooled_sessions?: number | null; +} + +export declare namespace Limits { + export { + type ProjectLimits as ProjectLimits, + type UpdateProjectLimitsRequest as UpdateProjectLimitsRequest, + type LimitUpdateParams as LimitUpdateParams, + }; +} diff --git a/src/resources/projects/projects.ts b/src/resources/projects/projects.ts new file mode 100644 index 00000000..142531fa --- /dev/null +++ b/src/resources/projects/projects.ts @@ -0,0 +1,179 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../core/resource'; +import * as LimitsAPI from './limits'; +import { LimitUpdateParams, Limits, ProjectLimits, UpdateProjectLimitsRequest } from './limits'; +import { APIPromise } from '../../core/api-promise'; +import { OffsetPagination, type OffsetPaginationParams, PagePromise } from '../../core/pagination'; +import { buildHeaders } from '../../internal/headers'; +import { RequestOptions } from '../../internal/request-options'; +import { path } from '../../internal/utils/path'; + +/** + * Create and manage projects for resource isolation within an organization. + */ +export class Projects extends APIResource { + limits: LimitsAPI.Limits = new LimitsAPI.Limits(this._client); + + /** + * Create a new project within the authenticated organization. Requires a paid plan + * and the projects feature flag. + * + * @example + * ```ts + * const project = await client.projects.create({ + * name: 'staging', + * }); + * ``` + */ + create(body: ProjectCreateParams, options?: RequestOptions): APIPromise { + return this._client.post('/projects', { body, ...options }); + } + + /** + * Get a project by ID. + * + * @example + * ```ts + * const project = await client.projects.retrieve('id'); + * ``` + */ + retrieve(id: string, options?: RequestOptions): APIPromise { + return this._client.get(path`/projects/${id}`, options); + } + + /** + * Update a project's name or status. + * + * @example + * ```ts + * const project = await client.projects.update('id'); + * ``` + */ + update(id: string, body: ProjectUpdateParams, options?: RequestOptions): APIPromise { + return this._client.patch(path`/projects/${id}`, { body, ...options }); + } + + /** + * List projects for the authenticated organization. + * + * @example + * ```ts + * // Automatically fetches more pages as needed. + * for await (const project of client.projects.list()) { + * // ... + * } + * ``` + */ + list( + query: ProjectListParams | null | undefined = {}, + options?: RequestOptions, + ): PagePromise { + return this._client.getAPIList('/projects', OffsetPagination, { query, ...options }); + } + + /** + * Soft-delete a project. The project must be empty (no active resources). + * + * @example + * ```ts + * await client.projects.delete('id'); + * ``` + */ + delete(id: string, options?: RequestOptions): APIPromise { + return this._client.delete(path`/projects/${id}`, { + ...options, + headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), + }); + } +} + +export type ProjectsOffsetPagination = OffsetPagination; + +export interface CreateProjectRequest { + /** + * Project name (1-255 characters) + */ + name: string; +} + +export interface Project { + /** + * Unique project identifier + */ + id: string; + + /** + * When the project was created + */ + created_at: string; + + /** + * Project name + */ + name: string; + + /** + * Project status + */ + status: 'active' | 'archived'; + + /** + * When the project was last updated + */ + updated_at: string; +} + +export interface UpdateProjectRequest { + /** + * New project name + */ + name?: string; + + /** + * New project status + */ + status?: 'active' | 'archived'; +} + +export interface ProjectCreateParams { + /** + * Project name (1-255 characters) + */ + name: string; +} + +export interface ProjectUpdateParams { + /** + * New project name + */ + name?: string; + + /** + * New project status + */ + status?: 'active' | 'archived'; +} + +export interface ProjectListParams extends OffsetPaginationParams {} + +Projects.Limits = Limits; + +export declare namespace Projects { + export { + type CreateProjectRequest as CreateProjectRequest, + type Project as Project, + type UpdateProjectRequest as UpdateProjectRequest, + type ProjectsOffsetPagination as ProjectsOffsetPagination, + type ProjectCreateParams as ProjectCreateParams, + type ProjectUpdateParams as ProjectUpdateParams, + type ProjectListParams as ProjectListParams, + }; + + export { + Limits as Limits, + type ProjectLimits as ProjectLimits, + type UpdateProjectLimitsRequest as UpdateProjectLimitsRequest, + type LimitUpdateParams as LimitUpdateParams, + }; +} diff --git a/tests/api-resources/projects/limits.test.ts b/tests/api-resources/projects/limits.test.ts new file mode 100644 index 00000000..61b40cae --- /dev/null +++ b/tests/api-resources/projects/limits.test.ts @@ -0,0 +1,34 @@ +// 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 limits', () => { + // Mock server tests are disabled + test.skip('retrieve', async () => { + const responsePromise = client.projects.limits.retrieve('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); + }); + + // Mock server tests are disabled + test.skip('update', async () => { + const responsePromise = client.projects.limits.update('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); + }); +}); diff --git a/tests/api-resources/projects/projects.test.ts b/tests/api-resources/projects/projects.test.ts new file mode 100644 index 00000000..d3fb12ee --- /dev/null +++ b/tests/api-resources/projects/projects.test.ts @@ -0,0 +1,83 @@ +// 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 projects', () => { + // Mock server tests are disabled + test.skip('create: only required params', async () => { + const responsePromise = client.projects.create({ name: 'staging' }); + 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); + }); + + // Mock server tests are disabled + test.skip('create: required and optional params', async () => { + const response = await client.projects.create({ name: 'staging' }); + }); + + // Mock server tests are disabled + test.skip('retrieve', async () => { + const responsePromise = client.projects.retrieve('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); + }); + + // Mock server tests are disabled + test.skip('update', async () => { + const responsePromise = client.projects.update('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); + }); + + // Mock server tests are disabled + test.skip('list', async () => { + const responsePromise = client.projects.list(); + 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); + }); + + // Mock server tests are disabled + test.skip('list: 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.projects.list({ limit: 100, offset: 0 }, { path: '/_stainless_unknown_path' }), + ).rejects.toThrow(Kernel.NotFoundError); + }); + + // Mock server tests are disabled + test.skip('delete', async () => { + const responsePromise = client.projects.delete('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); + }); +}); From a6d105a270d42fbbf047d831cc1f474a7ad3186c Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 10 Apr 2026 13:46:37 +0000 Subject: [PATCH 355/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 3bafaeb4..1383393b 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.47.0" + ".": "0.48.0" } diff --git a/package.json b/package.json index 7564d5d4..7de23aed 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.47.0", + "version": "0.48.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index d84ba019..71ccf04c 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.47.0'; // x-release-please-version +export const VERSION = '0.48.0'; // x-release-please-version From e1f63d54647e7c0f851704829c86eddbd137e358 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 10 Apr 2026 16:29:04 +0000 Subject: [PATCH 356/551] feat: Raise replay framerate limit from 20 to 60 fps --- .stats.yml | 4 ++-- src/resources/browsers/replays.ts | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.stats.yml b/.stats.yml index db7b03c8..481f7d4d 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_hash: 3aa6ab6939790f538332054162fbdedc -config_hash: 9818dd634f87b677410eefd013d7a179 +openapi_spec_hash: 8670a9860c54682b158924e990d4de31 +config_hash: b12b028d6aa7564db0983135073805e3 diff --git a/src/resources/browsers/replays.ts b/src/resources/browsers/replays.ts index 7ac768d9..6b944fac 100644 --- a/src/resources/browsers/replays.ts +++ b/src/resources/browsers/replays.ts @@ -143,7 +143,8 @@ export interface ReplayDownloadParams { export interface ReplayStartParams { /** - * Recording framerate in fps. + * Recording framerate in fps. Values above 20 require GPU to be enabled on the + * browser session. */ framerate?: number; From 99581b3123581fc8b38ee19446409a84603ab9ff Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 10 Apr 2026 17:32:41 +0000 Subject: [PATCH 357/551] feat: Neil/kernel 1180 fuzzy matching for browser pools --- .stats.yml | 4 ++-- src/resources/browsers/browsers.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.stats.yml b/.stats.yml index 481f7d4d..ad1b0f25 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_hash: 8670a9860c54682b158924e990d4de31 -config_hash: b12b028d6aa7564db0983135073805e3 +openapi_spec_hash: 0ffef6a95f9d9b1096180fc5e4c5b39c +config_hash: 9818dd634f87b677410eefd013d7a179 diff --git a/src/resources/browsers/browsers.ts b/src/resources/browsers/browsers.ts index 2e1264b2..c4a910eb 100644 --- a/src/resources/browsers/browsers.ts +++ b/src/resources/browsers/browsers.ts @@ -841,7 +841,7 @@ export interface BrowserListParams extends OffsetPaginationParams { include_deleted?: boolean; /** - * Search browsers by session ID, profile ID, or proxy ID. + * Search browsers by session ID, profile ID, proxy ID, or pool name. */ query?: string; From fd064f994248e4477f449ff491ca64d1327bb77e 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:49 +0000 Subject: [PATCH 358/551] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index ad1b0f25..6b88334e 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 3e2a82abcffb50856c61676e30a4ea6bc0c50df3 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 13 Apr 2026 02:11:47 +0000 Subject: [PATCH 359/551] chore(internal): codegen related update --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index e5e2a93b..f6eae3cd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1220,9 +1220,9 @@ baseline-browser-mapping@^2.9.0: integrity sha512-B0xUquLkiGLgHhpPBqvl7GWegWBUNuujQ6kXd/r1U38ElPT6Ok8KZ8e+FpUGEc2ZoRQUzq/aUnaKFc/svWUGSg== brace-expansion@^2.0.2: - version "2.0.3" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.3.tgz#0493338bdd58e319b1039c67cf7ee439892c01d9" - integrity sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA== + version "2.1.0" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.1.0.tgz#4f41a41190216ee36067ec381526fe9539c4f0ae" + integrity sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w== dependencies: balanced-match "^1.0.0" From 1519082f75aafd0ed869663bee27a8c28ab73a0e 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:19 +0000 Subject: [PATCH 360/551] feat: add POST /browsers/{id}/curl and /curl/raw endpoints --- .stats.yml | 8 +- api.md | 2 + src/client.ts | 4 + src/resources/browsers/browsers.ts | 75 +++++++++++++++++++ src/resources/browsers/index.ts | 2 + src/resources/index.ts | 2 + tests/api-resources/browsers/browsers.test.ts | 24 ++++++ 7 files changed, 113 insertions(+), 4 deletions(-) diff --git a/.stats.yml b/.stats.yml index 6b88334e..f0ba92fd 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 4f2faea0..ba877c96 100644 --- a/api.md +++ b/api.md @@ -74,6 +74,7 @@ Types: - BrowserRetrieveResponse - BrowserUpdateResponse - BrowserListResponse +- BrowserCurlResponse Methods: @@ -82,6 +83,7 @@ Methods: - client.browsers.update(id, { ...params }) -> BrowserUpdateResponse - client.browsers.list({ ...params }) -> BrowserListResponsesOffsetPagination - client.browsers.delete({ ...params }) -> void +- client.browsers.curl(id, { ...params }) -> BrowserCurlResponse - client.browsers.deleteByID(id) -> void - client.browsers.loadExtensions(id, { ...params }) -> void diff --git a/src/client.ts b/src/client.ts index c39f1161..e116cd86 100644 --- a/src/client.ts +++ b/src/client.ts @@ -102,6 +102,8 @@ import { Auth } from './resources/auth/auth'; import { BrowserCreateParams, BrowserCreateResponse, + BrowserCurlParams, + BrowserCurlResponse, BrowserDeleteParams, BrowserListParams, BrowserListResponse, @@ -990,12 +992,14 @@ export declare namespace Kernel { type BrowserRetrieveResponse as BrowserRetrieveResponse, type BrowserUpdateResponse as BrowserUpdateResponse, type BrowserListResponse as BrowserListResponse, + type BrowserCurlResponse as BrowserCurlResponse, type BrowserListResponsesOffsetPagination as BrowserListResponsesOffsetPagination, type BrowserCreateParams as BrowserCreateParams, type BrowserRetrieveParams as BrowserRetrieveParams, type BrowserUpdateParams as BrowserUpdateParams, type BrowserListParams as BrowserListParams, type BrowserDeleteParams as BrowserDeleteParams, + type BrowserCurlParams as BrowserCurlParams, type BrowserLoadExtensionsParams as BrowserLoadExtensionsParams, }; diff --git a/src/resources/browsers/browsers.ts b/src/resources/browsers/browsers.ts index c4a910eb..61873f31 100644 --- a/src/resources/browsers/browsers.ts +++ b/src/resources/browsers/browsers.ts @@ -168,6 +168,22 @@ export class Browsers extends APIResource { }); } + /** + * 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. + * + * @example + * ```ts + * const response = await client.browsers.curl('id', { + * url: 'url', + * }); + * ``` + */ + curl(id: string, body: BrowserCurlParams, options?: RequestOptions): APIPromise { + return this._client.post(path`/browsers/${id}/curl`, { body, ...options }); + } + /** * Delete a browser session by ID * @@ -706,6 +722,31 @@ export interface BrowserListResponse { viewport?: Shared.BrowserViewport; } +/** + * Structured response from the browser curl request. + */ +export interface BrowserCurlResponse { + /** + * Response body (UTF-8 string or base64 depending on request). + */ + body: string; + + /** + * Total request duration in milliseconds. + */ + duration_ms: number; + + /** + * Response headers (multi-value). + */ + headers: { [key: string]: Array }; + + /** + * HTTP status code from target. + */ + status: number; +} + export interface BrowserCreateParams { /** * List of browser extensions to load into the session. Provide each by id or name. @@ -859,6 +900,38 @@ export interface BrowserDeleteParams { persistent_id: string; } +export interface BrowserCurlParams { + /** + * Target URL (must be http or https). + */ + url: string; + + /** + * Request body (for POST/PUT/PATCH). + */ + body?: string; + + /** + * Custom headers merged with browser defaults. + */ + headers?: { [key: string]: string }; + + /** + * HTTP method. + */ + method?: 'GET' | 'HEAD' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'OPTIONS'; + + /** + * Encoding for the response body. Use base64 for binary content. + */ + response_encoding?: 'utf8' | 'base64'; + + /** + * Request timeout in milliseconds. + */ + timeout_ms?: number; +} + export interface BrowserLoadExtensionsParams { /** * List of extensions to upload and activate @@ -898,12 +971,14 @@ export declare namespace Browsers { type BrowserRetrieveResponse as BrowserRetrieveResponse, type BrowserUpdateResponse as BrowserUpdateResponse, type BrowserListResponse as BrowserListResponse, + type BrowserCurlResponse as BrowserCurlResponse, type BrowserListResponsesOffsetPagination as BrowserListResponsesOffsetPagination, type BrowserCreateParams as BrowserCreateParams, type BrowserRetrieveParams as BrowserRetrieveParams, type BrowserUpdateParams as BrowserUpdateParams, type BrowserListParams as BrowserListParams, type BrowserDeleteParams as BrowserDeleteParams, + type BrowserCurlParams as BrowserCurlParams, type BrowserLoadExtensionsParams as BrowserLoadExtensionsParams, }; diff --git a/src/resources/browsers/index.ts b/src/resources/browsers/index.ts index 4af2fb19..e38f0732 100644 --- a/src/resources/browsers/index.ts +++ b/src/resources/browsers/index.ts @@ -10,11 +10,13 @@ export { type BrowserRetrieveResponse, type BrowserUpdateResponse, type BrowserListResponse, + type BrowserCurlResponse, type BrowserCreateParams, type BrowserRetrieveParams, type BrowserUpdateParams, type BrowserListParams, type BrowserDeleteParams, + type BrowserCurlParams, type BrowserLoadExtensionsParams, type ProfilesOffsetPagination, type BrowserListResponsesOffsetPagination, diff --git a/src/resources/index.ts b/src/resources/index.ts index 312dbe0f..789de808 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -29,11 +29,13 @@ export { type BrowserRetrieveResponse, type BrowserUpdateResponse, type BrowserListResponse, + type BrowserCurlResponse, type BrowserCreateParams, type BrowserRetrieveParams, type BrowserUpdateParams, type BrowserListParams, type BrowserDeleteParams, + type BrowserCurlParams, type BrowserLoadExtensionsParams, type ProfilesOffsetPagination, type BrowserListResponsesOffsetPagination, diff --git a/tests/api-resources/browsers/browsers.test.ts b/tests/api-resources/browsers/browsers.test.ts index e4f99975..0c2f5740 100644 --- a/tests/api-resources/browsers/browsers.test.ts +++ b/tests/api-resources/browsers/browsers.test.ts @@ -133,6 +133,30 @@ describe('resource browsers', () => { const response = await client.browsers.delete({ persistent_id: 'persistent_id' }); }); + // Mock server tests are disabled + test.skip('curl: only required params', async () => { + const responsePromise = client.browsers.curl('id', { url: 'url' }); + 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); + }); + + // Mock server tests are disabled + test.skip('curl: required and optional params', async () => { + const response = await client.browsers.curl('id', { + url: 'url', + body: 'body', + headers: { foo: 'string' }, + method: 'GET', + response_encoding: 'utf8', + timeout_ms: 1000, + }); + }); + // Mock server tests are disabled test.skip('deleteByID', async () => { const responsePromise = client.browsers.deleteByID('htzv5orfit78e1m2biiifpbv'); From a03f37d694323b2509790739607370493cb1cd4a Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 20 Apr 2026 03:54:05 +0000 Subject: [PATCH 361/551] fix: include MFA and sign-in options in CUA SSO-only step response --- .stats.yml | 4 ++-- src/resources/auth/connections.ts | 12 ++++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index f0ba92fd..a0c2ee4b 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 112 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-930823e8b25b4644b74098ad5479840f64a329321aa236460f8a9562ae9051bf.yml -openapi_spec_hash: 9f868e67df8fd2fec8d8fc3eb5ba0b26 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-57bfd737f612a4f16965ef7eb85f709752f616a3941c451736a9ad76e4a1135f.yml +openapi_spec_hash: 61d13a607970deefff0cbfe6b77ae6e8 config_hash: 08d55086449943a8fec212b870061a3f diff --git a/src/resources/auth/connections.ts b/src/resources/auth/connections.ts index 09ffe71e..852cd6b4 100644 --- a/src/resources/auth/connections.ts +++ b/src/resources/auth/connections.ts @@ -433,6 +433,12 @@ export namespace ManagedAuth { */ type: 'text' | 'email' | 'password' | 'tel' | 'number' | 'url' | 'code' | 'totp'; + /** + * Contextual help text near the field that tells the user what to enter (e.g., + * "Enter the phone ending in (**_) _**-\*\*92") + */ + hint?: string; + /** * If this field is associated with an MFA option, the type of that option (e.g., * password field linked to "Enter password" option) @@ -890,6 +896,12 @@ export namespace ConnectionFollowResponse { */ type: 'text' | 'email' | 'password' | 'tel' | 'number' | 'url' | 'code' | 'totp'; + /** + * Contextual help text near the field that tells the user what to enter (e.g., + * "Enter the phone ending in (**_) _**-\*\*92") + */ + hint?: string; + /** * If this field is associated with an MFA option, the type of that option (e.g., * password field linked to "Enter password" option) From 675ff4d1b13d5ca259d1228d6878fc75d247d364 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 20 Apr 2026 23:08:53 +0000 Subject: [PATCH 362/551] feat: remove paid plan gating from project endpoints --- .stats.yml | 4 ++-- src/resources/projects/projects.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.stats.yml b/.stats.yml index a0c2ee4b..bed10345 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 112 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-57bfd737f612a4f16965ef7eb85f709752f616a3941c451736a9ad76e4a1135f.yml -openapi_spec_hash: 61d13a607970deefff0cbfe6b77ae6e8 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-686a9addd4f9356ca26ff3ff04e1a11466d77a412859829075566394922b715d.yml +openapi_spec_hash: 7a9e9c2023400d44bcbfb87b7ec07708 config_hash: 08d55086449943a8fec212b870061a3f diff --git a/src/resources/projects/projects.ts b/src/resources/projects/projects.ts index 142531fa..b2d1219c 100644 --- a/src/resources/projects/projects.ts +++ b/src/resources/projects/projects.ts @@ -16,8 +16,8 @@ export class Projects extends APIResource { limits: LimitsAPI.Limits = new LimitsAPI.Limits(this._client); /** - * Create a new project within the authenticated organization. Requires a paid plan - * and the projects feature flag. + * Create a new project within the authenticated organization. Requires the + * projects feature flag. * * @example * ```ts From 179568b4b3e03f7b67612b9a9fe34ac6f40bb645 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 21 Apr 2026 15:38:41 +0000 Subject: [PATCH 363/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 1383393b..febc17a4 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.48.0" + ".": "0.50.0" } diff --git a/package.json b/package.json index 7de23aed..a6b2e8f5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.48.0", + "version": "0.50.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 71ccf04c..049e29ec 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.48.0'; // x-release-please-version +export const VERSION = '0.50.0'; // x-release-please-version From 825bc8089bcdc7f16bad606b11ac3e37d2c409ac Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 23 Apr 2026 03:08:42 +0000 Subject: [PATCH 364/551] chore(internal): more robust bootstrap script --- scripts/bootstrap | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/bootstrap b/scripts/bootstrap index a8b69ff3..2e315f53 100755 --- a/scripts/bootstrap +++ b/scripts/bootstrap @@ -4,7 +4,7 @@ set -e cd "$(dirname "$0")/.." -if [ -f "Brewfile" ] && [ "$(uname -s)" = "Darwin" ] && [ "$SKIP_BREW" != "1" ] && [ -t 0 ]; then +if [ -f "Brewfile" ] && [ "$(uname -s)" = "Darwin" ] && [ "${SKIP_BREW:-}" != "1" ] && [ -t 0 ]; then brew bundle check >/dev/null 2>&1 || { echo -n "==> Install Homebrew dependencies? (y/N): " read -r response From 276d18258ba7db173ba1e2af783781835a9092d9 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 24 Apr 2026 17:57:02 +0000 Subject: [PATCH 365/551] feat: Expose browser_session_id on managed auth connection --- .stats.yml | 4 ++-- src/resources/auth/connections.ts | 7 +++++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index bed10345..fec95fa1 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 112 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-686a9addd4f9356ca26ff3ff04e1a11466d77a412859829075566394922b715d.yml -openapi_spec_hash: 7a9e9c2023400d44bcbfb87b7ec07708 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-e14974fd90680e5745b35d8718a1ccce2181f6d17a6e0a1fd35fc5bca88795ae.yml +openapi_spec_hash: 1b3aa75f0ab48b122d514047f9c82873 config_hash: 08d55086449943a8fec212b870061a3f diff --git a/src/resources/auth/connections.ts b/src/resources/auth/connections.ts index 852cd6b4..53f96373 100644 --- a/src/resources/auth/connections.ts +++ b/src/resources/auth/connections.ts @@ -244,6 +244,13 @@ export interface ManagedAuth { */ allowed_domains?: Array; + /** + * ID of the underlying browser session driving the current flow (present when flow + * in progress). Use this to inspect or terminate the browser session via the + * `/browsers` API. + */ + browser_session_id?: string | null; + /** * Whether automatic re-authentication is possible (has credential, selectors, and * login_url) From 74e11a04772013a5ad311affee4a0f086ac3a3fe Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 25 Apr 2026 16:29:21 +0000 Subject: [PATCH 366/551] feat: Expire stuck IN_PROGRESS managed auth sessions via background worker --- .stats.yml | 4 ++-- src/resources/auth/connections.ts | 18 ++++++++++++++++-- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/.stats.yml b/.stats.yml index fec95fa1..d58220c1 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 112 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-e14974fd90680e5745b35d8718a1ccce2181f6d17a6e0a1fd35fc5bca88795ae.yml -openapi_spec_hash: 1b3aa75f0ab48b122d514047f9c82873 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-a674e3c4c0063942621d1b4e7f67b72f7e240c12dd88564fe16627618ba33dd6.yml +openapi_spec_hash: 8b97c87f0dafe5fc5e5a7365f3687755 config_hash: 08d55086449943a8fec212b870061a3f diff --git a/src/resources/auth/connections.ts b/src/resources/auth/connections.ts index 53f96373..256800dd 100644 --- a/src/resources/auth/connections.ts +++ b/src/resources/auth/connections.ts @@ -293,7 +293,10 @@ export interface ManagedAuth { external_action_message?: string | null; /** - * When the current flow expires (null when no flow in progress) + * When the current flow expires (null when no flow in progress). A flow past this + * timestamp is no longer valid and its `flow_status` will be `EXPIRED`. Clients + * may start a new login to supersede a stale `IN_PROGRESS` flow past this + * timestamp. */ flow_expires_at?: string | null; @@ -333,10 +336,21 @@ export interface ManagedAuth { hosted_url?: string | null; /** - * When the profile was last successfully authenticated + * @deprecated Deprecated alias for `last_auth_check_at`. Despite the name, this is + * the last health-check timestamp, not the last successful authentication. Use + * `last_auth_check_at` instead. */ last_auth_at?: string; + /** + * When the most recent auth health check ran for this connection, regardless of + * outcome. Updated on every health check and does not by itself indicate that the + * profile is currently authenticated - use `status` for that. May be newer than + * `flow_expires_at` when a flow is still in progress because health checks + * continue to run in parallel. + */ + last_auth_check_at?: string; + /** * Browser live view URL for debugging (present when flow in progress) */ From 13dde69beb39a83dce6768c9b2f518b6fe34e577 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 27 Apr 2026 19:54:42 +0000 Subject: [PATCH 367/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index febc17a4..75d439ac 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.50.0" + ".": "0.51.0" } diff --git a/package.json b/package.json index a6b2e8f5..81abc96a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.50.0", + "version": "0.51.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 049e29ec..7768f744 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.50.0'; // x-release-please-version +export const VERSION = '0.51.0'; // x-release-please-version From 1ba1d010f71dcd7a78b3566a0e3b82ac9527095f Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 28 Apr 2026 03:03:06 +0000 Subject: [PATCH 368/551] chore(internal): codegen related update --- scripts/utils/postprocess-files.cjs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/scripts/utils/postprocess-files.cjs b/scripts/utils/postprocess-files.cjs index deae575e..a8cdeb7c 100644 --- a/scripts/utils/postprocess-files.cjs +++ b/scripts/utils/postprocess-files.cjs @@ -23,12 +23,19 @@ async function postprocess() { // strip out lib="dom", types="node", and types="react" references; these // are needed at build time, but would pollute the user's TS environment - const transformed = code.replace( + let transformed = code.replace( /^ *\/\/\/ * ' '.repeat(match.length - 1) + '\n', ); + // TypeScript's declaration emitter collapses /** @ts-ignore */ onto the same + // line as the type declaration, which doesn't work. So we convert to // @ts-ignore + // on its own line to properly suppresses errors. + if (file.endsWith('.d.ts') || file.endsWith('.d.mts') || file.endsWith('.d.cts')) { + transformed = transformed.replace(/\/\*\* @ts-ignore\b[^*]*\*\/ /gm, '// @ts-ignore\n'); + } + if (transformed !== code) { console.error(`wrote ${path.relative(process.cwd(), file)}`); await fs.promises.writeFile(file, transformed, 'utf8'); From 429d084722d64a2548c147be6b22264abed3e58e Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 28 Apr 2026 03:03:49 +0000 Subject: [PATCH 369/551] feat: support setting headers via env --- src/client.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/client.ts b/src/client.ts index e116cd86..871ea9e7 100644 --- a/src/client.ts +++ b/src/client.ts @@ -302,6 +302,18 @@ export class Kernel { this.fetch = options.fetch ?? Shims.getDefaultFetch(); this.#encoder = Opts.FallbackEncoder; + const customHeadersEnv = readEnv('KERNEL_CUSTOM_HEADERS'); + if (customHeadersEnv) { + const parsed: Record = {}; + for (const line of customHeadersEnv.split('\n')) { + const colon = line.indexOf(':'); + if (colon >= 0) { + parsed[line.substring(0, colon).trim()] = line.substring(colon + 1).trim(); + } + } + options.defaultHeaders = { ...parsed, ...options.defaultHeaders }; + } + this._options = options; this.apiKey = apiKey; From 9e4d117a5dd5132ddba8710fc11677f72955a44f Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 29 Apr 2026 07:57:01 +0000 Subject: [PATCH 370/551] chore(format): run eslint and prettier separately --- .github/workflows/release-doctor.yml | 1 - eslint.config.mjs | 3 --- package.json | 1 - scripts/fast-format | 9 +++----- scripts/format | 3 +-- scripts/lint | 3 +++ src/internal/types.ts | 14 ++++++------ yarn.lock | 32 ---------------------------- 8 files changed, 13 insertions(+), 53 deletions(-) diff --git a/.github/workflows/release-doctor.yml b/.github/workflows/release-doctor.yml index 2d0c9317..42e30af8 100644 --- a/.github/workflows/release-doctor.yml +++ b/.github/workflows/release-doctor.yml @@ -17,4 +17,3 @@ jobs: - name: Check release environment run: | bash ./bin/check-release-environment - diff --git a/eslint.config.mjs b/eslint.config.mjs index 341aac52..1fcecb1e 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -1,7 +1,6 @@ // @ts-check import tseslint from 'typescript-eslint'; import unusedImports from 'eslint-plugin-unused-imports'; -import prettier from 'eslint-plugin-prettier'; export default tseslint.config( { @@ -14,11 +13,9 @@ export default tseslint.config( plugins: { '@typescript-eslint': tseslint.plugin, 'unused-imports': unusedImports, - prettier, }, rules: { 'no-unused-vars': 'off', - 'prettier/prettier': 'error', 'unused-imports/no-unused-imports': 'error', 'no-restricted-imports': [ 'error', diff --git a/package.json b/package.json index 81abc96a..8ae3f494 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,6 @@ "@typescript-eslint/eslint-plugin": "8.31.1", "@typescript-eslint/parser": "8.31.1", "eslint": "^9.39.1", - "eslint-plugin-prettier": "^5.4.1", "eslint-plugin-unused-imports": "^4.1.4", "iconv-lite": "^0.6.3", "jest": "^29.4.0", diff --git a/scripts/fast-format b/scripts/fast-format index 53721ac0..f1873aef 100755 --- a/scripts/fast-format +++ b/scripts/fast-format @@ -31,10 +31,7 @@ if ! [ -z "$ESLINT_FILES" ]; then fi echo "==> Running prettier --write" -# format things eslint didn't -PRETTIER_FILES="$(grep '\.\(js\|json\)$' "$FILE_LIST" || true)" -if ! [ -z "$PRETTIER_FILES" ]; then - echo "$PRETTIER_FILES" | xargs ./node_modules/.bin/prettier \ - --write --cache --cache-strategy metadata --no-error-on-unmatched-pattern \ - '!**/dist' '!**/*.ts' '!**/*.mts' '!**/*.cts' '!**/*.js' '!**/*.mjs' '!**/*.cjs' +if ! [ -z "$FILE_LIST" ]; then + cat "$FILE_LIST" | xargs ./node_modules/.bin/prettier \ + --write --cache --cache-strategy metadata --no-error-on-unmatched-pattern --ignore-unknown fi diff --git a/scripts/format b/scripts/format index 7a756401..b1b2c17a 100755 --- a/scripts/format +++ b/scripts/format @@ -8,5 +8,4 @@ echo "==> Running eslint --fix" ./node_modules/.bin/eslint --fix . echo "==> Running prettier --write" -# format things eslint didn't -./node_modules/.bin/prettier --write --cache --cache-strategy metadata . '!**/dist' '!**/*.ts' '!**/*.mts' '!**/*.cts' '!**/*.js' '!**/*.mjs' '!**/*.cjs' +./node_modules/.bin/prettier --write --cache --cache-strategy metadata . diff --git a/scripts/lint b/scripts/lint index 3ffb78a6..1f532548 100755 --- a/scripts/lint +++ b/scripts/lint @@ -4,6 +4,9 @@ set -e cd "$(dirname "$0")/.." +echo "==> Running prettier --check" +./node_modules/.bin/prettier --check . + echo "==> Running eslint" ./node_modules/.bin/eslint . diff --git a/src/internal/types.ts b/src/internal/types.ts index b668dfc0..a050513a 100644 --- a/src/internal/types.ts +++ b/src/internal/types.ts @@ -40,7 +40,6 @@ type OverloadedParameters = : T extends (...args: infer A) => unknown ? A : never; -/* eslint-disable */ /** * These imports attempt to get types from a parent package's dependencies. * Unresolved bare specifiers can trigger [automatic type acquisition][1] in some projects, which @@ -63,19 +62,18 @@ type OverloadedParameters = * * [1]: https://www.typescriptlang.org/tsconfig/#typeAcquisition */ -/** @ts-ignore For users with \@types/node */ +/** @ts-ignore For users with \@types/node */ /* prettier-ignore */ type UndiciTypesRequestInit = NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny; -/** @ts-ignore For users with undici */ +/** @ts-ignore For users with undici */ /* prettier-ignore */ type UndiciRequestInit = NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny; -/** @ts-ignore For users with \@types/bun */ +/** @ts-ignore For users with \@types/bun */ /* prettier-ignore */ type BunRequestInit = globalThis.FetchRequestInit; -/** @ts-ignore For users with node-fetch@2 */ +/** @ts-ignore For users with node-fetch@2 */ /* prettier-ignore */ type NodeFetch2RequestInit = NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny; -/** @ts-ignore For users with node-fetch@3, doesn't need file extension because types are at ./@types/index.d.ts */ +/** @ts-ignore For users with node-fetch@3, doesn't need file extension because types are at ./@types/index.d.ts */ /* prettier-ignore */ type NodeFetch3RequestInit = NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny; -/** @ts-ignore For users who use Deno */ +/** @ts-ignore For users who use Deno */ /* prettier-ignore */ type FetchRequestInit = NonNullable[1]>; -/* eslint-enable */ type RequestInits = | NotAny diff --git a/yarn.lock b/yarn.lock index f6eae3cd..18e7cbdc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -709,11 +709,6 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" -"@pkgr/core@^0.2.4": - version "0.2.4" - resolved "https://registry.yarnpkg.com/@pkgr/core/-/core-0.2.4.tgz#d897170a2b0ba51f78a099edccd968f7b103387c" - integrity sha512-ROFF39F6ZrnzSUEmQQZUar0Jt4xVoP9WnDRdWwF4NNcXs3xBTLgBUDoOwW141y1jP+S8nahIbdxbFC7IShw9Iw== - "@sinclair/typebox@^0.27.8": version "0.27.8" resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.27.8.tgz#6667fac16c436b5434a387a34dedb013198f6e6e" @@ -1515,14 +1510,6 @@ escape-string-regexp@^4.0.0: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== -eslint-plugin-prettier@^5.4.1: - version "5.4.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-5.4.1.tgz#99b55d7dd70047886b2222fdd853665f180b36af" - integrity sha512-9dF+KuU/Ilkq27A8idRP7N2DH8iUR6qXcjF3FR2wETY21PZdBrIjwCau8oboyGj9b7etWmTGEeM8e7oOed6ZWg== - dependencies: - prettier-linter-helpers "^1.0.0" - synckit "^0.11.7" - eslint-plugin-unused-imports@^4.1.4: version "4.1.4" resolved "https://registry.yarnpkg.com/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-4.1.4.tgz#62ddc7446ccbf9aa7b6f1f0b00a980423cda2738" @@ -1674,11 +1661,6 @@ fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== -fast-diff@^1.1.2: - version "1.3.0" - resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.3.0.tgz#ece407fa550a64d638536cd727e129c61616e0f0" - integrity sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw== - fast-glob@^3.3.2: version "3.3.2" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129" @@ -2841,13 +2823,6 @@ prelude-ls@^1.2.1: resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== -prettier-linter-helpers@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" - integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w== - dependencies: - fast-diff "^1.1.2" - prettier@^3.0.0: version "3.1.1" resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.1.1.tgz#6ba9f23165d690b6cbdaa88cb0807278f7019848" @@ -3144,13 +3119,6 @@ supports-preserve-symlinks-flag@^1.0.0: resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== -synckit@^0.11.7: - version "0.11.8" - resolved "https://registry.yarnpkg.com/synckit/-/synckit-0.11.8.tgz#b2aaae998a4ef47ded60773ad06e7cb821f55457" - integrity sha512-+XZ+r1XGIJGeQk3VvXhT6xx/VpbHsRzsTkGgF6E5RX9TTXD0118l87puaEBZ566FhqblC6U0d4XnubznJDm30A== - dependencies: - "@pkgr/core" "^0.2.4" - test-exclude@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" From dea28692986b0138fd2967cefb78c3e5bf5dfae3 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 29 Apr 2026 14:36:48 +0000 Subject: [PATCH 371/551] feat: profile download: 409 for empty profile + surface API errors in dashboard --- .stats.yml | 4 ++-- src/resources/profiles.ts | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/.stats.yml b/.stats.yml index d58220c1..33f284fe 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 112 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-a674e3c4c0063942621d1b4e7f67b72f7e240c12dd88564fe16627618ba33dd6.yml -openapi_spec_hash: 8b97c87f0dafe5fc5e5a7365f3687755 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-4ce09d1a7546ab36f578cb27d819187eeb90c580b11834c7ff7a375aa22f9a20.yml +openapi_spec_hash: 1043ab2d699f6c828680c3352cd4cece config_hash: 08d55086449943a8fec212b870061a3f diff --git a/src/resources/profiles.ts b/src/resources/profiles.ts index 4b9345c2..5d6c63c4 100644 --- a/src/resources/profiles.ts +++ b/src/resources/profiles.ts @@ -49,8 +49,7 @@ export class Profiles extends APIResource { } /** - * Download the profile. Profiles are JSON files containing the pieces of state - * that we save. + * Returns a zstd-compressed tar file of the full user-data directory. */ download(idOrName: string, options?: RequestOptions): APIPromise { return this._client.get(path`/profiles/${idOrName}/download`, { From 08c3072550c220958af8e7579d60a5dbe88c7b5a Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 29 Apr 2026 15:35:04 +0000 Subject: [PATCH 372/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 75d439ac..acba76f8 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.51.0" + ".": "0.52.0" } diff --git a/package.json b/package.json index 8ae3f494..f994a099 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.51.0", + "version": "0.52.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 7768f744..612bdd29 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.51.0'; // x-release-please-version +export const VERSION = '0.52.0'; // x-release-please-version From a83e658747a0926be89670ff1f1771a4736b7ade Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 30 Apr 2026 07:27:18 +0000 Subject: [PATCH 373/551] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index 33f284fe..324dd3f5 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 112 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-4ce09d1a7546ab36f578cb27d819187eeb90c580b11834c7ff7a375aa22f9a20.yml +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-4ce09d1a7546ab36f578cb27d819187eeb90c580b11834c7ff7a375aa22f9a20.yml openapi_spec_hash: 1043ab2d699f6c828680c3352cd4cece config_hash: 08d55086449943a8fec212b870061a3f From 65a726b66d844b8a6f6b030d0d66633e6e30e0b2 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 30 Apr 2026 14:55:40 +0000 Subject: [PATCH 374/551] feat: Add 'switch' MFA option type for generic method-switcher links --- .stats.yml | 4 ++-- src/resources/auth/connections.ts | 16 ++++++++++------ 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/.stats.yml b/.stats.yml index 324dd3f5..d0f4a0f3 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 112 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-4ce09d1a7546ab36f578cb27d819187eeb90c580b11834c7ff7a375aa22f9a20.yml -openapi_spec_hash: 1043ab2d699f6c828680c3352cd4cece +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-81659c4d18e7992d17a0930d6c13c8592a0ff5bb974ea9e2e4b3f46d43b117d2.yml +openapi_spec_hash: f3d12a3a0a5e9ce711fb1c571ee36f9c config_hash: 08d55086449943a8fec212b870061a3f diff --git a/src/resources/auth/connections.ts b/src/resources/auth/connections.ts index 256800dd..d5815819 100644 --- a/src/resources/auth/connections.ts +++ b/src/resources/auth/connections.ts @@ -464,7 +464,7 @@ export namespace ManagedAuth { * If this field is associated with an MFA option, the type of that option (e.g., * password field linked to "Enter password" option) */ - linked_mfa_type?: 'sms' | 'call' | 'email' | 'totp' | 'push' | 'password' | null; + linked_mfa_type?: 'sms' | 'call' | 'email' | 'totp' | 'push' | 'password' | 'switch' | null; /** * Field placeholder @@ -487,9 +487,11 @@ export namespace ManagedAuth { label: string; /** - * The MFA delivery method type (includes password for auth method selection pages) + * The MFA delivery method type. Includes 'password' for auth method selection + * pages and 'switch' for generic method-switcher links like "Use another method" + * that do not name a specific method. */ - type: 'sms' | 'call' | 'email' | 'totp' | 'push' | 'password'; + type: 'sms' | 'call' | 'email' | 'totp' | 'push' | 'password' | 'switch'; /** * Additional instructions from the site @@ -927,7 +929,7 @@ export namespace ConnectionFollowResponse { * If this field is associated with an MFA option, the type of that option (e.g., * password field linked to "Enter password" option) */ - linked_mfa_type?: 'sms' | 'call' | 'email' | 'totp' | 'push' | 'password' | null; + linked_mfa_type?: 'sms' | 'call' | 'email' | 'totp' | 'push' | 'password' | 'switch' | null; /** * Field placeholder @@ -950,9 +952,11 @@ export namespace ConnectionFollowResponse { label: string; /** - * The MFA delivery method type (includes password for auth method selection pages) + * The MFA delivery method type. Includes 'password' for auth method selection + * pages and 'switch' for generic method-switcher links like "Use another method" + * that do not name a specific method. */ - type: 'sms' | 'call' | 'email' | 'totp' | 'push' | 'password'; + type: 'sms' | 'call' | 'email' | 'totp' | 'push' | 'password' | 'switch'; /** * Additional instructions from the site From 24906c78befc300cc92fbe02a4c36183aa1d59a1 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 1 May 2026 03:39:52 +0000 Subject: [PATCH 375/551] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index d0f4a0f3..d2492a7d 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 112 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-81659c4d18e7992d17a0930d6c13c8592a0ff5bb974ea9e2e4b3f46d43b117d2.yml +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-718b49461ceaa1d6cac7854c29dfef9036a83f6632e756c9d1ecf31fd77c57f6.yml openapi_spec_hash: f3d12a3a0a5e9ce711fb1c571ee36f9c config_hash: 08d55086449943a8fec212b870061a3f From cea6f7452a353487cec64225ba805a034de800c7 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 2 May 2026 16:48:49 +0000 Subject: [PATCH 376/551] feat(api): server-side search on GET /projects --- .stats.yml | 4 ++-- src/resources/projects/projects.ts | 7 ++++++- tests/api-resources/projects/projects.test.ts | 9 ++++++++- 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/.stats.yml b/.stats.yml index d2492a7d..229ced73 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 112 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-718b49461ceaa1d6cac7854c29dfef9036a83f6632e756c9d1ecf31fd77c57f6.yml -openapi_spec_hash: f3d12a3a0a5e9ce711fb1c571ee36f9c +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-86e061884d273a27064593a0de3a4ba366a12a1001181741addb4f781be18ec9.yml +openapi_spec_hash: e0a4ddf4a3302599376756127099488c config_hash: 08d55086449943a8fec212b870061a3f diff --git a/src/resources/projects/projects.ts b/src/resources/projects/projects.ts index b2d1219c..fb1827f7 100644 --- a/src/resources/projects/projects.ts +++ b/src/resources/projects/projects.ts @@ -155,7 +155,12 @@ export interface ProjectUpdateParams { status?: 'active' | 'archived'; } -export interface ProjectListParams extends OffsetPaginationParams {} +export interface ProjectListParams extends OffsetPaginationParams { + /** + * Case-insensitive substring match against project name + */ + query?: string; +} Projects.Limits = Limits; diff --git a/tests/api-resources/projects/projects.test.ts b/tests/api-resources/projects/projects.test.ts index d3fb12ee..229d6581 100644 --- a/tests/api-resources/projects/projects.test.ts +++ b/tests/api-resources/projects/projects.test.ts @@ -65,7 +65,14 @@ describe('resource projects', () => { test.skip('list: 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.projects.list({ limit: 100, offset: 0 }, { path: '/_stainless_unknown_path' }), + client.projects.list( + { + limit: 100, + offset: 0, + query: 'query', + }, + { path: '/_stainless_unknown_path' }, + ), ).rejects.toThrow(Kernel.NotFoundError); }); From 6f0d80d8ad9d879389289ea8e3a3b8a0fc7386e5 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 5 May 2026 21:20:15 +0000 Subject: [PATCH 377/551] feat: Scope name uniqueness to project for profiles, session_pools, extensions, credentials --- .stats.yml | 4 ++-- src/resources/browser-pools.ts | 6 +++--- src/resources/credentials.ts | 6 +++--- src/resources/extensions.ts | 6 +++--- src/resources/profiles.ts | 2 +- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/.stats.yml b/.stats.yml index 229ced73..797624b4 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 112 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-86e061884d273a27064593a0de3a4ba366a12a1001181741addb4f781be18ec9.yml -openapi_spec_hash: e0a4ddf4a3302599376756127099488c +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-b51c72a040c8dfea9c0693de6631feabfffe42922d5feb60b4ac0ee5c83bb8f4.yml +openapi_spec_hash: 8b671cfe4debe8d9ad7c39ba5b0eaf6d config_hash: 08d55086449943a8fec212b870061a3f diff --git a/src/resources/browser-pools.ts b/src/resources/browser-pools.ts index f587ded7..fa9bd67e 100644 --- a/src/resources/browser-pools.ts +++ b/src/resources/browser-pools.ts @@ -220,7 +220,7 @@ export namespace BrowserPool { kiosk_mode?: boolean; /** - * Optional name for the browser pool. Must be unique within the organization. + * Optional name for the browser pool. Must be unique within the project. */ name?: string; @@ -413,7 +413,7 @@ export interface BrowserPoolCreateParams { kiosk_mode?: boolean; /** - * Optional name for the browser pool. Must be unique within the organization. + * Optional name for the browser pool. Must be unique within the project. */ name?: string; @@ -503,7 +503,7 @@ export interface BrowserPoolUpdateParams { kiosk_mode?: boolean; /** - * Optional name for the browser pool. Must be unique within the organization. + * Optional name for the browser pool. Must be unique within the project. */ name?: string; diff --git a/src/resources/credentials.ts b/src/resources/credentials.ts index 5ae00211..ef80c0dc 100644 --- a/src/resources/credentials.ts +++ b/src/resources/credentials.ts @@ -122,7 +122,7 @@ export interface CreateCredentialRequest { domain: string; /** - * Unique name for the credential within the organization + * Unique name for the credential within the project */ name: string; @@ -166,7 +166,7 @@ export interface Credential { domain: string; /** - * Unique name for the credential within the organization + * Unique name for the credential within the project */ name: string; @@ -252,7 +252,7 @@ export interface CredentialCreateParams { domain: string; /** - * Unique name for the credential within the organization + * Unique name for the credential within the project */ name: string; diff --git a/src/resources/extensions.ts b/src/resources/extensions.ts index b28eb86e..c9e282d2 100644 --- a/src/resources/extensions.ts +++ b/src/resources/extensions.ts @@ -132,7 +132,7 @@ export namespace ExtensionListResponse { /** * Optional, easier-to-reference name for the extension. Must be unique within the - * organization. + * project. */ name?: string | null; } @@ -164,7 +164,7 @@ export interface ExtensionUploadResponse { /** * Optional, easier-to-reference name for the extension. Must be unique within the - * organization. + * project. */ name?: string | null; } @@ -188,7 +188,7 @@ export interface ExtensionUploadParams { file: Uploadable; /** - * Optional unique name within the organization to reference this extension. + * Optional unique name within the project to reference this extension. */ name?: string; } diff --git a/src/resources/profiles.ts b/src/resources/profiles.ts index 5d6c63c4..aa78a014 100644 --- a/src/resources/profiles.ts +++ b/src/resources/profiles.ts @@ -62,7 +62,7 @@ export class Profiles extends APIResource { export interface ProfileCreateParams { /** - * Optional name of the profile. Must be unique within the organization. + * Optional name of the profile. Must be unique within the project. */ name?: string; } From 5aaed19216a6a1038cf0c1b0670a00075829ce66 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 8 May 2026 03:43:24 +0000 Subject: [PATCH 378/551] chore: redact api-key headers in debug logs --- src/internal/utils/log.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/internal/utils/log.ts b/src/internal/utils/log.ts index 912b523a..736a419d 100644 --- a/src/internal/utils/log.ts +++ b/src/internal/utils/log.ts @@ -107,6 +107,8 @@ export const formatRequestDetails = (details: { name, ( name.toLowerCase() === 'authorization' || + name.toLowerCase() === 'api-key' || + name.toLowerCase() === 'x-api-key' || name.toLowerCase() === 'cookie' || name.toLowerCase() === 'set-cookie' ) ? From d183a908945d5b1822d372c7efec91a32a91aec6 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 11 May 2026 20:42:40 +0000 Subject: [PATCH 379/551] feat: browser_pools: add start_url config (KERNEL-1217 PR 2) --- .stats.yml | 4 +-- src/resources/browser-pools.ts | 33 +++++++++++++++++++ src/resources/browsers/browsers.ts | 33 +++++++++++++++++++ src/resources/invocations.ts | 6 ++++ tests/api-resources/browser-pools.test.ts | 2 ++ tests/api-resources/browsers/browsers.test.ts | 1 + 6 files changed, 77 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 797624b4..e7699746 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 112 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-b51c72a040c8dfea9c0693de6631feabfffe42922d5feb60b4ac0ee5c83bb8f4.yml -openapi_spec_hash: 8b671cfe4debe8d9ad7c39ba5b0eaf6d +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-7d2d29d7598105d50e5118e0bc5ac654361a92cb95555705dbd1d236848e1456.yml +openapi_spec_hash: 10002eae793e08f81932239bbc72b503 config_hash: 08d55086449943a8fec212b870061a3f diff --git a/src/resources/browser-pools.ts b/src/resources/browser-pools.ts index fa9bd67e..c8e38d05 100644 --- a/src/resources/browser-pools.ts +++ b/src/resources/browser-pools.ts @@ -237,6 +237,15 @@ export namespace BrowserPool { */ proxy_id?: string; + /** + * Optional URL to navigate to when a new browser is warmed into the pool. + * Best-effort: failures to navigate do not fail pool fill. Only applied to + * newly-warmed browsers — browsers reused via release/acquire keep whatever URL + * the previous lease left them on. Accepts any URL Chromium can resolve, including + * chrome:// pages. + */ + start_url?: string; + /** * If true, launches the browser in stealth mode to reduce detection by anti-bot * mechanisms. @@ -353,6 +362,12 @@ export interface BrowserPoolAcquireResponse { */ proxy_id?: string; + /** + * URL the session was asked to navigate to on creation, if any. Recorded for + * debugging — navigation is best-effort and may have failed. + */ + start_url?: string; + /** * Session usage metrics. */ @@ -430,6 +445,15 @@ export interface BrowserPoolCreateParams { */ proxy_id?: string; + /** + * Optional URL to navigate to when a new browser is warmed into the pool. + * Best-effort: failures to navigate do not fail pool fill. Only applied to + * newly-warmed browsers — browsers reused via release/acquire keep whatever URL + * the previous lease left them on. Accepts any URL Chromium can resolve, including + * chrome:// pages. + */ + start_url?: string; + /** * If true, launches the browser in stealth mode to reduce detection by anti-bot * mechanisms. @@ -520,6 +544,15 @@ export interface BrowserPoolUpdateParams { */ proxy_id?: string; + /** + * Optional URL to navigate to when a new browser is warmed into the pool. + * Best-effort: failures to navigate do not fail pool fill. Only applied to + * newly-warmed browsers — browsers reused via release/acquire keep whatever URL + * the previous lease left them on. Accepts any URL Chromium can resolve, including + * chrome:// pages. + */ + start_url?: string; + /** * If true, launches the browser in stealth mode to reduce detection by anti-bot * mechanisms. diff --git a/src/resources/browsers/browsers.ts b/src/resources/browsers/browsers.ts index 61873f31..1846d218 100644 --- a/src/resources/browsers/browsers.ts +++ b/src/resources/browsers/browsers.ts @@ -382,6 +382,12 @@ export interface BrowserCreateResponse { */ proxy_id?: string; + /** + * URL the session was asked to navigate to on creation, if any. Recorded for + * debugging — navigation is best-effort and may have failed. + */ + start_url?: string; + /** * Session usage metrics. */ @@ -488,6 +494,12 @@ export interface BrowserRetrieveResponse { */ proxy_id?: string; + /** + * URL the session was asked to navigate to on creation, if any. Recorded for + * debugging — navigation is best-effort and may have failed. + */ + start_url?: string; + /** * Session usage metrics. */ @@ -594,6 +606,12 @@ export interface BrowserUpdateResponse { */ proxy_id?: string; + /** + * URL the session was asked to navigate to on creation, if any. Recorded for + * debugging — navigation is best-effort and may have failed. + */ + start_url?: string; + /** * Session usage metrics. */ @@ -700,6 +718,12 @@ export interface BrowserListResponse { */ proxy_id?: string; + /** + * URL the session was asked to navigate to on creation, if any. Recorded for + * debugging — navigation is best-effort and may have failed. + */ + start_url?: string; + /** * Session usage metrics. */ @@ -795,6 +819,15 @@ export interface BrowserCreateParams { */ proxy_id?: string; + /** + * Optional URL to navigate to immediately after the browser is created. + * Best-effort: failures to navigate do not fail browser creation. Any pre-existing + * tabs are reduced to a single tab which is then navigated. Accepts any URL + * Chromium can resolve, including chrome:// pages. Ignored when reusing an + * existing persistent session. + */ + start_url?: string; + /** * If true, launches the browser in stealth mode to reduce detection by anti-bot * mechanisms. diff --git a/src/resources/invocations.ts b/src/resources/invocations.ts index 430751b8..f722823c 100644 --- a/src/resources/invocations.ts +++ b/src/resources/invocations.ts @@ -501,6 +501,12 @@ export namespace InvocationListBrowsersResponse { */ proxy_id?: string; + /** + * URL the session was asked to navigate to on creation, if any. Recorded for + * debugging — navigation is best-effort and may have failed. + */ + start_url?: string; + /** * Session usage metrics. */ diff --git a/tests/api-resources/browser-pools.test.ts b/tests/api-resources/browser-pools.test.ts index 4bc1157d..7a473ba2 100644 --- a/tests/api-resources/browser-pools.test.ts +++ b/tests/api-resources/browser-pools.test.ts @@ -36,6 +36,7 @@ describe('resource browserPools', () => { save_changes: true, }, proxy_id: 'proxy_id', + start_url: 'https://example.com', stealth: true, timeout_seconds: 60, viewport: { @@ -87,6 +88,7 @@ describe('resource browserPools', () => { save_changes: true, }, proxy_id: 'proxy_id', + start_url: 'https://example.com', stealth: true, timeout_seconds: 60, viewport: { diff --git a/tests/api-resources/browsers/browsers.test.ts b/tests/api-resources/browsers/browsers.test.ts index 0c2f5740..471a51c8 100644 --- a/tests/api-resources/browsers/browsers.test.ts +++ b/tests/api-resources/browsers/browsers.test.ts @@ -38,6 +38,7 @@ describe('resource browsers', () => { save_changes: true, }, proxy_id: 'proxy_id', + start_url: 'https://example.com', stealth: true, timeout_seconds: 10, viewport: { From 2ca8ef6c7719fdecb33a3b671c31a4ffe072cb0a Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 12 May 2026 19:06:52 +0000 Subject: [PATCH 380/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index acba76f8..2ffa421e 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.52.0" + ".": "0.53.0" } diff --git a/package.json b/package.json index f994a099..ea824a7c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.52.0", + "version": "0.53.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 612bdd29..16fa1b47 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.52.0'; // x-release-please-version +export const VERSION = '0.53.0'; // x-release-please-version From 4e2f95a0e80f412d02303693b4c564edd9475dcd Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 12 May 2026 19:36:27 +0000 Subject: [PATCH 381/551] feat: managed-auth: surface awaiting_external_action even when fallback actions exist --- .stats.yml | 4 ++-- src/resources/auth/connections.ts | 26 ++++++++++++++++---------- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/.stats.yml b/.stats.yml index e7699746..2085eb07 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 112 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-7d2d29d7598105d50e5118e0bc5ac654361a92cb95555705dbd1d236848e1456.yml -openapi_spec_hash: 10002eae793e08f81932239bbc72b503 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-38c6ce8b0ce54e6c62517b9635acaf65369c26cdb1b55eb66290c13a8ab2b33d.yml +openapi_spec_hash: e6f6ed157b1e318d1a1db72fd1d27091 config_hash: 08d55086449943a8fec212b870061a3f diff --git a/src/resources/auth/connections.ts b/src/resources/auth/connections.ts index d5815819..4a603884 100644 --- a/src/resources/auth/connections.ts +++ b/src/resources/auth/connections.ts @@ -272,7 +272,8 @@ export interface ManagedAuth { credential?: ManagedAuth.Credential; /** - * Fields awaiting input (present when flow_step=awaiting_input) + * Fields awaiting input (present when flow_step=awaiting_input; may also be + * present with awaiting_external_action as fallback actions) */ discovered_fields?: Array | null; @@ -362,13 +363,14 @@ export interface ManagedAuth { login_url?: string; /** - * MFA method options (present when flow_step=awaiting_input and MFA selection - * required) + * MFA method options (present when flow_step=awaiting_input; may also be present + * with awaiting_external_action as fallback actions) */ mfa_options?: Array | null; /** - * SSO buttons available (present when flow_step=awaiting_input) + * SSO buttons available (present when flow_step=awaiting_input; may also be + * present with awaiting_external_action as fallback actions) */ pending_sso_buttons?: Array | null; @@ -384,7 +386,8 @@ export interface ManagedAuth { /** * Non-MFA choices presented during the auth flow, such as account selection or org - * pickers (present when flow_step=awaiting_input). + * pickers (present when flow_step=awaiting_input; may also be present with + * awaiting_external_action as fallback actions). */ sign_in_options?: Array | null; @@ -830,7 +833,8 @@ export namespace ConnectionFollowResponse { timestamp: string; /** - * Fields awaiting input (present when flow_step=AWAITING_INPUT). + * Fields awaiting input (present when flow_step=AWAITING_INPUT; may also be + * present with AWAITING_EXTERNAL_ACTION as fallback actions). */ discovered_fields?: Array; @@ -866,13 +870,14 @@ export namespace ConnectionFollowResponse { live_view_url?: string; /** - * MFA method options (present when flow_step=AWAITING_INPUT and MFA selection - * required). + * MFA method options (present when flow_step=AWAITING_INPUT; may also be present + * with AWAITING_EXTERNAL_ACTION as fallback actions). */ mfa_options?: Array; /** - * SSO buttons available (present when flow_step=AWAITING_INPUT). + * SSO buttons available (present when flow_step=AWAITING_INPUT; may also be + * present with AWAITING_EXTERNAL_ACTION as fallback actions). */ pending_sso_buttons?: Array; @@ -883,7 +888,8 @@ export namespace ConnectionFollowResponse { /** * Non-MFA choices presented during the auth flow, such as account selection or org - * pickers (present when flow_step=AWAITING_INPUT). + * pickers (present when flow_step=AWAITING_INPUT; may also be present with + * AWAITING_EXTERNAL_ACTION as fallback actions). */ sign_in_options?: Array; From 55beb40e6f883c2fc352f9e25356ca9182c924c2 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 12 May 2026 21:38:03 +0000 Subject: [PATCH 382/551] feat: Add opt-in record_session flag to managed auth --- .stats.yml | 4 +-- src/resources/auth/connections.ts | 34 ++++++++++++++++++++ tests/api-resources/auth/connections.test.ts | 6 +++- 3 files changed, 41 insertions(+), 3 deletions(-) diff --git a/.stats.yml b/.stats.yml index 2085eb07..2939ac96 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 112 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-38c6ce8b0ce54e6c62517b9635acaf65369c26cdb1b55eb66290c13a8ab2b33d.yml -openapi_spec_hash: e6f6ed157b1e318d1a1db72fd1d27091 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-64dac369ae935b0318cd611e1735d45359a663eb55cf43fbb8b09e9dd814d7a2.yml +openapi_spec_hash: cc0c6a4e716977df4b9eab5f4658d41b config_hash: 08d55086449943a8fec212b870061a3f diff --git a/src/resources/auth/connections.ts b/src/resources/auth/connections.ts index 4a603884..26f59492 100644 --- a/src/resources/auth/connections.ts +++ b/src/resources/auth/connections.ts @@ -212,6 +212,12 @@ export interface ManagedAuth { */ profile_name: string; + /** + * Whether browser sessions for this connection are recorded by default for + * debugging. Can be overridden per-login. + */ + record_session: boolean; + /** * Whether credentials are saved after every successful login. One-time codes * (TOTP, SMS, etc.) are not saved. @@ -614,6 +620,12 @@ export interface ManagedAuthCreateRequest { */ proxy?: ManagedAuthCreateRequest.Proxy; + /** + * Whether to record browser sessions for this connection by default. Useful for + * debugging. Can be overridden per-login. Defaults to false. + */ + record_session?: boolean; + /** * Whether to save credentials after every successful login. Defaults to true. * One-time codes (TOTP, SMS, etc.) are not saved. @@ -702,6 +714,11 @@ export interface ManagedAuthUpdateRequest { */ proxy?: ManagedAuthUpdateRequest.Proxy; + /** + * Whether to record browser sessions for this connection by default + */ + record_session?: boolean; + /** * Whether to save credentials after every successful login */ @@ -1080,6 +1097,12 @@ export interface ConnectionCreateParams { */ proxy?: ConnectionCreateParams.Proxy; + /** + * Whether to record browser sessions for this connection by default. Useful for + * debugging. Can be overridden per-login. Defaults to false. + */ + record_session?: boolean; + /** * Whether to save credentials after every successful login. Defaults to true. * One-time codes (TOTP, SMS, etc.) are not saved. @@ -1165,6 +1188,11 @@ export interface ConnectionUpdateParams { */ proxy?: ConnectionUpdateParams.Proxy; + /** + * Whether to record browser sessions for this connection by default + */ + record_session?: boolean; + /** * Whether to save credentials after every successful login */ @@ -1236,6 +1264,12 @@ export interface ConnectionLoginParams { * caller's org. */ proxy?: ConnectionLoginParams.Proxy; + + /** + * Override the connection's default for recording this login's browser session. + * When omitted, the connection's record_session default is used. + */ + record_session?: boolean; } export namespace ConnectionLoginParams { diff --git a/tests/api-resources/auth/connections.test.ts b/tests/api-resources/auth/connections.test.ts index 1d08c5c0..675c3620 100644 --- a/tests/api-resources/auth/connections.test.ts +++ b/tests/api-resources/auth/connections.test.ts @@ -38,6 +38,7 @@ describe('resource connections', () => { health_check_interval: 3600, login_url: 'https://netflix.com/login', proxy: { id: 'id', name: 'name' }, + record_session: false, save_credentials: true, }); }); @@ -136,7 +137,10 @@ describe('resource connections', () => { await expect( client.auth.connections.login( 'id', - { proxy: { id: 'id', name: 'name' } }, + { + proxy: { id: 'id', name: 'name' }, + record_session: true, + }, { path: '/_stainless_unknown_path' }, ), ).rejects.toThrow(Kernel.NotFoundError); From 1e213f7b2dcc88bb7244e91c918739e660a7356c Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 12 May 2026 22:59:46 +0000 Subject: [PATCH 383/551] docs: clarify record_session description in OpenAPI spec --- .stats.yml | 4 ++-- src/resources/auth/connections.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.stats.yml b/.stats.yml index 2939ac96..7915e042 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 112 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-64dac369ae935b0318cd611e1735d45359a663eb55cf43fbb8b09e9dd814d7a2.yml -openapi_spec_hash: cc0c6a4e716977df4b9eab5f4658d41b +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-a33e59aa1758ba51f13538838ecd70b0a23ed69739b3022e8c2ce0622e42b904.yml +openapi_spec_hash: c042d2f6880c927be09aa9fa79d7241e config_hash: 08d55086449943a8fec212b870061a3f diff --git a/src/resources/auth/connections.ts b/src/resources/auth/connections.ts index 26f59492..55e2e843 100644 --- a/src/resources/auth/connections.ts +++ b/src/resources/auth/connections.ts @@ -213,8 +213,8 @@ export interface ManagedAuth { profile_name: string; /** - * Whether browser sessions for this connection are recorded by default for - * debugging. Can be overridden per-login. + * Whether to record browser session replays for this connection by default. Useful + * for debugging login flows. Can be overridden per-login. */ record_session: boolean; From 7281e7f9be199c6e0abbba7648213a9990b871e5 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 13 May 2026 02:41:09 +0000 Subject: [PATCH 384/551] ci: pin GitHub Actions to commit SHAs Pin all GitHub Actions referenced in generated workflows (both first-party `actions/*` and third-party) to immutable commit SHAs. Updating pinned actions is now a deliberate codegen-side bump rather than implicit on every workflow run. --- .github/workflows/ci.yml | 14 +++++++------- .github/workflows/publish-npm.yml | 4 ++-- .github/workflows/release-doctor.yml | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 42341634..d920d7bf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,10 +21,10 @@ jobs: runs-on: ${{ github.repository == 'stainless-sdks/kernel-typescript' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} if: (github.event_name == 'push' || github.event.pull_request.head.repo.fork) && (github.event_name != 'push' || github.event.head_commit.message != 'codegen metadata') steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Set up Node - uses: actions/setup-node@v4 + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: node-version: '20' @@ -43,10 +43,10 @@ jobs: contents: read id-token: write steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Set up Node - uses: actions/setup-node@v4 + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: node-version: '20' @@ -61,7 +61,7 @@ jobs: github.repository == 'stainless-sdks/kernel-typescript' && !startsWith(github.ref, 'refs/heads/stl/') id: github-oidc - uses: actions/github-script@v8 + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 with: script: core.setOutput('github_token', await core.getIDToken()); @@ -80,10 +80,10 @@ jobs: runs-on: ${{ github.repository == 'stainless-sdks/kernel-typescript' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} if: github.event_name == 'push' || github.event.pull_request.head.repo.fork steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Set up Node - uses: actions/setup-node@v4 + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: node-version: '20' diff --git a/.github/workflows/publish-npm.yml b/.github/workflows/publish-npm.yml index 8984e27c..664e42c3 100644 --- a/.github/workflows/publish-npm.yml +++ b/.github/workflows/publish-npm.yml @@ -17,10 +17,10 @@ jobs: id-token: write steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Set up Node - uses: actions/setup-node@v3 + uses: actions/setup-node@3235b876344d2a9aa001b8d1453c930bba69e610 # v3.9.1 with: node-version: '20' diff --git a/.github/workflows/release-doctor.yml b/.github/workflows/release-doctor.yml index 42e30af8..4fef92eb 100644 --- a/.github/workflows/release-doctor.yml +++ b/.github/workflows/release-doctor.yml @@ -12,7 +12,7 @@ jobs: if: github.repository == 'kernel/kernel-node-sdk' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch' || startsWith(github.head_ref, 'release-please') || github.head_ref == 'next') steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Check release environment run: | From 664974b5eb543fe9f1fb7f8b59bd3b52b71b1d2e Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 13 May 2026 14:40:10 +0000 Subject: [PATCH 385/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 2ffa421e..330850bf 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.53.0" + ".": "0.54.0" } diff --git a/package.json b/package.json index ea824a7c..33125442 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.53.0", + "version": "0.54.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 16fa1b47..3a6141dc 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.53.0'; // x-release-please-version +export const VERSION = '0.54.0'; // x-release-please-version From 67fdbaf2faf4d6a5bf6eaf5f39a54ccb5c11fc06 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 14 May 2026 18:20:28 +0000 Subject: [PATCH 386/551] feat: Polish start URL OpenAPI descriptions --- .stats.yml | 4 ++-- src/resources/browser-pools.ts | 27 ++++++++++----------------- src/resources/browsers/browsers.ts | 20 +++++++------------- src/resources/invocations.ts | 3 +-- 4 files changed, 20 insertions(+), 34 deletions(-) diff --git a/.stats.yml b/.stats.yml index 7915e042..35cab471 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 112 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-a33e59aa1758ba51f13538838ecd70b0a23ed69739b3022e8c2ce0622e42b904.yml -openapi_spec_hash: c042d2f6880c927be09aa9fa79d7241e +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-b7a19ff1fbd93322c8cffcd0b397ce2536ca8bff91594e0081bd030d4bec879f.yml +openapi_spec_hash: 490520e6f0a8b1ebc89e9c0add46082d config_hash: 08d55086449943a8fec212b870061a3f diff --git a/src/resources/browser-pools.ts b/src/resources/browser-pools.ts index c8e38d05..f7e1890a 100644 --- a/src/resources/browser-pools.ts +++ b/src/resources/browser-pools.ts @@ -238,11 +238,9 @@ export namespace BrowserPool { proxy_id?: string; /** - * Optional URL to navigate to when a new browser is warmed into the pool. - * Best-effort: failures to navigate do not fail pool fill. Only applied to - * newly-warmed browsers — browsers reused via release/acquire keep whatever URL - * the previous lease left them on. Accepts any URL Chromium can resolve, including - * chrome:// pages. + * Optional URL to open when a browser is created for the pool. Navigation is + * best-effort, so navigation failures do not prevent the pool from filling. Reused + * browsers keep the page left by the previous lease. */ start_url?: string; @@ -363,8 +361,7 @@ export interface BrowserPoolAcquireResponse { proxy_id?: string; /** - * URL the session was asked to navigate to on creation, if any. Recorded for - * debugging — navigation is best-effort and may have failed. + * Start URL requested for the session, if provided. */ start_url?: string; @@ -446,11 +443,9 @@ export interface BrowserPoolCreateParams { proxy_id?: string; /** - * Optional URL to navigate to when a new browser is warmed into the pool. - * Best-effort: failures to navigate do not fail pool fill. Only applied to - * newly-warmed browsers — browsers reused via release/acquire keep whatever URL - * the previous lease left them on. Accepts any URL Chromium can resolve, including - * chrome:// pages. + * Optional URL to open when a browser is created for the pool. Navigation is + * best-effort, so navigation failures do not prevent the pool from filling. Reused + * browsers keep the page left by the previous lease. */ start_url?: string; @@ -545,11 +540,9 @@ export interface BrowserPoolUpdateParams { proxy_id?: string; /** - * Optional URL to navigate to when a new browser is warmed into the pool. - * Best-effort: failures to navigate do not fail pool fill. Only applied to - * newly-warmed browsers — browsers reused via release/acquire keep whatever URL - * the previous lease left them on. Accepts any URL Chromium can resolve, including - * chrome:// pages. + * Optional URL to open when a browser is created for the pool. Navigation is + * best-effort, so navigation failures do not prevent the pool from filling. Reused + * browsers keep the page left by the previous lease. */ start_url?: string; diff --git a/src/resources/browsers/browsers.ts b/src/resources/browsers/browsers.ts index 1846d218..c4d6ce97 100644 --- a/src/resources/browsers/browsers.ts +++ b/src/resources/browsers/browsers.ts @@ -383,8 +383,7 @@ export interface BrowserCreateResponse { proxy_id?: string; /** - * URL the session was asked to navigate to on creation, if any. Recorded for - * debugging — navigation is best-effort and may have failed. + * Start URL requested for the session, if provided. */ start_url?: string; @@ -495,8 +494,7 @@ export interface BrowserRetrieveResponse { proxy_id?: string; /** - * URL the session was asked to navigate to on creation, if any. Recorded for - * debugging — navigation is best-effort and may have failed. + * Start URL requested for the session, if provided. */ start_url?: string; @@ -607,8 +605,7 @@ export interface BrowserUpdateResponse { proxy_id?: string; /** - * URL the session was asked to navigate to on creation, if any. Recorded for - * debugging — navigation is best-effort and may have failed. + * Start URL requested for the session, if provided. */ start_url?: string; @@ -719,8 +716,7 @@ export interface BrowserListResponse { proxy_id?: string; /** - * URL the session was asked to navigate to on creation, if any. Recorded for - * debugging — navigation is best-effort and may have failed. + * Start URL requested for the session, if provided. */ start_url?: string; @@ -820,11 +816,9 @@ export interface BrowserCreateParams { proxy_id?: string; /** - * Optional URL to navigate to immediately after the browser is created. - * Best-effort: failures to navigate do not fail browser creation. Any pre-existing - * tabs are reduced to a single tab which is then navigated. Accepts any URL - * Chromium can resolve, including chrome:// pages. Ignored when reusing an - * existing persistent session. + * Optional URL to open when the browser session is created. Navigation is + * best-effort, so navigation failures do not prevent the session from being + * created. */ start_url?: string; diff --git a/src/resources/invocations.ts b/src/resources/invocations.ts index f722823c..c26f6ecf 100644 --- a/src/resources/invocations.ts +++ b/src/resources/invocations.ts @@ -502,8 +502,7 @@ export namespace InvocationListBrowsersResponse { proxy_id?: string; /** - * URL the session was asked to navigate to on creation, if any. Recorded for - * debugging — navigation is best-effort and may have failed. + * Start URL requested for the session, if provided. */ start_url?: string; From 630f15c2cf7e05d383a0c6f2b3b2918ebefad5d5 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 15 May 2026 20:32:31 +0000 Subject: [PATCH 387/551] feat: Add health check and auto-reauth controls for managed auth connections --- .stats.yml | 2 +- src/resources/auth/connections.ts | 98 ++++++++++++++++++++ tests/api-resources/auth/connections.test.ts | 2 + 3 files changed, 101 insertions(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index 35cab471..6b78eac1 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 112 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-b7a19ff1fbd93322c8cffcd0b397ce2536ca8bff91594e0081bd030d4bec879f.yml -openapi_spec_hash: 490520e6f0a8b1ebc89e9c0add46082d +openapi_spec_hash: 9dd204b37a357b19032aea9eb4496645 config_hash: 08d55086449943a8fec212b870061a3f diff --git a/src/resources/auth/connections.ts b/src/resources/auth/connections.ts index 55e2e843..2b37a78e 100644 --- a/src/resources/auth/connections.ts +++ b/src/resources/auth/connections.ts @@ -250,6 +250,17 @@ export interface ManagedAuth { */ allowed_domains?: Array; + /** + * Whether automatic re-authentication is permitted for this connection. This is an + * opt-in flag only — it does not check whether re-auth is actually feasible. Even + * when true, re-auth only runs when the system has what it needs to perform it + * (for example, saved credentials for the required login fields), and only after a + * scheduled health check detects an expired session — so this flag has no effect + * when `health_checks` is false. When false, expired sessions detected by a health + * check are marked as `NEEDS_AUTH` instead of attempting re-auth. + */ + auto_reauth?: boolean; + /** * ID of the underlying browser session driving the current flow (present when flow * in progress). Use this to inspect or terminate the browser session via the @@ -337,6 +348,15 @@ export interface ManagedAuth { */ health_check_interval?: number | null; + /** + * Whether periodic health checks are enabled for this connection. When false, the + * system will not automatically verify authentication status, and `auto_reauth` + * has no effect on the automatic flow (since re-auth is only triggered by a failed + * scheduled health check). Manually triggering a health check via the API still + * works regardless of this setting. + */ + health_checks?: boolean; + /** * URL to redirect user to for hosted login (present when flow in progress) */ @@ -591,6 +611,18 @@ export interface ManagedAuthCreateRequest { */ allowed_domains?: Array; + /** + * Whether to permit automatic re-authentication when a scheduled health check + * detects an expired session. This is an opt-in flag only — it does not check + * whether re-auth is actually feasible. Even when true, re-auth only runs when the + * system has what it needs to perform it (for example, saved credentials for the + * required login fields), and only after a scheduled health check detects an + * expired session — so this flag has no effect when `health_checks` is false. When + * false, expired sessions are marked as `NEEDS_AUTH` instead of attempting + * re-auth. Defaults to true. + */ + auto_reauth?: boolean; + /** * Reference to credentials for the auth connection. Use one of: * @@ -609,6 +641,14 @@ export interface ManagedAuthCreateRequest { */ health_check_interval?: number; + /** + * Whether to enable periodic health checks. When false, the system will not + * automatically verify authentication status, and `auto_reauth` has no effect on + * the automatic flow (since re-auth is only triggered by a failed scheduled health + * check). Defaults to true. + */ + health_checks?: boolean; + /** * Optional login page URL to skip discovery */ @@ -689,6 +729,17 @@ export interface ManagedAuthUpdateRequest { */ allowed_domains?: Array; + /** + * Whether automatic re-authentication is permitted for this connection. This is an + * opt-in flag only — it does not check whether re-auth is actually feasible. Even + * when true, re-auth only runs when the system has what it needs to perform it + * (for example, saved credentials for the required login fields), and only after a + * scheduled health check detects an expired session — so this flag has no effect + * when `health_checks` is false. When false, expired sessions detected by a health + * check are marked as `NEEDS_AUTH` instead of attempting re-auth. + */ + auto_reauth?: boolean; + /** * Reference to credentials for the auth connection. Use one of: * @@ -703,6 +754,14 @@ export interface ManagedAuthUpdateRequest { */ health_check_interval?: number; + /** + * Whether periodic health checks are enabled. When set to false, the system will + * not automatically verify authentication status, and `auto_reauth` has no effect + * on the automatic flow (since re-auth is only triggered by a failed scheduled + * health check). + */ + health_checks?: boolean; + /** * Login page URL. Set to empty string to clear. */ @@ -1068,6 +1127,18 @@ export interface ConnectionCreateParams { */ allowed_domains?: Array; + /** + * Whether to permit automatic re-authentication when a scheduled health check + * detects an expired session. This is an opt-in flag only — it does not check + * whether re-auth is actually feasible. Even when true, re-auth only runs when the + * system has what it needs to perform it (for example, saved credentials for the + * required login fields), and only after a scheduled health check detects an + * expired session — so this flag has no effect when `health_checks` is false. When + * false, expired sessions are marked as `NEEDS_AUTH` instead of attempting + * re-auth. Defaults to true. + */ + auto_reauth?: boolean; + /** * Reference to credentials for the auth connection. Use one of: * @@ -1086,6 +1157,14 @@ export interface ConnectionCreateParams { */ health_check_interval?: number; + /** + * Whether to enable periodic health checks. When false, the system will not + * automatically verify authentication status, and `auto_reauth` has no effect on + * the automatic flow (since re-auth is only triggered by a failed scheduled health + * check). Defaults to true. + */ + health_checks?: boolean; + /** * Optional login page URL to skip discovery */ @@ -1163,6 +1242,17 @@ export interface ConnectionUpdateParams { */ allowed_domains?: Array; + /** + * Whether automatic re-authentication is permitted for this connection. This is an + * opt-in flag only — it does not check whether re-auth is actually feasible. Even + * when true, re-auth only runs when the system has what it needs to perform it + * (for example, saved credentials for the required login fields), and only after a + * scheduled health check detects an expired session — so this flag has no effect + * when `health_checks` is false. When false, expired sessions detected by a health + * check are marked as `NEEDS_AUTH` instead of attempting re-auth. + */ + auto_reauth?: boolean; + /** * Reference to credentials for the auth connection. Use one of: * @@ -1177,6 +1267,14 @@ export interface ConnectionUpdateParams { */ health_check_interval?: number; + /** + * Whether periodic health checks are enabled. When set to false, the system will + * not automatically verify authentication status, and `auto_reauth` has no effect + * on the automatic flow (since re-auth is only triggered by a failed scheduled + * health check). + */ + health_checks?: boolean; + /** * Login page URL. Set to empty string to clear. */ diff --git a/tests/api-resources/auth/connections.test.ts b/tests/api-resources/auth/connections.test.ts index 675c3620..c03afb3a 100644 --- a/tests/api-resources/auth/connections.test.ts +++ b/tests/api-resources/auth/connections.test.ts @@ -29,6 +29,7 @@ describe('resource connections', () => { domain: 'netflix.com', profile_name: 'user-123', allowed_domains: ['login.netflix.com', 'auth.netflix.com'], + auto_reauth: true, credential: { auto: true, name: 'my-netflix-creds', @@ -36,6 +37,7 @@ describe('resource connections', () => { provider: 'my-1p', }, health_check_interval: 3600, + health_checks: true, login_url: 'https://netflix.com/login', proxy: { id: 'id', name: 'name' }, record_session: false, From 90067c8a73933cae41b778d27e72a5724969bf22 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 15 May 2026 20:58:16 +0000 Subject: [PATCH 388/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 330850bf..b2ddd217 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.54.0" + ".": "0.55.0" } diff --git a/package.json b/package.json index 33125442..35bf5b01 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.54.0", + "version": "0.55.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 3a6141dc..7c47df59 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.54.0'; // x-release-please-version +export const VERSION = '0.55.0'; // x-release-please-version From 0a736096068d4fc11c86fead40622192f96d1729 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 16 May 2026 02:13:51 +0000 Subject: [PATCH 389/551] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index 6b78eac1..e7238e0a 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 112 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-b7a19ff1fbd93322c8cffcd0b397ce2536ca8bff91594e0081bd030d4bec879f.yml +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-85604d59d55171797ed7e5e60f46532e7825ccfcaf6ee1319284d513f582a9cf.yml openapi_spec_hash: 9dd204b37a357b19032aea9eb4496645 config_hash: 08d55086449943a8fec212b870061a3f From 7d4b470b0bb1fbc5d3ee86e902b3d1c2565c7abe Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 18 May 2026 13:14:49 +0000 Subject: [PATCH 390/551] feat: Expose POST /projects in public API --- .stats.yml | 4 ++-- src/resources/projects/projects.ts | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/.stats.yml b/.stats.yml index e7238e0a..e0a033ee 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 112 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-85604d59d55171797ed7e5e60f46532e7825ccfcaf6ee1319284d513f582a9cf.yml -openapi_spec_hash: 9dd204b37a357b19032aea9eb4496645 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-982efd191c23737c9e1cdbcbf9237fa2231b9f74e0a25db2870293bdf9951c21.yml +openapi_spec_hash: eeb27952a4cc939316c24fc0ce2c9e3a config_hash: 08d55086449943a8fec212b870061a3f diff --git a/src/resources/projects/projects.ts b/src/resources/projects/projects.ts index fb1827f7..dba12289 100644 --- a/src/resources/projects/projects.ts +++ b/src/resources/projects/projects.ts @@ -16,8 +16,7 @@ export class Projects extends APIResource { limits: LimitsAPI.Limits = new LimitsAPI.Limits(this._client); /** - * Create a new project within the authenticated organization. Requires the - * projects feature flag. + * Create a new project within the authenticated organization. * * @example * ```ts From eb19cd27cbce4eb842489b5d0ec574621e297944 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 19 May 2026 00:02:36 +0000 Subject: [PATCH 391/551] feat: browsers: accept chrome_policy on POST /browsers (KERNEL-1216) --- .stats.yml | 4 +- src/resources/browser-pools.ts | 7 ++++ src/resources/browsers/browsers.ts | 37 +++++++++++++++++++ src/resources/invocations.ts | 7 ++++ tests/api-resources/browsers/browsers.test.ts | 1 + 5 files changed, 54 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index e0a033ee..542eaa0d 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 112 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-982efd191c23737c9e1cdbcbf9237fa2231b9f74e0a25db2870293bdf9951c21.yml -openapi_spec_hash: eeb27952a4cc939316c24fc0ce2c9e3a +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-e564e74a7aae1744d4aa070a63c387f456c4719a48747dc6229b58a986255b65.yml +openapi_spec_hash: 62beb1f20708652aaee31bbffb6cfbe9 config_hash: 08d55086449943a8fec212b870061a3f diff --git a/src/resources/browser-pools.ts b/src/resources/browser-pools.ts index f7e1890a..173abb07 100644 --- a/src/resources/browser-pools.ts +++ b/src/resources/browser-pools.ts @@ -323,6 +323,13 @@ export interface BrowserPoolAcquireResponse { */ browser_live_view_url?: string; + /** + * Custom Chrome enterprise policy overrides that were applied to this browser + * session, if any. Echoed back for verification. Keys are Chrome enterprise policy + * names. + */ + chrome_policy?: { [key: string]: unknown }; + /** * When the browser session was soft-deleted. Only present for deleted sessions. */ diff --git a/src/resources/browsers/browsers.ts b/src/resources/browsers/browsers.ts index c4d6ce97..23cbfc99 100644 --- a/src/resources/browsers/browsers.ts +++ b/src/resources/browsers/browsers.ts @@ -345,6 +345,13 @@ export interface BrowserCreateResponse { */ browser_live_view_url?: string; + /** + * Custom Chrome enterprise policy overrides that were applied to this browser + * session, if any. Echoed back for verification. Keys are Chrome enterprise policy + * names. + */ + chrome_policy?: { [key: string]: unknown }; + /** * When the browser session was soft-deleted. Only present for deleted sessions. */ @@ -456,6 +463,13 @@ export interface BrowserRetrieveResponse { */ browser_live_view_url?: string; + /** + * Custom Chrome enterprise policy overrides that were applied to this browser + * session, if any. Echoed back for verification. Keys are Chrome enterprise policy + * names. + */ + chrome_policy?: { [key: string]: unknown }; + /** * When the browser session was soft-deleted. Only present for deleted sessions. */ @@ -567,6 +581,13 @@ export interface BrowserUpdateResponse { */ browser_live_view_url?: string; + /** + * Custom Chrome enterprise policy overrides that were applied to this browser + * session, if any. Echoed back for verification. Keys are Chrome enterprise policy + * names. + */ + chrome_policy?: { [key: string]: unknown }; + /** * When the browser session was soft-deleted. Only present for deleted sessions. */ @@ -678,6 +699,13 @@ export interface BrowserListResponse { */ browser_live_view_url?: string; + /** + * Custom Chrome enterprise policy overrides that were applied to this browser + * session, if any. Echoed back for verification. Keys are Chrome enterprise policy + * names. + */ + chrome_policy?: { [key: string]: unknown }; + /** * When the browser session was soft-deleted. Only present for deleted sessions. */ @@ -768,6 +796,15 @@ export interface BrowserCurlResponse { } export interface BrowserCreateParams { + /** + * Custom Chrome enterprise policy overrides applied to this browser session. Keys + * are Chrome enterprise policy names; values must match their expected types. + * Blocked: kernel-managed policies (extensions, proxy, CDP/automation). Ignored + * when reusing an existing persistent session. See + * https://chromeenterprise.google/policies/ + */ + chrome_policy?: { [key: string]: unknown }; + /** * List of browser extensions to load into the session. Provide each by id or name. */ diff --git a/src/resources/invocations.ts b/src/resources/invocations.ts index c26f6ecf..d51c8ca8 100644 --- a/src/resources/invocations.ts +++ b/src/resources/invocations.ts @@ -464,6 +464,13 @@ export namespace InvocationListBrowsersResponse { */ browser_live_view_url?: string; + /** + * Custom Chrome enterprise policy overrides that were applied to this browser + * session, if any. Echoed back for verification. Keys are Chrome enterprise policy + * names. + */ + chrome_policy?: { [key: string]: unknown }; + /** * When the browser session was soft-deleted. Only present for deleted sessions. */ diff --git a/tests/api-resources/browsers/browsers.test.ts b/tests/api-resources/browsers/browsers.test.ts index 471a51c8..5ea987ed 100644 --- a/tests/api-resources/browsers/browsers.test.ts +++ b/tests/api-resources/browsers/browsers.test.ts @@ -26,6 +26,7 @@ describe('resource browsers', () => { await expect( client.browsers.create( { + chrome_policy: { foo: 'bar' }, extensions: [{ id: 'id', name: 'name' }], gpu: false, headless: false, From a3ccf55d6baedc80ba8f665c9470add788df3a22 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 19 May 2026 02:37:18 +0000 Subject: [PATCH 392/551] chore(tests): remove redundant File import --- tests/uploads.test.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/uploads.test.ts b/tests/uploads.test.ts index ba84b0c1..981451d0 100644 --- a/tests/uploads.test.ts +++ b/tests/uploads.test.ts @@ -1,7 +1,6 @@ import fs from 'fs'; import type { ResponseLike } from '@onkernel/sdk/internal/to-file'; import { toFile } from '@onkernel/sdk/core/uploads'; -import { File } from 'node:buffer'; class MyClass { name: string = 'foo'; From 032c854131cf2b42e99e988248266f6f08a78c43 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 19 May 2026 02:37:52 +0000 Subject: [PATCH 393/551] fix(typescript): upgrade tsc-multi so that it works with Node 26 --- package.json | 2 +- yarn.lock | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 35bf5b01..c032f0d5 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,7 @@ "publint": "^0.2.12", "ts-jest": "^29.1.0", "ts-node": "^10.5.0", - "tsc-multi": "https://github.com/stainless-api/tsc-multi/releases/download/v1.1.9/tsc-multi.tgz", + "tsc-multi": "https://github.com/stainless-api/tsc-multi/releases/download/v1.1.11/tsc-multi.tgz", "tsconfig-paths": "^4.0.0", "tslib": "^2.8.1", "typescript": "5.8.3", diff --git a/yarn.lock b/yarn.lock index 18e7cbdc..00842e32 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3192,9 +3192,9 @@ ts-node@^10.5.0: v8-compile-cache-lib "^3.0.0" yn "3.1.1" -"tsc-multi@https://github.com/stainless-api/tsc-multi/releases/download/v1.1.9/tsc-multi.tgz": - version "1.1.9" - resolved "https://github.com/stainless-api/tsc-multi/releases/download/v1.1.9/tsc-multi.tgz#777f6f5d9e26bf0e94e5170990dd3a841d6707cd" +"tsc-multi@https://github.com/stainless-api/tsc-multi/releases/download/v1.1.11/tsc-multi.tgz": + version "1.1.11" + resolved "https://github.com/stainless-api/tsc-multi/releases/download/v1.1.11/tsc-multi.tgz#010247051be13b55abdc98f787c017285149f4f2" dependencies: debug "^4.3.7" fast-glob "^3.3.2" From 2f19dfd1b1118633007440ec093b37ed10d4d756 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 21 May 2026 18:53:03 +0000 Subject: [PATCH 394/551] feat: [kernel-1116] browser events api integration --- .stats.yml | 8 +- api.md | 40 + src/resources/browser-pools.ts | 36 +- src/resources/browsers/browsers.ts | 133 +- src/resources/browsers/index.ts | 35 + src/resources/browsers/telemetry.ts | 1521 +++++++++++++++++ src/resources/invocations.ts | 12 +- src/resources/proxies.ts | 4 +- tests/api-resources/browsers/browsers.test.ts | 8 + .../api-resources/browsers/telemetry.test.ts | 34 + 10 files changed, 1811 insertions(+), 20 deletions(-) create mode 100644 src/resources/browsers/telemetry.ts create mode 100644 tests/api-resources/browsers/telemetry.test.ts diff --git a/.stats.yml b/.stats.yml index 542eaa0d..3dfe6c63 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 112 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-e564e74a7aae1744d4aa070a63c387f456c4719a48747dc6229b58a986255b65.yml -openapi_spec_hash: 62beb1f20708652aaee31bbffb6cfbe9 -config_hash: 08d55086449943a8fec212b870061a3f +configured_endpoints: 113 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-a9c7e806132001dbfbd4e8ae6c7d0935e503f457d63385fc800c862e3d064375.yml +openapi_spec_hash: b048dcb0c5401bc0a301c3d30cb8ecba +config_hash: 37661d89120558d34b6cc184292632f2 diff --git a/api.md b/api.md index ba877c96..3e2a18d0 100644 --- a/api.md +++ b/api.md @@ -87,6 +87,46 @@ Methods: - client.browsers.deleteByID(id) -> void - client.browsers.loadExtensions(id, { ...params }) -> void +## Telemetry + +Types: + +- BrowserCallStack +- BrowserConsoleErrorEvent +- BrowserConsoleLogEvent +- BrowserEventContext +- BrowserEventSource +- BrowserHTTPHeaders +- BrowserInteractionClickEvent +- BrowserInteractionKeyEvent +- BrowserInteractionScrollSettledEvent +- BrowserMonitorDisconnectedEvent +- BrowserMonitorInitFailedEvent +- BrowserMonitorReconnectFailedEvent +- BrowserMonitorReconnectedEvent +- BrowserMonitorScreenshotEvent +- BrowserNetworkIdleEvent +- BrowserNetworkLoadingFailedEvent +- BrowserNetworkRequestEvent +- BrowserNetworkResponseEvent +- BrowserPageDomContentLoadedEvent +- BrowserPageLayoutSettledEvent +- BrowserPageLayoutShiftEvent +- BrowserPageLcpEvent +- BrowserPageLoadEvent +- BrowserPageNavigationEvent +- BrowserPageNavigationSettledEvent +- BrowserPageTabOpenedEvent +- BrowserTelemetryCategoriesConfig +- BrowserTelemetryCategoryConfig +- BrowserTelemetryConfig +- BrowserTelemetryEvent +- TelemetryStreamResponse + +Methods: + +- client.browsers.telemetry.stream(id, { ...params }) -> TelemetryStreamResponse + ## Replays Types: diff --git a/src/resources/browser-pools.ts b/src/resources/browser-pools.ts index 173abb07..a20c8882 100644 --- a/src/resources/browser-pools.ts +++ b/src/resources/browser-pools.ts @@ -3,6 +3,7 @@ import { APIResource } from '../core/resource'; import * as Shared from './shared'; import * as BrowsersAPI from './browsers/browsers'; +import * as TelemetryAPI from './browsers/telemetry'; import { APIPromise } from '../core/api-promise'; import { buildHeaders } from '../internal/headers'; import { RequestOptions } from '../internal/request-options'; @@ -238,9 +239,11 @@ export namespace BrowserPool { proxy_id?: string; /** - * Optional URL to open when a browser is created for the pool. Navigation is - * best-effort, so navigation failures do not prevent the pool from filling. Reused - * browsers keep the page left by the previous lease. + * Optional URL to navigate to when a new browser is warmed into the pool. + * Best-effort: failures to navigate do not fail pool fill. Only applied to + * newly-warmed browsers; browsers reused via release/acquire keep whatever URL the + * previous lease left them on. Accepts any URL Chromium can resolve, including + * chrome:// pages. */ start_url?: string; @@ -368,10 +371,19 @@ export interface BrowserPoolAcquireResponse { proxy_id?: string; /** - * Start URL requested for the session, if provided. + * URL the session was asked to navigate to on creation, if any. Recorded for + * debugging. Navigation is fire-and-forget — the URL is dispatched to the browser + * without waiting for it to load, and any errors (DNS failure, bad status, + * timeout) are silently dropped. Captures what was requested, not what the browser + * actually loaded. */ start_url?: string; + /** + * Active telemetry configuration for the session, if any. + */ + telemetry?: TelemetryAPI.BrowserTelemetryConfig | null; + /** * Session usage metrics. */ @@ -450,9 +462,11 @@ export interface BrowserPoolCreateParams { proxy_id?: string; /** - * Optional URL to open when a browser is created for the pool. Navigation is - * best-effort, so navigation failures do not prevent the pool from filling. Reused - * browsers keep the page left by the previous lease. + * Optional URL to navigate to when a new browser is warmed into the pool. + * Best-effort: failures to navigate do not fail pool fill. Only applied to + * newly-warmed browsers; browsers reused via release/acquire keep whatever URL the + * previous lease left them on. Accepts any URL Chromium can resolve, including + * chrome:// pages. */ start_url?: string; @@ -547,9 +561,11 @@ export interface BrowserPoolUpdateParams { proxy_id?: string; /** - * Optional URL to open when a browser is created for the pool. Navigation is - * best-effort, so navigation failures do not prevent the pool from filling. Reused - * browsers keep the page left by the previous lease. + * Optional URL to navigate to when a new browser is warmed into the pool. + * Best-effort: failures to navigate do not fail pool fill. Only applied to + * newly-warmed browsers; browsers reused via release/acquire keep whatever URL the + * previous lease left them on. Accepts any URL Chromium can resolve, including + * chrome:// pages. */ start_url?: string; diff --git a/src/resources/browsers/browsers.ts b/src/resources/browsers/browsers.ts index 23cbfc99..2547d696 100644 --- a/src/resources/browsers/browsers.ts +++ b/src/resources/browsers/browsers.ts @@ -50,6 +50,42 @@ import { ReplayStopParams, Replays, } from './replays'; +import * as TelemetryAPI from './telemetry'; +import { + BrowserCallStack, + BrowserConsoleErrorEvent, + BrowserConsoleLogEvent, + BrowserEventContext, + BrowserEventSource, + BrowserHTTPHeaders, + BrowserInteractionClickEvent, + BrowserInteractionKeyEvent, + BrowserInteractionScrollSettledEvent, + BrowserMonitorDisconnectedEvent, + BrowserMonitorInitFailedEvent, + BrowserMonitorReconnectFailedEvent, + BrowserMonitorReconnectedEvent, + BrowserMonitorScreenshotEvent, + BrowserNetworkIdleEvent, + BrowserNetworkLoadingFailedEvent, + BrowserNetworkRequestEvent, + BrowserNetworkResponseEvent, + BrowserPageDomContentLoadedEvent, + BrowserPageLayoutSettledEvent, + BrowserPageLayoutShiftEvent, + BrowserPageLcpEvent, + BrowserPageLoadEvent, + BrowserPageNavigationEvent, + BrowserPageNavigationSettledEvent, + BrowserPageTabOpenedEvent, + BrowserTelemetryCategoriesConfig, + BrowserTelemetryCategoryConfig, + BrowserTelemetryConfig, + BrowserTelemetryEvent, + Telemetry, + TelemetryStreamParams, + TelemetryStreamResponse, +} from './telemetry'; import * as FsAPI from './fs/fs'; import { FCreateDirectoryParams, @@ -80,6 +116,7 @@ import { path } from '../../internal/utils/path'; * Create and manage browser sessions. */ export class Browsers extends APIResource { + telemetry: TelemetryAPI.Telemetry = new TelemetryAPI.Telemetry(this._client); replays: ReplaysAPI.Replays = new ReplaysAPI.Replays(this._client); fs: FsAPI.Fs = new FsAPI.Fs(this._client); process: ProcessAPI.Process = new ProcessAPI.Process(this._client); @@ -390,10 +427,19 @@ export interface BrowserCreateResponse { proxy_id?: string; /** - * Start URL requested for the session, if provided. + * URL the session was asked to navigate to on creation, if any. Recorded for + * debugging. Navigation is fire-and-forget — the URL is dispatched to the browser + * without waiting for it to load, and any errors (DNS failure, bad status, + * timeout) are silently dropped. Captures what was requested, not what the browser + * actually loaded. */ start_url?: string; + /** + * Active telemetry configuration for the session, if any. + */ + telemetry?: TelemetryAPI.BrowserTelemetryConfig | null; + /** * Session usage metrics. */ @@ -508,10 +554,19 @@ export interface BrowserRetrieveResponse { proxy_id?: string; /** - * Start URL requested for the session, if provided. + * URL the session was asked to navigate to on creation, if any. Recorded for + * debugging. Navigation is fire-and-forget — the URL is dispatched to the browser + * without waiting for it to load, and any errors (DNS failure, bad status, + * timeout) are silently dropped. Captures what was requested, not what the browser + * actually loaded. */ start_url?: string; + /** + * Active telemetry configuration for the session, if any. + */ + telemetry?: TelemetryAPI.BrowserTelemetryConfig | null; + /** * Session usage metrics. */ @@ -626,10 +681,19 @@ export interface BrowserUpdateResponse { proxy_id?: string; /** - * Start URL requested for the session, if provided. + * URL the session was asked to navigate to on creation, if any. Recorded for + * debugging. Navigation is fire-and-forget — the URL is dispatched to the browser + * without waiting for it to load, and any errors (DNS failure, bad status, + * timeout) are silently dropped. Captures what was requested, not what the browser + * actually loaded. */ start_url?: string; + /** + * Active telemetry configuration for the session, if any. + */ + telemetry?: TelemetryAPI.BrowserTelemetryConfig | null; + /** * Session usage metrics. */ @@ -744,10 +808,19 @@ export interface BrowserListResponse { proxy_id?: string; /** - * Start URL requested for the session, if provided. + * URL the session was asked to navigate to on creation, if any. Recorded for + * debugging. Navigation is fire-and-forget — the URL is dispatched to the browser + * without waiting for it to load, and any errors (DNS failure, bad status, + * timeout) are silently dropped. Captures what was requested, not what the browser + * actually loaded. */ start_url?: string; + /** + * Active telemetry configuration for the session, if any. + */ + telemetry?: TelemetryAPI.BrowserTelemetryConfig | null; + /** * Session usage metrics. */ @@ -865,6 +938,13 @@ export interface BrowserCreateParams { */ stealth?: boolean; + /** + * Telemetry configuration for the browser session. If provided, telemetry capture + * starts with the specified category filter when the session is created. If + * omitted, no telemetry capture is started. + */ + telemetry?: TelemetryAPI.BrowserTelemetryConfig | null; + /** * The number of seconds of inactivity before the browser session is terminated. * Activity includes CDP connections and live view connections. Defaults to 60 @@ -917,6 +997,14 @@ export interface BrowserUpdateParams { */ proxy_id?: string | null; + /** + * Telemetry configuration. Omit, set to null, or set to an empty object ({}) to + * leave the existing configuration unchanged (no-op). To enable capture for all + * categories using VM defaults, set browser to an empty object ({"browser": {}}). + * To stop capture, set every category's enabled to false. + */ + telemetry?: TelemetryAPI.BrowserTelemetryConfig | null; + /** * Viewport configuration to apply to the browser session. */ @@ -1018,6 +1106,7 @@ export namespace BrowserLoadExtensionsParams { } } +Browsers.Telemetry = Telemetry; Browsers.Replays = Replays; Browsers.Fs = Fs; Browsers.Process = Process; @@ -1046,6 +1135,42 @@ export declare namespace Browsers { type BrowserLoadExtensionsParams as BrowserLoadExtensionsParams, }; + export { + Telemetry as Telemetry, + type BrowserCallStack as BrowserCallStack, + type BrowserConsoleErrorEvent as BrowserConsoleErrorEvent, + type BrowserConsoleLogEvent as BrowserConsoleLogEvent, + type BrowserEventContext as BrowserEventContext, + type BrowserEventSource as BrowserEventSource, + type BrowserHTTPHeaders as BrowserHTTPHeaders, + type BrowserInteractionClickEvent as BrowserInteractionClickEvent, + type BrowserInteractionKeyEvent as BrowserInteractionKeyEvent, + type BrowserInteractionScrollSettledEvent as BrowserInteractionScrollSettledEvent, + type BrowserMonitorDisconnectedEvent as BrowserMonitorDisconnectedEvent, + type BrowserMonitorInitFailedEvent as BrowserMonitorInitFailedEvent, + type BrowserMonitorReconnectFailedEvent as BrowserMonitorReconnectFailedEvent, + type BrowserMonitorReconnectedEvent as BrowserMonitorReconnectedEvent, + type BrowserMonitorScreenshotEvent as BrowserMonitorScreenshotEvent, + type BrowserNetworkIdleEvent as BrowserNetworkIdleEvent, + type BrowserNetworkLoadingFailedEvent as BrowserNetworkLoadingFailedEvent, + type BrowserNetworkRequestEvent as BrowserNetworkRequestEvent, + type BrowserNetworkResponseEvent as BrowserNetworkResponseEvent, + type BrowserPageDomContentLoadedEvent as BrowserPageDomContentLoadedEvent, + type BrowserPageLayoutSettledEvent as BrowserPageLayoutSettledEvent, + type BrowserPageLayoutShiftEvent as BrowserPageLayoutShiftEvent, + type BrowserPageLcpEvent as BrowserPageLcpEvent, + type BrowserPageLoadEvent as BrowserPageLoadEvent, + type BrowserPageNavigationEvent as BrowserPageNavigationEvent, + type BrowserPageNavigationSettledEvent as BrowserPageNavigationSettledEvent, + type BrowserPageTabOpenedEvent as BrowserPageTabOpenedEvent, + type BrowserTelemetryCategoriesConfig as BrowserTelemetryCategoriesConfig, + type BrowserTelemetryCategoryConfig as BrowserTelemetryCategoryConfig, + type BrowserTelemetryConfig as BrowserTelemetryConfig, + type BrowserTelemetryEvent as BrowserTelemetryEvent, + type TelemetryStreamResponse as TelemetryStreamResponse, + type TelemetryStreamParams as TelemetryStreamParams, + }; + export { Replays as Replays, type ReplayListResponse as ReplayListResponse, diff --git a/src/resources/browsers/index.ts b/src/resources/browsers/index.ts index e38f0732..90f686a3 100644 --- a/src/resources/browsers/index.ts +++ b/src/resources/browsers/index.ts @@ -81,3 +81,38 @@ export { type ReplayStartParams, type ReplayStopParams, } from './replays'; +export { + Telemetry, + type BrowserCallStack, + type BrowserConsoleErrorEvent, + type BrowserConsoleLogEvent, + type BrowserEventContext, + type BrowserEventSource, + type BrowserHTTPHeaders, + type BrowserInteractionClickEvent, + type BrowserInteractionKeyEvent, + type BrowserInteractionScrollSettledEvent, + type BrowserMonitorDisconnectedEvent, + type BrowserMonitorInitFailedEvent, + type BrowserMonitorReconnectFailedEvent, + type BrowserMonitorReconnectedEvent, + type BrowserMonitorScreenshotEvent, + type BrowserNetworkIdleEvent, + type BrowserNetworkLoadingFailedEvent, + type BrowserNetworkRequestEvent, + type BrowserNetworkResponseEvent, + type BrowserPageDomContentLoadedEvent, + type BrowserPageLayoutSettledEvent, + type BrowserPageLayoutShiftEvent, + type BrowserPageLcpEvent, + type BrowserPageLoadEvent, + type BrowserPageNavigationEvent, + type BrowserPageNavigationSettledEvent, + type BrowserPageTabOpenedEvent, + type BrowserTelemetryCategoriesConfig, + type BrowserTelemetryCategoryConfig, + type BrowserTelemetryConfig, + type BrowserTelemetryEvent, + type TelemetryStreamResponse, + type TelemetryStreamParams, +} from './telemetry'; diff --git a/src/resources/browsers/telemetry.ts b/src/resources/browsers/telemetry.ts new file mode 100644 index 00000000..4c3adf52 --- /dev/null +++ b/src/resources/browsers/telemetry.ts @@ -0,0 +1,1521 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../core/resource'; +import * as TelemetryAPI from './telemetry'; +import { APIPromise } from '../../core/api-promise'; +import { Stream } from '../../core/streaming'; +import { buildHeaders } from '../../internal/headers'; +import { RequestOptions } from '../../internal/request-options'; +import { path } from '../../internal/utils/path'; + +/** + * Stream live telemetry events from a browser session. + */ +export class Telemetry extends APIResource { + /** + * Streams browser telemetry events as a server-sent events (SSE) stream. The + * stream closes when the browser session terminates. Each event frame includes an + * id: field containing a monotonically increasing sequence number; pass it as + * Last-Event-ID on reconnect to resume without gaps. The event: field is never + * set; all frames carry JSON in the data: field. A keepalive comment frame is sent + * every 15 seconds when no events arrive. Returns 404 if the browser session does + * not exist. If telemetry was not enabled on the session, the stream opens but no + * events are delivered. + * + * @example + * ```ts + * const response = await client.browsers.telemetry.stream( + * 'id', + * ); + * ``` + */ + stream( + id: string, + params: TelemetryStreamParams | undefined = {}, + options?: RequestOptions, + ): APIPromise> { + const { 'Last-Event-ID': lastEventID } = params ?? {}; + return this._client.get(path`/browsers/${id}/telemetry`, { + ...options, + headers: buildHeaders([ + { + Accept: 'text/event-stream', + ...(lastEventID != null ? { 'Last-Event-ID': lastEventID } : undefined), + }, + options?.headers, + ]), + stream: true, + }) as APIPromise>; + } +} + +/** + * CDP Runtime.StackTrace representing the JavaScript call stack at the time of an + * event. Fields use CDP naming conventions rather than snake_case to match the + * Chrome DevTools Protocol wire format. + */ +export interface BrowserCallStack { + /** + * Ordered list of call frames, outermost first. + */ + callFrames: Array; + + /** + * Optional label for the stack trace (e.g. async cause). + */ + description?: string; + + /** + * Parent stack trace for async stacks. + */ + parent?: BrowserCallStack; +} + +export namespace BrowserCallStack { + export interface CallFrame { + /** + * Zero-based column number within the line. + */ + columnNumber: number; + + /** + * JavaScript function name, or empty string for anonymous functions. + */ + functionName: string; + + /** + * Zero-based line number within the script. + */ + lineNumber: number; + + /** + * CDP script identifier. + */ + scriptId: string; + + /** + * URL or name of the script file. + */ + url: string; + } +} + +/** + * A browser console error or uncaught JavaScript exception event. Emitted from two + * distinct CDP sources with different data shapes. Runtime.consoleAPICalled + * (console.error calls) produces level, text, args, and stack_trace. + * Runtime.exceptionThrown (uncaught exceptions) produces text, line, column, + * source_url, and stack_trace. Fields not applicable to the source are absent. + */ +export interface BrowserConsoleErrorEvent { + /** + * Provenance metadata identifying which producer emitted the event. + */ + source: BrowserEventSource; + + /** + * Event timestamp in Unix microseconds. + */ + ts: number; + + type: 'console_error'; + + /** + * Browser event context stamped by the browser monitor onto all CDP-sourced + * events. Identifies the target, frame, and navigation epoch in which the event + * occurred. + */ + data?: BrowserConsoleErrorEvent.Data; + + /** + * True if the data field was truncated due to size limits. + */ + truncated?: boolean; +} + +export namespace BrowserConsoleErrorEvent { + /** + * Browser event context stamped by the browser monitor onto all CDP-sourced + * events. Identifies the target, frame, and navigation epoch in which the event + * occurred. + */ + export interface Data extends TelemetryAPI.BrowserEventContext { + /** + * Error message text. Present in both source paths. + */ + text: string; + + /** + * All console arguments coerced to strings. Present only when sourced from + * Runtime.consoleAPICalled. + */ + args?: Array; + + /** + * Column number in the script where the exception was thrown. Present only when + * sourced from Runtime.exceptionThrown. + */ + column?: number; + + /** + * CDP console type value, always "error". Present only when sourced from + * Runtime.consoleAPICalled. + */ + level?: string; + + /** + * Line number in the script where the exception was thrown. Present only when + * sourced from Runtime.exceptionThrown. + */ + line?: number; + + /** + * URL of the script file that threw the exception. Present only when sourced from + * Runtime.exceptionThrown. + */ + source_url?: string; + + /** + * CDP Runtime.StackTrace representing the JavaScript call stack at the time of an + * event. Fields use CDP naming conventions rather than snake_case to match the + * Chrome DevTools Protocol wire format. + */ + stack_trace?: TelemetryAPI.BrowserCallStack; + } +} + +/** + * A browser console log event (console.log, console.info, console.warn, etc.). + */ +export interface BrowserConsoleLogEvent { + /** + * Provenance metadata identifying which producer emitted the event. + */ + source: BrowserEventSource; + + /** + * Event timestamp in Unix microseconds. + */ + ts: number; + + type: 'console_log'; + + /** + * Browser event context stamped by the browser monitor onto all CDP-sourced + * events. Identifies the target, frame, and navigation epoch in which the event + * occurred. + */ + data?: BrowserConsoleLogEvent.Data; + + /** + * True if the data field was truncated due to size limits. + */ + truncated?: boolean; +} + +export namespace BrowserConsoleLogEvent { + /** + * Browser event context stamped by the browser monitor onto all CDP-sourced + * events. Identifies the target, frame, and navigation epoch in which the event + * occurred. + */ + export interface Data extends TelemetryAPI.BrowserEventContext { + /** + * All console arguments coerced to strings. + */ + args?: Array; + + /** + * CDP Runtime.consoleAPICalled type, passed through unfiltered from Chrome. error + * is routed to console_error events instead; all other CDP console types appear + * here. See CDP spec for the full enum. + */ + level?: string; + + /** + * CDP Runtime.StackTrace representing the JavaScript call stack at the time of an + * event. Fields use CDP naming conventions rather than snake_case to match the + * Chrome DevTools Protocol wire format. + */ + stack_trace?: TelemetryAPI.BrowserCallStack; + + /** + * First console argument coerced to string. + */ + text?: string; + } +} + +/** + * Browser event context stamped by the browser monitor onto all CDP-sourced + * events. Identifies the target, frame, and navigation epoch in which the event + * occurred. + */ +export interface BrowserEventContext { + /** + * CDP frame identifier within the target. + */ + frame_id?: string; + + /** + * CDP document loader identifier, reset on each navigation. + */ + loader_id?: string; + + /** + * Monotonically increasing navigation sequence number, incremented on each + * top-level navigation within the target. + */ + nav_seq?: number; + + /** + * CDP session identifier for the target connection. + */ + session_id?: string; + + /** + * Browser target identifier (stable across navigations within a tab). + */ + target_id?: string; + + /** + * CDP target type of the page that produced the event. + */ + target_type?: 'page' | 'background_page' | 'service_worker' | 'shared_worker' | 'other'; + + /** + * URL relevant to this event — page URL for navigation and page events, request + * URL for network events. + */ + url?: string; +} + +/** + * Provenance metadata identifying which producer emitted the event. + */ +export interface BrowserEventSource { + /** + * Event producer. cdp: Chrome DevTools Protocol events from the browser. + * kernel_api: Kernel API server. extension: injected Chrome extension. + * local_process: system process running alongside the browser. + */ + kind: 'cdp' | 'kernel_api' | 'extension' | 'local_process'; + + /** + * Producer-specific event name (e.g. Runtime.consoleAPICalled for CDP-sourced + * console events, Runtime.exceptionThrown for uncaught exceptions). + */ + event?: string; + + /** + * Producer-specific context (e.g. CDP target/session/frame IDs). + */ + metadata?: { [key: string]: string }; +} + +/** + * HTTP headers map forwarded as-is from CDP without normalization. Values are + * typically strings but may be any JSON type. + */ +export type BrowserHTTPHeaders = { [key: string]: unknown }; + +/** + * A browser user click event captured via injected page script. + */ +export interface BrowserInteractionClickEvent { + /** + * Provenance metadata identifying which producer emitted the event. + */ + source: BrowserEventSource; + + /** + * Event timestamp in Unix microseconds. + */ + ts: number; + + type: 'interaction_click'; + + /** + * Browser event context stamped by the browser monitor onto all CDP-sourced + * events. Identifies the target, frame, and navigation epoch in which the event + * occurred. + */ + data?: BrowserInteractionClickEvent.Data; + + /** + * True if the data field was truncated due to size limits. + */ + truncated?: boolean; +} + +export namespace BrowserInteractionClickEvent { + /** + * Browser event context stamped by the browser monitor onto all CDP-sourced + * events. Identifies the target, frame, and navigation epoch in which the event + * occurred. + */ + export interface Data extends TelemetryAPI.BrowserEventContext { + /** + * CSS selector path to the clicked element. + */ + selector?: string; + + /** + * HTML tag name of the clicked element in uppercase (e.g. BUTTON, A, DIV). + */ + tag?: string; + + /** + * Visible text content of the clicked element, trimmed. + */ + text?: string; + + /** + * Viewport x-coordinate of the click in CSS pixels. + */ + x?: number; + + /** + * Viewport y-coordinate of the click in CSS pixels. + */ + y?: number; + } +} + +/** + * A browser keyboard event captured via injected page script. + */ +export interface BrowserInteractionKeyEvent { + /** + * Provenance metadata identifying which producer emitted the event. + */ + source: BrowserEventSource; + + /** + * Event timestamp in Unix microseconds. + */ + ts: number; + + type: 'interaction_key'; + + /** + * Browser event context stamped by the browser monitor onto all CDP-sourced + * events. Identifies the target, frame, and navigation epoch in which the event + * occurred. + */ + data?: BrowserInteractionKeyEvent.Data; + + /** + * True if the data field was truncated due to size limits. + */ + truncated?: boolean; +} + +export namespace BrowserInteractionKeyEvent { + /** + * Browser event context stamped by the browser monitor onto all CDP-sourced + * events. Identifies the target, frame, and navigation epoch in which the event + * occurred. + */ + export interface Data extends TelemetryAPI.BrowserEventContext { + /** + * Key value from the KeyboardEvent (e.g. Enter, Backspace, a). + */ + key?: string; + + /** + * CSS selector path to the element that had focus when the key was pressed. + */ + selector?: string; + + /** + * HTML tag name of the focused element in uppercase (e.g. INPUT, TEXTAREA, DIV). + */ + tag?: string; + } +} + +/** + * A browser scroll settled event emitted after scroll position stops changing, + * captured via injected page script. + */ +export interface BrowserInteractionScrollSettledEvent { + /** + * Provenance metadata identifying which producer emitted the event. + */ + source: BrowserEventSource; + + /** + * Event timestamp in Unix microseconds. + */ + ts: number; + + type: 'interaction_scroll_settled'; + + /** + * Browser event context stamped by the browser monitor onto all CDP-sourced + * events. Identifies the target, frame, and navigation epoch in which the event + * occurred. + */ + data?: BrowserInteractionScrollSettledEvent.Data; + + /** + * True if the data field was truncated due to size limits. + */ + truncated?: boolean; +} + +export namespace BrowserInteractionScrollSettledEvent { + /** + * Browser event context stamped by the browser monitor onto all CDP-sourced + * events. Identifies the target, frame, and navigation epoch in which the event + * occurred. + */ + export interface Data extends TelemetryAPI.BrowserEventContext { + /** + * Scroll x-position at the start of the scroll gesture in CSS pixels. + */ + from_x?: number; + + /** + * Scroll y-position at the start of the scroll gesture in CSS pixels. + */ + from_y?: number; + + /** + * CSS selector path to the scrolled element. + */ + target_selector?: string; + + /** + * Final scroll x-position after the gesture settled in CSS pixels. + */ + to_x?: number; + + /** + * Final scroll y-position after the gesture settled in CSS pixels. + */ + to_y?: number; + } +} + +/** + * The CDP connection to Chrome was lost. Telemetry events may be dropped until + * monitor_reconnected arrives. Treat any in-progress computed state (network_idle, + * page_layout_settled) as unreliable until then. + */ +export interface BrowserMonitorDisconnectedEvent { + /** + * Provenance metadata identifying which producer emitted the event. + */ + source: BrowserEventSource; + + /** + * Event timestamp in Unix microseconds. + */ + ts: number; + + type: 'monitor_disconnected'; + + data?: BrowserMonitorDisconnectedEvent.Data; + + /** + * True if the data field was truncated due to size limits. + */ + truncated?: boolean; +} + +export namespace BrowserMonitorDisconnectedEvent { + export interface Data { + /** + * Reason for the disconnection. chrome_restarted: Chrome process restarted. + */ + reason?: 'chrome_restarted'; + } +} + +/** + * The CDP session could not be initialized. + */ +export interface BrowserMonitorInitFailedEvent { + /** + * Provenance metadata identifying which producer emitted the event. + */ + source: BrowserEventSource; + + /** + * Event timestamp in Unix microseconds. + */ + ts: number; + + type: 'monitor_init_failed'; + + data?: BrowserMonitorInitFailedEvent.Data; + + /** + * True if the data field was truncated due to size limits. + */ + truncated?: boolean; +} + +export namespace BrowserMonitorInitFailedEvent { + export interface Data { + /** + * The CDP method or initialization step that failed (e.g. Target.setAutoAttach). + */ + step?: string; + } +} + +/** + * The CDP connection to Chrome could not be re-established after exhausting all + * reconnection attempts. No further telemetry events will arrive on this session. + */ +export interface BrowserMonitorReconnectFailedEvent { + /** + * Provenance metadata identifying which producer emitted the event. + */ + source: BrowserEventSource; + + /** + * Event timestamp in Unix microseconds. + */ + ts: number; + + type: 'monitor_reconnect_failed'; + + data?: BrowserMonitorReconnectFailedEvent.Data; + + /** + * True if the data field was truncated due to size limits. + */ + truncated?: boolean; +} + +export namespace BrowserMonitorReconnectFailedEvent { + export interface Data { + /** + * Reason for the reconnection failure. reconnect_exhausted: all retry attempts + * were used up without successfully restoring the CDP connection. + */ + reason?: 'reconnect_exhausted'; + } +} + +/** + * The CDP connection to Chrome was successfully re-established after a + * disconnection. Events emitted during the gap are lost. Computed state is reset, + * so navigation and network tracking restart fresh from this point. + */ +export interface BrowserMonitorReconnectedEvent { + /** + * Provenance metadata identifying which producer emitted the event. + */ + source: BrowserEventSource; + + /** + * Event timestamp in Unix microseconds. + */ + ts: number; + + type: 'monitor_reconnected'; + + data?: BrowserMonitorReconnectedEvent.Data; + + /** + * True if the data field was truncated due to size limits. + */ + truncated?: boolean; +} + +export namespace BrowserMonitorReconnectedEvent { + export interface Data { + /** + * Wall-clock time in milliseconds taken to reconnect after the disconnection. + */ + reconnect_duration_ms?: number; + } +} + +/** + * A periodic screenshot of the browser viewport. + */ +export interface BrowserMonitorScreenshotEvent { + /** + * Provenance metadata identifying which producer emitted the event. + */ + source: BrowserEventSource; + + /** + * Event timestamp in Unix microseconds. + */ + ts: number; + + type: 'monitor_screenshot'; + + data?: BrowserMonitorScreenshotEvent.Data; + + /** + * True if the data field was truncated due to size limits. + */ + truncated?: boolean; +} + +export namespace BrowserMonitorScreenshotEvent { + export interface Data { + /** + * Base64-encoded PNG screenshot of the browser viewport. + */ + png?: string; + } +} + +/** + * A browser network idle event emitted after a 500ms quiet period with no + * in-flight HTTP requests. + */ +export interface BrowserNetworkIdleEvent { + /** + * Provenance metadata identifying which producer emitted the event. + */ + source: BrowserEventSource; + + /** + * Event timestamp in Unix microseconds. + */ + ts: number; + + type: 'network_idle'; + + /** + * Browser event context stamped by the browser monitor onto all CDP-sourced + * events. Identifies the target, frame, and navigation epoch in which the event + * occurred. + */ + data?: BrowserEventContext; + + /** + * True if the data field was truncated due to size limits. + */ + truncated?: boolean; +} + +/** + * A browser network loading failed event. If the request was already in flight + * when CDP attached (no prior network_request was emitted for it), url, frame_id, + * loader_id, and resource_type are absent; BrowserEventContext is partially + * populated in that case. + */ +export interface BrowserNetworkLoadingFailedEvent { + /** + * Provenance metadata identifying which producer emitted the event. + */ + source: BrowserEventSource; + + /** + * Event timestamp in Unix microseconds. + */ + ts: number; + + type: 'network_loading_failed'; + + /** + * Browser event context stamped by the browser monitor onto all CDP-sourced + * events. Identifies the target, frame, and navigation epoch in which the event + * occurred. + */ + data?: BrowserNetworkLoadingFailedEvent.Data; + + /** + * True if the data field was truncated due to size limits. + */ + truncated?: boolean; +} + +export namespace BrowserNetworkLoadingFailedEvent { + /** + * Browser event context stamped by the browser monitor onto all CDP-sourced + * events. Identifies the target, frame, and navigation epoch in which the event + * occurred. + */ + export interface Data extends TelemetryAPI.BrowserEventContext { + /** + * True if the request was canceled by the browser or page script. + */ + canceled?: boolean; + + /** + * Network error description (e.g. net::ERR_CONNECTION_REFUSED). + */ + error_text?: string; + + /** + * CDP request identifier matching the originating network_request event. + */ + request_id?: string; + + /** + * CDP Network.ResourceType for the request, passed through as-is from Chrome. + * Known values include Document, Fetch, XHR, Script, Stylesheet, Image, Media, + * Font, TextTrack, EventSource, WebSocket, Manifest, Prefetch, Other, and more. + */ + resource_type?: string; + } +} + +/** + * A browser network request sent event. + */ +export interface BrowserNetworkRequestEvent { + /** + * Provenance metadata identifying which producer emitted the event. + */ + source: BrowserEventSource; + + /** + * Event timestamp in Unix microseconds. + */ + ts: number; + + type: 'network_request'; + + /** + * Browser event context stamped by the browser monitor onto all CDP-sourced + * events. Identifies the target, frame, and navigation epoch in which the event + * occurred. + */ + data?: BrowserNetworkRequestEvent.Data; + + /** + * True if the data field was truncated due to size limits. + */ + truncated?: boolean; +} + +export namespace BrowserNetworkRequestEvent { + /** + * Browser event context stamped by the browser monitor onto all CDP-sourced + * events. Identifies the target, frame, and navigation epoch in which the event + * occurred. + */ + export interface Data extends TelemetryAPI.BrowserEventContext { + /** + * URL of the document that initiated the request. + */ + document_url?: string; + + /** + * Request headers. + */ + headers?: TelemetryAPI.BrowserHTTPHeaders; + + /** + * CDP Initiator.type indicating what caused the request, passed through as-is from + * Chrome. Known values include script, parser, preload, and other. + */ + initiator_type?: string; + + /** + * True if this request is the result of a redirect. + */ + is_redirect?: boolean; + + /** + * HTTP method as sent on the wire (e.g. GET, POST). + */ + method?: string; + + /** + * Request body for POST/PUT requests, if available. + */ + post_data?: string; + + /** + * Original URL before the redirect, present when is_redirect is true. + */ + redirect_url?: string; + + /** + * CDP request identifier, unique within the session. + */ + request_id?: string; + + /** + * CDP Network.ResourceType for the request, passed through as-is from Chrome. + * Known values include Document, Fetch, XHR, Script, Stylesheet, Image, Media, + * Font, TextTrack, EventSource, WebSocket, Manifest, Prefetch, Other, and more. + */ + resource_type?: string; + } +} + +/** + * A browser network response received event. Fired after the response body is + * fully received, not when headers arrive. + */ +export interface BrowserNetworkResponseEvent { + /** + * Provenance metadata identifying which producer emitted the event. + */ + source: BrowserEventSource; + + /** + * Event timestamp in Unix microseconds. + */ + ts: number; + + type: 'network_response'; + + /** + * Browser event context stamped by the browser monitor onto all CDP-sourced + * events. Identifies the target, frame, and navigation epoch in which the event + * occurred. + */ + data?: BrowserNetworkResponseEvent.Data; + + /** + * True if the data field was truncated due to size limits. + */ + truncated?: boolean; +} + +export namespace BrowserNetworkResponseEvent { + /** + * Browser event context stamped by the browser monitor onto all CDP-sourced + * events. Identifies the target, frame, and navigation epoch in which the event + * occurred. + */ + export interface Data extends TelemetryAPI.BrowserEventContext { + /** + * Truncated response body, present only for text MIME types. + */ + body?: string; + + /** + * Response headers. + */ + headers?: TelemetryAPI.BrowserHTTPHeaders; + + /** + * HTTP method of the original request. + */ + method?: string; + + /** + * MIME type of the response (e.g. text/html, application/json). + */ + mime_type?: string; + + /** + * CDP request identifier matching the originating network_request event. + */ + request_id?: string; + + /** + * CDP Network.ResourceType for the request, passed through as-is from Chrome. + * Known values include Document, Fetch, XHR, Script, Stylesheet, Image, Media, + * Font, TextTrack, EventSource, WebSocket, Manifest, Prefetch, Other, and more. + */ + resource_type?: string; + + /** + * HTTP response status code. + */ + status?: number; + + /** + * HTTP response status text (e.g. OK, Not Found). + */ + status_text?: string; + } +} + +/** + * A browser DOMContentLoaded event (CDP Page.domContentEventFired). + */ +export interface BrowserPageDomContentLoadedEvent { + /** + * Provenance metadata identifying which producer emitted the event. + */ + source: BrowserEventSource; + + /** + * Event timestamp in Unix microseconds. + */ + ts: number; + + type: 'page_dom_content_loaded'; + + /** + * Browser event context stamped by the browser monitor onto all CDP-sourced + * events. Identifies the target, frame, and navigation epoch in which the event + * occurred. + */ + data?: BrowserPageDomContentLoadedEvent.Data; + + /** + * True if the data field was truncated due to size limits. + */ + truncated?: boolean; +} + +export namespace BrowserPageDomContentLoadedEvent { + /** + * Browser event context stamped by the browser monitor onto all CDP-sourced + * events. Identifies the target, frame, and navigation epoch in which the event + * occurred. + */ + export interface Data extends TelemetryAPI.BrowserEventContext { + /** + * Chrome monotonic clock value in seconds at which DOMContentLoaded fired, + * relative to browser process start (not Unix epoch). Use ts for wall-clock time. + */ + cdp_timestamp?: number; + } +} + +/** + * A browser layout settled event emitted 1 second after page load with no + * intervening layout shifts, indicating visual stability. Each layout shift resets + * the 1-second timer. + */ +export interface BrowserPageLayoutSettledEvent { + /** + * Provenance metadata identifying which producer emitted the event. + */ + source: BrowserEventSource; + + /** + * Event timestamp in Unix microseconds. + */ + ts: number; + + type: 'page_layout_settled'; + + /** + * Browser event context stamped by the browser monitor onto all CDP-sourced + * events. Identifies the target, frame, and navigation epoch in which the event + * occurred. + */ + data?: BrowserEventContext; + + /** + * True if the data field was truncated due to size limits. + */ + truncated?: boolean; +} + +/** + * A browser cumulative layout shift (CLS) event from the Performance Timeline API. + */ +export interface BrowserPageLayoutShiftEvent { + /** + * Provenance metadata identifying which producer emitted the event. + */ + source: BrowserEventSource; + + /** + * Event timestamp in Unix microseconds. + */ + ts: number; + + type: 'page_layout_shift'; + + /** + * Browser event context stamped by the browser monitor onto all CDP-sourced + * events. Identifies the target, frame, and navigation epoch in which the event + * occurred. + */ + data?: BrowserPageLayoutShiftEvent.Data; + + /** + * True if the data field was truncated due to size limits. + */ + truncated?: boolean; +} + +export namespace BrowserPageLayoutShiftEvent { + /** + * Browser event context stamped by the browser monitor onto all CDP-sourced + * events. Identifies the target, frame, and navigation epoch in which the event + * occurred. + */ + export interface Data extends TelemetryAPI.BrowserEventContext { + /** + * Duration of the layout shift entry in milliseconds (always 0 for layout shifts + * per spec). + */ + duration?: number; + + /** + * PerformanceLayoutShift attributes from the Performance Timeline entry. + */ + layout_shift_details?: Data.LayoutShiftDetails; + + /** + * CDP frame identifier of the frame where the layout shift occurred. + */ + source_frame_id?: string; + + /** + * Performance Timeline timestamp of the layout shift in milliseconds. + */ + time?: number; + } + + export namespace Data { + /** + * PerformanceLayoutShift attributes from the Performance Timeline entry. + */ + export interface LayoutShiftDetails { + /** + * True if the layout shift was preceded by user input within 500ms, excluding it + * from CLS. + */ + had_recent_input?: boolean; + + /** + * Layout shift score for this entry (contribution to CLS). + */ + value?: number; + } + } +} + +/** + * A browser Largest Contentful Paint (LCP) event from the Performance Timeline + * API. + */ +export interface BrowserPageLcpEvent { + /** + * Provenance metadata identifying which producer emitted the event. + */ + source: BrowserEventSource; + + /** + * Event timestamp in Unix microseconds. + */ + ts: number; + + type: 'page_lcp'; + + /** + * Browser event context stamped by the browser monitor onto all CDP-sourced + * events. Identifies the target, frame, and navigation epoch in which the event + * occurred. + */ + data?: BrowserPageLcpEvent.Data; + + /** + * True if the data field was truncated due to size limits. + */ + truncated?: boolean; +} + +export namespace BrowserPageLcpEvent { + /** + * Browser event context stamped by the browser monitor onto all CDP-sourced + * events. Identifies the target, frame, and navigation epoch in which the event + * occurred. + */ + export interface Data extends TelemetryAPI.BrowserEventContext { + /** + * LargestContentfulPaint attributes from the Performance Timeline entry. + */ + lcp_details?: Data.LcpDetails; + + /** + * CDP frame identifier of the frame where the LCP element was rendered. + */ + source_frame_id?: string; + + /** + * Performance Timeline timestamp of the LCP entry in milliseconds. + */ + time?: number; + } + + export namespace Data { + /** + * LargestContentfulPaint attributes from the Performance Timeline entry. + */ + export interface LcpDetails { + /** + * id attribute of the LCP element, if present. + */ + element_id?: string; + + /** + * Load time of the LCP element in milliseconds. + */ + load_time?: number; + + /** + * CDP DOM node identifier of the LCP element. + */ + node_id?: number; + + /** + * Render time of the LCP element in milliseconds; 0 for cross-origin images + * without Timing-Allow-Origin. + */ + render_time?: number; + + /** + * Visible area of the LCP element in pixels squared. + */ + size?: number; + + /** + * URL of the LCP element for image or video elements. + */ + url?: string; + } + } +} + +/** + * A browser page load event (CDP Page.loadEventFired). + */ +export interface BrowserPageLoadEvent { + /** + * Provenance metadata identifying which producer emitted the event. + */ + source: BrowserEventSource; + + /** + * Event timestamp in Unix microseconds. + */ + ts: number; + + type: 'page_load'; + + /** + * Browser event context stamped by the browser monitor onto all CDP-sourced + * events. Identifies the target, frame, and navigation epoch in which the event + * occurred. + */ + data?: BrowserPageLoadEvent.Data; + + /** + * True if the data field was truncated due to size limits. + */ + truncated?: boolean; +} + +export namespace BrowserPageLoadEvent { + /** + * Browser event context stamped by the browser monitor onto all CDP-sourced + * events. Identifies the target, frame, and navigation epoch in which the event + * occurred. + */ + export interface Data extends TelemetryAPI.BrowserEventContext { + /** + * Chrome monotonic clock value in seconds at which the load event fired, relative + * to browser process start (not Unix epoch). Use ts for wall-clock time. + */ + cdp_timestamp?: number; + } +} + +/** + * A browser page navigation started event (CDP Page.frameNavigated). Carries nav + * context fields inline but not nav_seq, as this event resets the navigation + * epoch. + */ +export interface BrowserPageNavigationEvent { + /** + * Provenance metadata identifying which producer emitted the event. + */ + source: BrowserEventSource; + + /** + * Event timestamp in Unix microseconds. + */ + ts: number; + + type: 'page_navigation'; + + data?: BrowserPageNavigationEvent.Data; + + /** + * True if the data field was truncated due to size limits. + */ + truncated?: boolean; +} + +export namespace BrowserPageNavigationEvent { + export interface Data { + /** + * CDP frame identifier of the navigated frame. + */ + frame_id?: string; + + /** + * New CDP document loader identifier assigned for this navigation. + */ + loader_id?: string; + + /** + * Parent frame identifier for subframe navigations; absent for top-level + * navigations. + */ + parent_frame_id?: string; + + /** + * CDP session identifier. + */ + session_id?: string; + + /** + * Browser target identifier. + */ + target_id?: string; + + /** + * CDP target type of the page that produced the event. + */ + target_type?: 'page' | 'background_page' | 'service_worker' | 'shared_worker' | 'other'; + + /** + * URL navigated to. + */ + url?: string; + } +} + +/** + * Emitted when page_dom_content_loaded and page_layout_settled have both fired for + * the same navigation, indicating the page is loaded and visually stable. + * Independent of network_idle; a single pending request does not block it. + */ +export interface BrowserPageNavigationSettledEvent { + /** + * Provenance metadata identifying which producer emitted the event. + */ + source: BrowserEventSource; + + /** + * Event timestamp in Unix microseconds. + */ + ts: number; + + type: 'page_navigation_settled'; + + /** + * Browser event context stamped by the browser monitor onto all CDP-sourced + * events. Identifies the target, frame, and navigation epoch in which the event + * occurred. + */ + data?: BrowserEventContext; + + /** + * True if the data field was truncated due to size limits. + */ + truncated?: boolean; +} + +/** + * A new browser tab or target was opened (CDP Target.attachedToTarget for page + * targets). Fires before a CDP session is attached to the new target, so + * session_id, frame_id, loader_id, and nav_seq are absent; this event does not + * compose BrowserEventContext. Consumers reading context fields generically should + * treat it as a special case. + */ +export interface BrowserPageTabOpenedEvent { + /** + * Provenance metadata identifying which producer emitted the event. + */ + source: BrowserEventSource; + + /** + * Event timestamp in Unix microseconds. + */ + ts: number; + + type: 'page_tab_opened'; + + data?: BrowserPageTabOpenedEvent.Data; + + /** + * True if the data field was truncated due to size limits. + */ + truncated?: boolean; +} + +export namespace BrowserPageTabOpenedEvent { + export interface Data { + /** + * Target identifier of the tab that opened this one, if any. + */ + opener_id?: string; + + /** + * CDP target identifier for the newly opened tab. + */ + target_id?: string; + + /** + * CDP target type of the page that produced the event. + */ + target_type?: 'page' | 'background_page' | 'service_worker' | 'shared_worker' | 'other'; + + /** + * Initial page title of the new tab. + */ + title?: string; + + /** + * Initial URL of the new tab. + */ + url?: string; + } +} + +/** + * Per-category telemetry capture settings. + */ +export interface BrowserTelemetryCategoriesConfig { + /** + * Console output (log, warn, error) and uncaught exceptions. + */ + console?: BrowserTelemetryCategoryConfig; + + /** + * User interaction events including clicks, keydowns, and scroll-settled events. + */ + interaction?: BrowserTelemetryCategoryConfig; + + /** + * HTTP request and response metadata including URL, method, status code, and + * timing. Request post data is forwarded as-is from CDP. Text response bodies are + * truncated at 8 KB for structured types (JSON, XML, form data) and 4 KB for other + * text types. Binary responses (images, fonts, media) are excluded. + */ + network?: BrowserTelemetryCategoryConfig; + + /** + * Page lifecycle events including navigation, DOMContentLoaded, load, layout + * shifts, and LCP. + */ + page?: BrowserTelemetryCategoryConfig; +} + +/** + * Per-category telemetry configuration. + */ +export interface BrowserTelemetryCategoryConfig { + /** + * Whether this category is captured. Defaults to true if omitted. + */ + enabled?: boolean; +} + +/** + * Telemetry configuration for a browser session. + */ +export interface BrowserTelemetryConfig { + /** + * Per-category enable/disable flags. If omitted, all categories are captured. + */ + browser?: BrowserTelemetryCategoriesConfig; +} + +/** + * Union type representing any browser telemetry event. Discriminated on `type`. + * Events with a `monitor_` prefix (monitor_screenshot, monitor_disconnected, + * monitor_reconnected, monitor_reconnect_failed, monitor_init_failed) are always + * emitted regardless of the category configuration in BrowserTelemetryConfig. All + * other event types are controlled by the per-category enable/disable flags. + */ +export type BrowserTelemetryEvent = + | BrowserConsoleLogEvent + | BrowserConsoleErrorEvent + | BrowserNetworkRequestEvent + | BrowserNetworkResponseEvent + | BrowserNetworkLoadingFailedEvent + | BrowserNetworkIdleEvent + | BrowserPageNavigationEvent + | BrowserPageDomContentLoadedEvent + | BrowserPageLoadEvent + | BrowserPageTabOpenedEvent + | BrowserPageLayoutShiftEvent + | BrowserPageLcpEvent + | BrowserPageLayoutSettledEvent + | BrowserPageNavigationSettledEvent + | BrowserInteractionClickEvent + | BrowserInteractionKeyEvent + | BrowserInteractionScrollSettledEvent + | BrowserMonitorScreenshotEvent + | BrowserMonitorDisconnectedEvent + | BrowserMonitorReconnectedEvent + | BrowserMonitorReconnectFailedEvent + | BrowserMonitorInitFailedEvent; + +/** + * Envelope wrapping a browser telemetry event with its monotonic sequence number. + * Each SSE data: frame carries one envelope as JSON. The seq value is also emitted + * as the SSE id: field so clients can pass it as Last-Event-ID on reconnect. + */ +export interface TelemetryStreamResponse { + /** + * Union type representing any browser telemetry event. Discriminated on `type`. + * Events with a `monitor_` prefix (monitor_screenshot, monitor_disconnected, + * monitor_reconnected, monitor_reconnect_failed, monitor_init_failed) are always + * emitted regardless of the category configuration in BrowserTelemetryConfig. All + * other event types are controlled by the per-category enable/disable flags. + */ + event: BrowserTelemetryEvent; + + /** + * Process-monotonic sequence number assigned by the browser VM. Pass as + * Last-Event-ID on reconnect to resume without gaps. Gaps in received seq values + * indicate dropped events. + */ + seq: number; +} + +export interface TelemetryStreamParams { + /** + * Last event sequence number for SSE reconnection (sent by SSE clients on + * reconnect) + */ + 'Last-Event-ID'?: string; +} + +export declare namespace Telemetry { + export { + type BrowserCallStack as BrowserCallStack, + type BrowserConsoleErrorEvent as BrowserConsoleErrorEvent, + type BrowserConsoleLogEvent as BrowserConsoleLogEvent, + type BrowserEventContext as BrowserEventContext, + type BrowserEventSource as BrowserEventSource, + type BrowserHTTPHeaders as BrowserHTTPHeaders, + type BrowserInteractionClickEvent as BrowserInteractionClickEvent, + type BrowserInteractionKeyEvent as BrowserInteractionKeyEvent, + type BrowserInteractionScrollSettledEvent as BrowserInteractionScrollSettledEvent, + type BrowserMonitorDisconnectedEvent as BrowserMonitorDisconnectedEvent, + type BrowserMonitorInitFailedEvent as BrowserMonitorInitFailedEvent, + type BrowserMonitorReconnectFailedEvent as BrowserMonitorReconnectFailedEvent, + type BrowserMonitorReconnectedEvent as BrowserMonitorReconnectedEvent, + type BrowserMonitorScreenshotEvent as BrowserMonitorScreenshotEvent, + type BrowserNetworkIdleEvent as BrowserNetworkIdleEvent, + type BrowserNetworkLoadingFailedEvent as BrowserNetworkLoadingFailedEvent, + type BrowserNetworkRequestEvent as BrowserNetworkRequestEvent, + type BrowserNetworkResponseEvent as BrowserNetworkResponseEvent, + type BrowserPageDomContentLoadedEvent as BrowserPageDomContentLoadedEvent, + type BrowserPageLayoutSettledEvent as BrowserPageLayoutSettledEvent, + type BrowserPageLayoutShiftEvent as BrowserPageLayoutShiftEvent, + type BrowserPageLcpEvent as BrowserPageLcpEvent, + type BrowserPageLoadEvent as BrowserPageLoadEvent, + type BrowserPageNavigationEvent as BrowserPageNavigationEvent, + type BrowserPageNavigationSettledEvent as BrowserPageNavigationSettledEvent, + type BrowserPageTabOpenedEvent as BrowserPageTabOpenedEvent, + type BrowserTelemetryCategoriesConfig as BrowserTelemetryCategoriesConfig, + type BrowserTelemetryCategoryConfig as BrowserTelemetryCategoryConfig, + type BrowserTelemetryConfig as BrowserTelemetryConfig, + type BrowserTelemetryEvent as BrowserTelemetryEvent, + type TelemetryStreamResponse as TelemetryStreamResponse, + type TelemetryStreamParams as TelemetryStreamParams, + }; +} diff --git a/src/resources/invocations.ts b/src/resources/invocations.ts index d51c8ca8..50dafd96 100644 --- a/src/resources/invocations.ts +++ b/src/resources/invocations.ts @@ -3,6 +3,7 @@ import { APIResource } from '../core/resource'; import * as Shared from './shared'; import * as BrowsersAPI from './browsers/browsers'; +import * as TelemetryAPI from './browsers/telemetry'; import { APIPromise } from '../core/api-promise'; import { OffsetPagination, type OffsetPaginationParams, PagePromise } from '../core/pagination'; import { Stream } from '../core/streaming'; @@ -509,10 +510,19 @@ export namespace InvocationListBrowsersResponse { proxy_id?: string; /** - * Start URL requested for the session, if provided. + * URL the session was asked to navigate to on creation, if any. Recorded for + * debugging. Navigation is fire-and-forget — the URL is dispatched to the browser + * without waiting for it to load, and any errors (DNS failure, bad status, + * timeout) are silently dropped. Captures what was requested, not what the browser + * actually loaded. */ start_url?: string; + /** + * Active telemetry configuration for the session, if any. + */ + telemetry?: TelemetryAPI.BrowserTelemetryConfig | null; + /** * Session usage metrics. */ diff --git a/src/resources/proxies.ts b/src/resources/proxies.ts index fdf7b923..b2eb5674 100644 --- a/src/resources/proxies.ts +++ b/src/resources/proxies.ts @@ -1203,7 +1203,9 @@ export interface ProxyCheckParams { * between requests, so a successful check validates proxy configuration but does * not guarantee that a subsequent browser session will use the same exit IP or * reach the same site — it is useful for verifying credentials and connectivity, - * not for predicting site-specific behavior. + * not for predicting site-specific behavior. When provided, the check result does + * not update the proxy's health status, since a failure may indicate a problem + * with the target site rather than the proxy itself. */ url?: string; } diff --git a/tests/api-resources/browsers/browsers.test.ts b/tests/api-resources/browsers/browsers.test.ts index 5ea987ed..6329136a 100644 --- a/tests/api-resources/browsers/browsers.test.ts +++ b/tests/api-resources/browsers/browsers.test.ts @@ -41,6 +41,14 @@ describe('resource browsers', () => { proxy_id: 'proxy_id', start_url: 'https://example.com', stealth: true, + telemetry: { + browser: { + console: { enabled: true }, + interaction: { enabled: true }, + network: { enabled: true }, + page: { enabled: true }, + }, + }, timeout_seconds: 10, viewport: { height: 800, diff --git a/tests/api-resources/browsers/telemetry.test.ts b/tests/api-resources/browsers/telemetry.test.ts new file mode 100644 index 00000000..e1986560 --- /dev/null +++ b/tests/api-resources/browsers/telemetry.test.ts @@ -0,0 +1,34 @@ +// 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 telemetry', () => { + // Mock server tests are disabled + test.skip('stream', async () => { + const responsePromise = client.browsers.telemetry.stream('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); + }); + + // Mock server tests are disabled + test.skip('stream: 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.telemetry.stream( + 'id', + { 'Last-Event-ID': 'Last-Event-ID' }, + { path: '/_stainless_unknown_path' }, + ), + ).rejects.toThrow(Kernel.NotFoundError); + }); +}); From 05b9b78b14692999c9815e42c519019d38b83b0a Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 22 May 2026 16:38:09 +0000 Subject: [PATCH 395/551] feat(api): type can_reauth_reason as an enum on ManagedAuth --- .stats.yml | 4 +-- src/resources/auth/connections.ts | 54 ++++++++++++++++++++++++++++--- 2 files changed, 51 insertions(+), 7 deletions(-) diff --git a/.stats.yml b/.stats.yml index 3dfe6c63..01ff0714 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 113 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-a9c7e806132001dbfbd4e8ae6c7d0935e503f457d63385fc800c862e3d064375.yml -openapi_spec_hash: b048dcb0c5401bc0a301c3d30cb8ecba +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-2118a79fa452fad5922776130ea4877059e9568b603ef146171b7bb6a0f8458a.yml +openapi_spec_hash: 686e8c5855ed88b2944b9d9ec21d22ce config_hash: 37661d89120558d34b6cc184292632f2 diff --git a/src/resources/auth/connections.ts b/src/resources/auth/connections.ts index 2b37a78e..1c338deb 100644 --- a/src/resources/auth/connections.ts +++ b/src/resources/auth/connections.ts @@ -269,15 +269,59 @@ export interface ManagedAuth { browser_session_id?: string | null; /** - * Whether automatic re-authentication is possible (has credential, selectors, and - * login_url) + * Whether Kernel can automatically re-authenticate this connection when the + * session expires. Requires a prior successful login plus either a Kernel + * credential or an external credential reference. See `can_reauth_reason` for the + * specific outcome. */ can_reauth?: boolean; /** - * Reason why automatic re-authentication is or is not possible - */ - can_reauth_reason?: string; + * Machine-readable reason for the current value of `can_reauth`. Affirmative + * values (re-auth is possible): + * + * - `external_credential` — an external credential provider is attached + * - `cua_has_credential` — CUA flow with a stored credential + * - `has_credential` — Kernel credential is attached (optimistic; plan viability + * not checked) + * - `viable_plans_found` — at least one stored login plan can be replayed + * - `no_requirements_recorded` — no recorded credential requirements to fail + * against + * - `requirements_satisfiable` — recorded requirements can be met by the attached + * credential + * + * Negative values (a human must complete the login flow): + * + * - `no_prior_successful_login` — connection has never completed a successful + * login + * - `no_credential` — no Kernel or external credential attached + * - `no_viable_plans` — credential attached but no replayable login plan exists + * yet + * - `viable_plans_require_external_action` — stored plans need an external step + * (email link, push, etc.) + * - `requires_external_action` — recorded requirements include an external step + * - `requires_totp_without_secret` — flow needs a TOTP code but no TOTP secret is + * stored + * - `requires_sms_code` — flow needs an SMS code that cannot be received + * automatically + * - `requires_email_code` — flow needs an email code that cannot be received + * automatically + */ + can_reauth_reason?: + | 'external_credential' + | 'cua_has_credential' + | 'has_credential' + | 'viable_plans_found' + | 'no_requirements_recorded' + | 'requirements_satisfiable' + | 'no_prior_successful_login' + | 'no_credential' + | 'no_viable_plans' + | 'viable_plans_require_external_action' + | 'requires_external_action' + | 'requires_totp_without_secret' + | 'requires_sms_code' + | 'requires_email_code'; /** * Reference to credentials for the auth connection. Use one of: From 16a47a306b774818ccff5e7d95cdfa6e4f3af761 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 22 May 2026 16:48:41 +0000 Subject: [PATCH 396/551] feat: EOL persistent browsers: openapi limits --- .stats.yml | 8 +-- api.md | 2 - src/client.ts | 4 -- src/resources/browser-pools.ts | 6 -- src/resources/browsers/browsers.ts | 68 +------------------ src/resources/browsers/index.ts | 2 - src/resources/index.ts | 2 - src/resources/invocations.ts | 6 -- src/resources/projects/limits.ts | 18 ----- tests/api-resources/browsers/browsers.test.ts | 18 ----- 10 files changed, 5 insertions(+), 129 deletions(-) diff --git a/.stats.yml b/.stats.yml index 01ff0714..6007fff2 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 113 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-2118a79fa452fad5922776130ea4877059e9568b603ef146171b7bb6a0f8458a.yml -openapi_spec_hash: 686e8c5855ed88b2944b9d9ec21d22ce -config_hash: 37661d89120558d34b6cc184292632f2 +configured_endpoints: 112 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-346b1affebf16e7f943bcf4db307a5589fcae636c9147dd0afbe5c02cf12ad30.yml +openapi_spec_hash: 348df436759d220264f12450919211c3 +config_hash: ae3dea7997fb5d36fa41979f9585ed78 diff --git a/api.md b/api.md index 3e2a18d0..e00297f9 100644 --- a/api.md +++ b/api.md @@ -66,7 +66,6 @@ Methods: Types: -- BrowserPersistence - BrowserPoolRef - BrowserUsage - Profile @@ -82,7 +81,6 @@ Methods: - client.browsers.retrieve(id, { ...params }) -> BrowserRetrieveResponse - client.browsers.update(id, { ...params }) -> BrowserUpdateResponse - client.browsers.list({ ...params }) -> BrowserListResponsesOffsetPagination -- client.browsers.delete({ ...params }) -> void - client.browsers.curl(id, { ...params }) -> BrowserCurlResponse - client.browsers.deleteByID(id) -> void - client.browsers.loadExtensions(id, { ...params }) -> void diff --git a/src/client.ts b/src/client.ts index 871ea9e7..4aa2a3e4 100644 --- a/src/client.ts +++ b/src/client.ts @@ -104,12 +104,10 @@ import { BrowserCreateResponse, BrowserCurlParams, BrowserCurlResponse, - BrowserDeleteParams, BrowserListParams, BrowserListResponse, BrowserListResponsesOffsetPagination, BrowserLoadExtensionsParams, - BrowserPersistence, BrowserPoolRef, BrowserRetrieveParams, BrowserRetrieveResponse, @@ -996,7 +994,6 @@ export declare namespace Kernel { export { Browsers as Browsers, - type BrowserPersistence as BrowserPersistence, type BrowserPoolRef as BrowserPoolRef, type BrowserUsage as BrowserUsage, type Profile as Profile, @@ -1010,7 +1007,6 @@ export declare namespace Kernel { type BrowserRetrieveParams as BrowserRetrieveParams, type BrowserUpdateParams as BrowserUpdateParams, type BrowserListParams as BrowserListParams, - type BrowserDeleteParams as BrowserDeleteParams, type BrowserCurlParams as BrowserCurlParams, type BrowserLoadExtensionsParams as BrowserLoadExtensionsParams, }; diff --git a/src/resources/browser-pools.ts b/src/resources/browser-pools.ts index a20c8882..dc1af440 100644 --- a/src/resources/browser-pools.ts +++ b/src/resources/browser-pools.ts @@ -349,12 +349,6 @@ export interface BrowserPoolAcquireResponse { */ kiosk_mode?: boolean; - /** - * @deprecated DEPRECATED: Use timeout_seconds (up to 72 hours) and Profiles - * instead. - */ - persistence?: BrowsersAPI.BrowserPersistence; - /** * Browser pool this session was acquired from, if any. */ diff --git a/src/resources/browsers/browsers.ts b/src/resources/browsers/browsers.ts index 2547d696..a72c5df9 100644 --- a/src/resources/browsers/browsers.ts +++ b/src/resources/browsers/browsers.ts @@ -190,21 +190,6 @@ export class Browsers extends APIResource { return this._client.getAPIList('/browsers', OffsetPagination, { query, ...options }); } - /** - * DEPRECATED: Use DELETE /browsers/{id} instead. Delete a persistent browser - * session by its persistent_id. - * - * @deprecated - */ - delete(params: BrowserDeleteParams, options?: RequestOptions): APIPromise { - const { persistent_id } = params; - return this._client.delete('/browsers', { - query: { persistent_id }, - ...options, - headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), - }); - } - /** * Sends an HTTP request through Chrome's HTTP request stack, inheriting the * browser's TLS fingerprint, cookies, proxy configuration, and headers. Returns a @@ -269,17 +254,6 @@ export type BrowserListResponsesOffsetPagination = OffsetPagination; -/** - * @deprecated DEPRECATED: Use timeout_seconds (up to 72 hours) and Profiles - * instead. - */ -export interface BrowserPersistence { - /** - * DEPRECATED: Unique identifier for the persistent browser session. - */ - id: string; -} - /** * Browser pool this session was acquired from, if any. */ @@ -405,12 +379,6 @@ export interface BrowserCreateResponse { */ kiosk_mode?: boolean; - /** - * @deprecated DEPRECATED: Use timeout_seconds (up to 72 hours) and Profiles - * instead. - */ - persistence?: BrowserPersistence; - /** * Browser pool this session was acquired from, if any. */ @@ -532,12 +500,6 @@ export interface BrowserRetrieveResponse { */ kiosk_mode?: boolean; - /** - * @deprecated DEPRECATED: Use timeout_seconds (up to 72 hours) and Profiles - * instead. - */ - persistence?: BrowserPersistence; - /** * Browser pool this session was acquired from, if any. */ @@ -659,12 +621,6 @@ export interface BrowserUpdateResponse { */ kiosk_mode?: boolean; - /** - * @deprecated DEPRECATED: Use timeout_seconds (up to 72 hours) and Profiles - * instead. - */ - persistence?: BrowserPersistence; - /** * Browser pool this session was acquired from, if any. */ @@ -786,12 +742,6 @@ export interface BrowserListResponse { */ kiosk_mode?: boolean; - /** - * @deprecated DEPRECATED: Use timeout_seconds (up to 72 hours) and Profiles - * instead. - */ - persistence?: BrowserPersistence; - /** * Browser pool this session was acquired from, if any. */ @@ -872,8 +822,7 @@ export interface BrowserCreateParams { /** * Custom Chrome enterprise policy overrides applied to this browser session. Keys * are Chrome enterprise policy names; values must match their expected types. - * Blocked: kernel-managed policies (extensions, proxy, CDP/automation). Ignored - * when reusing an existing persistent session. See + * Blocked: kernel-managed policies (extensions, proxy, CDP/automation). See * https://chromeenterprise.google/policies/ */ chrome_policy?: { [key: string]: unknown }; @@ -906,12 +855,6 @@ export interface BrowserCreateParams { */ kiosk_mode?: boolean; - /** - * @deprecated DEPRECATED: Use timeout_seconds (up to 72 hours) and Profiles - * instead. - */ - persistence?: BrowserPersistence; - /** * Profile selection for the browser session. Provide either id or name. If * specified, the matching profile will be loaded into the browser session. @@ -1045,13 +988,6 @@ export interface BrowserListParams extends OffsetPaginationParams { status?: 'active' | 'deleted' | 'all'; } -export interface BrowserDeleteParams { - /** - * Persistent browser identifier - */ - persistent_id: string; -} - export interface BrowserCurlParams { /** * Target URL (must be http or https). @@ -1116,7 +1052,6 @@ Browsers.Playwright = Playwright; export declare namespace Browsers { export { - type BrowserPersistence as BrowserPersistence, type BrowserPoolRef as BrowserPoolRef, type BrowserUsage as BrowserUsage, type Profile as Profile, @@ -1130,7 +1065,6 @@ export declare namespace Browsers { type BrowserRetrieveParams as BrowserRetrieveParams, type BrowserUpdateParams as BrowserUpdateParams, type BrowserListParams as BrowserListParams, - type BrowserDeleteParams as BrowserDeleteParams, type BrowserCurlParams as BrowserCurlParams, type BrowserLoadExtensionsParams as BrowserLoadExtensionsParams, }; diff --git a/src/resources/browsers/index.ts b/src/resources/browsers/index.ts index 90f686a3..98ba2d8b 100644 --- a/src/resources/browsers/index.ts +++ b/src/resources/browsers/index.ts @@ -2,7 +2,6 @@ export { Browsers, - type BrowserPersistence, type BrowserPoolRef, type BrowserUsage, type Profile, @@ -15,7 +14,6 @@ export { type BrowserRetrieveParams, type BrowserUpdateParams, type BrowserListParams, - type BrowserDeleteParams, type BrowserCurlParams, type BrowserLoadExtensionsParams, type ProfilesOffsetPagination, diff --git a/src/resources/index.ts b/src/resources/index.ts index 789de808..7c3cf90b 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -21,7 +21,6 @@ export { } from './browser-pools'; export { Browsers, - type BrowserPersistence, type BrowserPoolRef, type BrowserUsage, type Profile, @@ -34,7 +33,6 @@ export { type BrowserRetrieveParams, type BrowserUpdateParams, type BrowserListParams, - type BrowserDeleteParams, type BrowserCurlParams, type BrowserLoadExtensionsParams, type ProfilesOffsetPagination, diff --git a/src/resources/invocations.ts b/src/resources/invocations.ts index 50dafd96..b99efb4e 100644 --- a/src/resources/invocations.ts +++ b/src/resources/invocations.ts @@ -488,12 +488,6 @@ export namespace InvocationListBrowsersResponse { */ kiosk_mode?: boolean; - /** - * @deprecated DEPRECATED: Use timeout_seconds (up to 72 hours) and Profiles - * instead. - */ - persistence?: BrowsersAPI.BrowserPersistence; - /** * Browser pool this session was acquired from, if any. */ diff --git a/src/resources/projects/limits.ts b/src/resources/projects/limits.ts index 5475e4db..951ee4f7 100644 --- a/src/resources/projects/limits.ts +++ b/src/resources/projects/limits.ts @@ -54,12 +54,6 @@ export interface ProjectLimits { */ max_concurrent_sessions?: number | null; - /** - * Maximum persistent browser sessions for this project. Null means no - * project-level cap. - */ - max_persistent_sessions?: number | null; - /** * Maximum pooled sessions capacity for this project. Null means no project-level * cap. @@ -80,12 +74,6 @@ export interface UpdateProjectLimitsRequest { */ max_concurrent_sessions?: number | null; - /** - * Maximum persistent browser sessions for this project. Set to 0 to remove the - * cap; omit to leave unchanged. - */ - max_persistent_sessions?: number | null; - /** * Maximum pooled sessions capacity for this project. Set to 0 to remove the cap; * omit to leave unchanged. @@ -106,12 +94,6 @@ export interface LimitUpdateParams { */ max_concurrent_sessions?: number | null; - /** - * Maximum persistent browser sessions for this project. Set to 0 to remove the - * cap; omit to leave unchanged. - */ - max_persistent_sessions?: number | null; - /** * Maximum pooled sessions capacity for this project. Set to 0 to remove the cap; * omit to leave unchanged. diff --git a/tests/api-resources/browsers/browsers.test.ts b/tests/api-resources/browsers/browsers.test.ts index 6329136a..38571042 100644 --- a/tests/api-resources/browsers/browsers.test.ts +++ b/tests/api-resources/browsers/browsers.test.ts @@ -32,7 +32,6 @@ describe('resource browsers', () => { headless: false, invocation_id: 'rr33xuugxj9h0bkf1rdt2bet', kiosk_mode: true, - persistence: { id: 'my-awesome-browser-for-user-1234' }, profile: { id: 'id', name: 'name', @@ -126,23 +125,6 @@ describe('resource browsers', () => { ).rejects.toThrow(Kernel.NotFoundError); }); - // Mock server tests are disabled - test.skip('delete: only required params', async () => { - const responsePromise = client.browsers.delete({ persistent_id: 'persistent_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); - }); - - // Mock server tests are disabled - test.skip('delete: required and optional params', async () => { - const response = await client.browsers.delete({ persistent_id: 'persistent_id' }); - }); - // Mock server tests are disabled test.skip('curl: only required params', async () => { const responsePromise = client.browsers.curl('id', { url: 'url' }); From 4ebed6f2feb5f48ee449aa22421f0aac91da63dd Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 22 May 2026 19:17:14 +0000 Subject: [PATCH 397/551] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 6007fff2..6f5d31f0 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 112 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-346b1affebf16e7f943bcf4db307a5589fcae636c9147dd0afbe5c02cf12ad30.yml -openapi_spec_hash: 348df436759d220264f12450919211c3 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-5d96fec7a84722f300bd99db7352d6284141826f3412f6d370ac0926edf03d42.yml +openapi_spec_hash: d4e1a29ac06f9543e0ef69372eb3ff35 config_hash: ae3dea7997fb5d36fa41979f9585ed78 From 32e34f8d4646fb5005e9e820b3eb2973c684d7dc Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sun, 24 May 2026 21:26:13 +0000 Subject: [PATCH 398/551] feat: api: dual-route /projects under /org/projects, deprecate /projects --- .stats.yml | 6 +++--- api.md | 14 +++++++------- src/resources/projects/limits.ts | 4 ++-- src/resources/projects/projects.ts | 10 +++++----- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/.stats.yml b/.stats.yml index 6f5d31f0..dbf097fb 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 112 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-5d96fec7a84722f300bd99db7352d6284141826f3412f6d370ac0926edf03d42.yml -openapi_spec_hash: d4e1a29ac06f9543e0ef69372eb3ff35 -config_hash: ae3dea7997fb5d36fa41979f9585ed78 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-a0ad160eb0fb11e201e240de8487c12992a474076aeed1c1167ee54ade43edfb.yml +openapi_spec_hash: 84a7075fddbe17b1446a759e8cc39047 +config_hash: 26beac3050665664d5d74d2bbfe9e808 diff --git a/api.md b/api.md index e00297f9..68507b75 100644 --- a/api.md +++ b/api.md @@ -349,11 +349,11 @@ Types: Methods: -- client.projects.create({ ...params }) -> Project -- client.projects.retrieve(id) -> Project -- client.projects.update(id, { ...params }) -> Project -- client.projects.list({ ...params }) -> ProjectsOffsetPagination -- client.projects.delete(id) -> void +- client.projects.create({ ...params }) -> Project +- client.projects.retrieve(id) -> Project +- client.projects.update(id, { ...params }) -> Project +- client.projects.list({ ...params }) -> ProjectsOffsetPagination +- client.projects.delete(id) -> void ## Limits @@ -364,8 +364,8 @@ Types: Methods: -- client.projects.limits.retrieve(id) -> ProjectLimits -- client.projects.limits.update(id, { ...params }) -> ProjectLimits +- client.projects.limits.retrieve(id) -> ProjectLimits +- client.projects.limits.update(id, { ...params }) -> ProjectLimits # CredentialProviders diff --git a/src/resources/projects/limits.ts b/src/resources/projects/limits.ts index 951ee4f7..52ec16ac 100644 --- a/src/resources/projects/limits.ts +++ b/src/resources/projects/limits.ts @@ -21,7 +21,7 @@ export class Limits extends APIResource { * ``` */ retrieve(id: string, options?: RequestOptions): APIPromise { - return this._client.get(path`/projects/${id}/limits`, options); + return this._client.get(path`/org/projects/${id}/limits`, options); } /** @@ -37,7 +37,7 @@ export class Limits extends APIResource { * ``` */ update(id: string, body: LimitUpdateParams, options?: RequestOptions): APIPromise { - return this._client.patch(path`/projects/${id}/limits`, { body, ...options }); + return this._client.patch(path`/org/projects/${id}/limits`, { body, ...options }); } } diff --git a/src/resources/projects/projects.ts b/src/resources/projects/projects.ts index dba12289..520b1afb 100644 --- a/src/resources/projects/projects.ts +++ b/src/resources/projects/projects.ts @@ -26,7 +26,7 @@ export class Projects extends APIResource { * ``` */ create(body: ProjectCreateParams, options?: RequestOptions): APIPromise { - return this._client.post('/projects', { body, ...options }); + return this._client.post('/org/projects', { body, ...options }); } /** @@ -38,7 +38,7 @@ export class Projects extends APIResource { * ``` */ retrieve(id: string, options?: RequestOptions): APIPromise { - return this._client.get(path`/projects/${id}`, options); + return this._client.get(path`/org/projects/${id}`, options); } /** @@ -50,7 +50,7 @@ export class Projects extends APIResource { * ``` */ update(id: string, body: ProjectUpdateParams, options?: RequestOptions): APIPromise { - return this._client.patch(path`/projects/${id}`, { body, ...options }); + return this._client.patch(path`/org/projects/${id}`, { body, ...options }); } /** @@ -68,7 +68,7 @@ export class Projects extends APIResource { query: ProjectListParams | null | undefined = {}, options?: RequestOptions, ): PagePromise { - return this._client.getAPIList('/projects', OffsetPagination, { query, ...options }); + return this._client.getAPIList('/org/projects', OffsetPagination, { query, ...options }); } /** @@ -80,7 +80,7 @@ export class Projects extends APIResource { * ``` */ delete(id: string, options?: RequestOptions): APIPromise { - return this._client.delete(path`/projects/${id}`, { + return this._client.delete(path`/org/projects/${id}`, { ...options, headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), }); From 870a7e4ae01ab3d6e23934859f51569ad30a364e Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 26 May 2026 17:42:50 +0000 Subject: [PATCH 399/551] feat: Support telemetry enabled request config --- .stats.yml | 6 ++--- api.md | 1 + src/resources/browsers/browsers.ts | 21 +++++++++------- src/resources/browsers/index.ts | 1 + src/resources/browsers/telemetry.ts | 24 +++++++++++++++++-- tests/api-resources/browsers/browsers.test.ts | 1 + yarn.lock | 6 ++--- 7 files changed, 44 insertions(+), 16 deletions(-) diff --git a/.stats.yml b/.stats.yml index dbf097fb..47ab7c16 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 112 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-a0ad160eb0fb11e201e240de8487c12992a474076aeed1c1167ee54ade43edfb.yml -openapi_spec_hash: 84a7075fddbe17b1446a759e8cc39047 -config_hash: 26beac3050665664d5d74d2bbfe9e808 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-e9c99662d29710f105847d461f8919e06f6aa2e43b0e1a6285d0b137643a7907.yml +openapi_spec_hash: 4415cb4790c7a5ec892f4e3521217cb4 +config_hash: 27b38657d9a3b33328be930eeb319628 diff --git a/api.md b/api.md index 68507b75..35dc8240 100644 --- a/api.md +++ b/api.md @@ -119,6 +119,7 @@ Types: - BrowserTelemetryCategoryConfig - BrowserTelemetryConfig - BrowserTelemetryEvent +- BrowserTelemetryRequestConfig - TelemetryStreamResponse Methods: diff --git a/src/resources/browsers/browsers.ts b/src/resources/browsers/browsers.ts index a72c5df9..e7a8d126 100644 --- a/src/resources/browsers/browsers.ts +++ b/src/resources/browsers/browsers.ts @@ -82,6 +82,7 @@ import { BrowserTelemetryCategoryConfig, BrowserTelemetryConfig, BrowserTelemetryEvent, + BrowserTelemetryRequestConfig, Telemetry, TelemetryStreamParams, TelemetryStreamResponse, @@ -882,11 +883,13 @@ export interface BrowserCreateParams { stealth?: boolean; /** - * Telemetry configuration for the browser session. If provided, telemetry capture - * starts with the specified category filter when the session is created. If - * omitted, no telemetry capture is started. + * Telemetry configuration for the browser session. Set enabled to true to start + * capture using VM defaults, or provide browser category settings. If omitted, + * null, set to an empty object ({}), set to enabled: false without browser + * category settings, or all four categories are explicitly disabled, capture is + * not started. */ - telemetry?: TelemetryAPI.BrowserTelemetryConfig | null; + telemetry?: TelemetryAPI.BrowserTelemetryRequestConfig | null; /** * The number of seconds of inactivity before the browser session is terminated. @@ -942,11 +945,12 @@ export interface BrowserUpdateParams { /** * Telemetry configuration. Omit, set to null, or set to an empty object ({}) to - * leave the existing configuration unchanged (no-op). To enable capture for all - * categories using VM defaults, set browser to an empty object ({"browser": {}}). - * To stop capture, set every category's enabled to false. + * leave the existing configuration unchanged. Set enabled to true to enable + * capture using VM defaults. Set enabled to false to stop capture. Provide browser + * category settings for per-category updates. Explicitly disabling all four + * categories also stops capture. */ - telemetry?: TelemetryAPI.BrowserTelemetryConfig | null; + telemetry?: TelemetryAPI.BrowserTelemetryRequestConfig | null; /** * Viewport configuration to apply to the browser session. @@ -1101,6 +1105,7 @@ export declare namespace Browsers { type BrowserTelemetryCategoryConfig as BrowserTelemetryCategoryConfig, type BrowserTelemetryConfig as BrowserTelemetryConfig, type BrowserTelemetryEvent as BrowserTelemetryEvent, + type BrowserTelemetryRequestConfig as BrowserTelemetryRequestConfig, type TelemetryStreamResponse as TelemetryStreamResponse, type TelemetryStreamParams as TelemetryStreamParams, }; diff --git a/src/resources/browsers/index.ts b/src/resources/browsers/index.ts index 98ba2d8b..f804b6cb 100644 --- a/src/resources/browsers/index.ts +++ b/src/resources/browsers/index.ts @@ -111,6 +111,7 @@ export { type BrowserTelemetryCategoryConfig, type BrowserTelemetryConfig, type BrowserTelemetryEvent, + type BrowserTelemetryRequestConfig, type TelemetryStreamResponse, type TelemetryStreamParams, } from './telemetry'; diff --git a/src/resources/browsers/telemetry.ts b/src/resources/browsers/telemetry.ts index 4c3adf52..2d41d3e4 100644 --- a/src/resources/browsers/telemetry.ts +++ b/src/resources/browsers/telemetry.ts @@ -1412,11 +1412,11 @@ export interface BrowserTelemetryCategoryConfig { } /** - * Telemetry configuration for a browser session. + * Active telemetry configuration for a browser session. */ export interface BrowserTelemetryConfig { /** - * Per-category enable/disable flags. If omitted, all categories are captured. + * Per-category enable/disable flags. */ browser?: BrowserTelemetryCategoriesConfig; } @@ -1452,6 +1452,25 @@ export type BrowserTelemetryEvent = | BrowserMonitorReconnectFailedEvent | BrowserMonitorInitFailedEvent; +/** + * Telemetry request configuration for a browser session. + */ +export interface BrowserTelemetryRequestConfig { + /** + * Per-category enable/disable flags. If enabled is true and browser is omitted or + * empty, the VM default category set is used. Explicitly disabling all four + * categories stops capture on update and starts no capture on create. + */ + browser?: BrowserTelemetryCategoriesConfig; + + /** + * Request shortcut for browser telemetry capture. True enables capture using VM + * defaults. False stops capture on update and starts no capture on create. Cannot + * be combined with browser category settings. + */ + enabled?: boolean; +} + /** * Envelope wrapping a browser telemetry event with its monotonic sequence number. * Each SSE data: frame carries one envelope as JSON. The seq value is also emitted @@ -1515,6 +1534,7 @@ export declare namespace Telemetry { type BrowserTelemetryCategoryConfig as BrowserTelemetryCategoryConfig, type BrowserTelemetryConfig as BrowserTelemetryConfig, type BrowserTelemetryEvent as BrowserTelemetryEvent, + type BrowserTelemetryRequestConfig as BrowserTelemetryRequestConfig, type TelemetryStreamResponse as TelemetryStreamResponse, type TelemetryStreamParams as TelemetryStreamParams, }; diff --git a/tests/api-resources/browsers/browsers.test.ts b/tests/api-resources/browsers/browsers.test.ts index 38571042..370bfc5e 100644 --- a/tests/api-resources/browsers/browsers.test.ts +++ b/tests/api-resources/browsers/browsers.test.ts @@ -47,6 +47,7 @@ describe('resource browsers', () => { network: { enabled: true }, page: { enabled: true }, }, + enabled: true, }, timeout_seconds: 10, viewport: { diff --git a/yarn.lock b/yarn.lock index 00842e32..06fc1085 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1215,9 +1215,9 @@ baseline-browser-mapping@^2.9.0: integrity sha512-B0xUquLkiGLgHhpPBqvl7GWegWBUNuujQ6kXd/r1U38ElPT6Ok8KZ8e+FpUGEc2ZoRQUzq/aUnaKFc/svWUGSg== brace-expansion@^2.0.2: - version "2.1.0" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.1.0.tgz#4f41a41190216ee36067ec381526fe9539c4f0ae" - integrity sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w== + version "2.1.1" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.1.1.tgz#c68b1c4111c76aae3a6fba55d496cee10c39dad8" + integrity sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA== dependencies: balanced-match "^1.0.0" From ed7d598fa7d872064af9fabe5ecf4d43870cef2b Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 26 May 2026 18:28:30 +0000 Subject: [PATCH 400/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index b2ddd217..e2fcf21d 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.55.0" + ".": "0.57.0" } diff --git a/package.json b/package.json index c032f0d5..95aff5be 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.55.0", + "version": "0.57.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 7c47df59..63fdbe05 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.55.0'; // x-release-please-version +export const VERSION = '0.57.0'; // x-release-please-version From f016a21faa651192548328e4ebbdc7c7679eae1b Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 26 May 2026 18:34:04 +0000 Subject: [PATCH 401/551] feat: Support telemetry enabled request config and fix SDK metadata --- .stats.yml | 6 +-- api.md | 1 - src/resources/browsers/browsers.ts | 62 +++++++++++++++++++++++++---- src/resources/browsers/index.ts | 1 - src/resources/browsers/telemetry.ts | 20 ---------- 5 files changed, 58 insertions(+), 32 deletions(-) diff --git a/.stats.yml b/.stats.yml index 47ab7c16..7fdb7bfb 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 112 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-e9c99662d29710f105847d461f8919e06f6aa2e43b0e1a6285d0b137643a7907.yml -openapi_spec_hash: 4415cb4790c7a5ec892f4e3521217cb4 -config_hash: 27b38657d9a3b33328be930eeb319628 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-0a186c486b56f555cab374ea5f2adbef2d718b5c9190a48c862f0fdf1232324f.yml +openapi_spec_hash: fad386b8e8712e6639ed9689e9dfc070 +config_hash: 5dde8b5de321a7bb96f695a69eb21c23 diff --git a/api.md b/api.md index 35dc8240..68507b75 100644 --- a/api.md +++ b/api.md @@ -119,7 +119,6 @@ Types: - BrowserTelemetryCategoryConfig - BrowserTelemetryConfig - BrowserTelemetryEvent -- BrowserTelemetryRequestConfig - TelemetryStreamResponse Methods: diff --git a/src/resources/browsers/browsers.ts b/src/resources/browsers/browsers.ts index e7a8d126..911837bb 100644 --- a/src/resources/browsers/browsers.ts +++ b/src/resources/browsers/browsers.ts @@ -82,8 +82,7 @@ import { BrowserTelemetryCategoryConfig, BrowserTelemetryConfig, BrowserTelemetryEvent, - BrowserTelemetryRequestConfig, - Telemetry, + Telemetry as TelemetryAPITelemetry, TelemetryStreamParams, TelemetryStreamResponse, } from './telemetry'; @@ -889,7 +888,7 @@ export interface BrowserCreateParams { * category settings, or all four categories are explicitly disabled, capture is * not started. */ - telemetry?: TelemetryAPI.BrowserTelemetryRequestConfig | null; + telemetry?: BrowserCreateParams.Telemetry | null; /** * The number of seconds of inactivity before the browser session is terminated. @@ -917,6 +916,32 @@ export interface BrowserCreateParams { viewport?: Shared.BrowserViewport; } +export namespace BrowserCreateParams { + /** + * Telemetry configuration for the browser session. Set enabled to true to start + * capture using VM defaults, or provide browser category settings. If omitted, + * null, set to an empty object ({}), set to enabled: false without browser + * category settings, or all four categories are explicitly disabled, capture is + * not started. + */ + export interface Telemetry { + /** + * Per-category enable/disable flags. If enabled is true and browser is omitted or + * empty, the VM default category set is used. Explicitly disabling all four + * categories stops capture on update and starts no capture on create. + */ + browser?: TelemetryAPI.BrowserTelemetryCategoriesConfig; + + /** + * Request shortcut for browser telemetry capture. True enables capture using VM + * defaults unless browser category settings are provided. False stops capture on + * update and starts no capture on create. enabled=false cannot be combined with + * browser category settings. + */ + enabled?: boolean; + } +} + export interface BrowserRetrieveParams { /** * When true, includes soft-deleted browser sessions in the lookup. @@ -950,7 +975,7 @@ export interface BrowserUpdateParams { * category settings for per-category updates. Explicitly disabling all four * categories also stops capture. */ - telemetry?: TelemetryAPI.BrowserTelemetryRequestConfig | null; + telemetry?: BrowserUpdateParams.Telemetry | null; /** * Viewport configuration to apply to the browser session. @@ -959,6 +984,30 @@ export interface BrowserUpdateParams { } export namespace BrowserUpdateParams { + /** + * Telemetry configuration. Omit, set to null, or set to an empty object ({}) to + * leave the existing configuration unchanged. Set enabled to true to enable + * capture using VM defaults. Set enabled to false to stop capture. Provide browser + * category settings for per-category updates. Explicitly disabling all four + * categories also stops capture. + */ + export interface Telemetry { + /** + * Per-category enable/disable flags. If enabled is true and browser is omitted or + * empty, the VM default category set is used. Explicitly disabling all four + * categories stops capture on update and starts no capture on create. + */ + browser?: TelemetryAPI.BrowserTelemetryCategoriesConfig; + + /** + * Request shortcut for browser telemetry capture. True enables capture using VM + * defaults unless browser category settings are provided. False stops capture on + * update and starts no capture on create. enabled=false cannot be combined with + * browser category settings. + */ + enabled?: boolean; + } + /** * Viewport configuration to apply to the browser session. */ @@ -1046,7 +1095,7 @@ export namespace BrowserLoadExtensionsParams { } } -Browsers.Telemetry = Telemetry; +Browsers.Telemetry = TelemetryAPITelemetry; Browsers.Replays = Replays; Browsers.Fs = Fs; Browsers.Process = Process; @@ -1074,7 +1123,7 @@ export declare namespace Browsers { }; export { - Telemetry as Telemetry, + TelemetryAPITelemetry as Telemetry, type BrowserCallStack as BrowserCallStack, type BrowserConsoleErrorEvent as BrowserConsoleErrorEvent, type BrowserConsoleLogEvent as BrowserConsoleLogEvent, @@ -1105,7 +1154,6 @@ export declare namespace Browsers { type BrowserTelemetryCategoryConfig as BrowserTelemetryCategoryConfig, type BrowserTelemetryConfig as BrowserTelemetryConfig, type BrowserTelemetryEvent as BrowserTelemetryEvent, - type BrowserTelemetryRequestConfig as BrowserTelemetryRequestConfig, type TelemetryStreamResponse as TelemetryStreamResponse, type TelemetryStreamParams as TelemetryStreamParams, }; diff --git a/src/resources/browsers/index.ts b/src/resources/browsers/index.ts index f804b6cb..98ba2d8b 100644 --- a/src/resources/browsers/index.ts +++ b/src/resources/browsers/index.ts @@ -111,7 +111,6 @@ export { type BrowserTelemetryCategoryConfig, type BrowserTelemetryConfig, type BrowserTelemetryEvent, - type BrowserTelemetryRequestConfig, type TelemetryStreamResponse, type TelemetryStreamParams, } from './telemetry'; diff --git a/src/resources/browsers/telemetry.ts b/src/resources/browsers/telemetry.ts index 2d41d3e4..f9ff2d42 100644 --- a/src/resources/browsers/telemetry.ts +++ b/src/resources/browsers/telemetry.ts @@ -1452,25 +1452,6 @@ export type BrowserTelemetryEvent = | BrowserMonitorReconnectFailedEvent | BrowserMonitorInitFailedEvent; -/** - * Telemetry request configuration for a browser session. - */ -export interface BrowserTelemetryRequestConfig { - /** - * Per-category enable/disable flags. If enabled is true and browser is omitted or - * empty, the VM default category set is used. Explicitly disabling all four - * categories stops capture on update and starts no capture on create. - */ - browser?: BrowserTelemetryCategoriesConfig; - - /** - * Request shortcut for browser telemetry capture. True enables capture using VM - * defaults. False stops capture on update and starts no capture on create. Cannot - * be combined with browser category settings. - */ - enabled?: boolean; -} - /** * Envelope wrapping a browser telemetry event with its monotonic sequence number. * Each SSE data: frame carries one envelope as JSON. The seq value is also emitted @@ -1534,7 +1515,6 @@ export declare namespace Telemetry { type BrowserTelemetryCategoryConfig as BrowserTelemetryCategoryConfig, type BrowserTelemetryConfig as BrowserTelemetryConfig, type BrowserTelemetryEvent as BrowserTelemetryEvent, - type BrowserTelemetryRequestConfig as BrowserTelemetryRequestConfig, type TelemetryStreamResponse as TelemetryStreamResponse, type TelemetryStreamParams as TelemetryStreamParams, }; From fdf264a756639341e0c4584482f52ecade75c278 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 27 May 2026 15:07:52 +0000 Subject: [PATCH 402/551] feat: [codex] Expose API keys in SDK config --- .stats.yml | 6 +- api.md | 17 +++ src/client.ts | 28 ++++ src/resources/api-keys.ts | 221 +++++++++++++++++++++++++++ src/resources/index.ts | 11 ++ tests/api-resources/api-keys.test.ts | 92 +++++++++++ 6 files changed, 372 insertions(+), 3 deletions(-) create mode 100644 src/resources/api-keys.ts create mode 100644 tests/api-resources/api-keys.test.ts diff --git a/.stats.yml b/.stats.yml index 7fdb7bfb..e86e3342 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 112 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-0a186c486b56f555cab374ea5f2adbef2d718b5c9190a48c862f0fdf1232324f.yml +configured_endpoints: 117 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-54d9016df9730e65881df9f694df4f33620b0c032f177849d36ccc426cd42fa8.yml openapi_spec_hash: fad386b8e8712e6639ed9689e9dfc070 -config_hash: 5dde8b5de321a7bb96f695a69eb21c23 +config_hash: 58396d6c1fafaf72b26596b9117edf48 diff --git a/api.md b/api.md index 68507b75..e3b8c121 100644 --- a/api.md +++ b/api.md @@ -367,6 +367,23 @@ Methods: - client.projects.limits.retrieve(id) -> ProjectLimits - client.projects.limits.update(id, { ...params }) -> ProjectLimits +# APIKeys + +Types: + +- APIKey +- CreateAPIKeyRequest +- CreatedAPIKey +- UpdateAPIKeyRequest + +Methods: + +- client.apiKeys.create({ ...params }) -> CreatedAPIKey +- client.apiKeys.retrieve(id) -> APIKey +- client.apiKeys.update(id, { ...params }) -> APIKey +- client.apiKeys.list({ ...params }) -> APIKeysOffsetPagination +- client.apiKeys.delete(id) -> void + # CredentialProviders Types: diff --git a/src/client.ts b/src/client.ts index 4aa2a3e4..90482593 100644 --- a/src/client.ts +++ b/src/client.ts @@ -19,6 +19,17 @@ import { AbstractPage, type OffsetPaginationParams, OffsetPaginationResponse } f import * as Uploads from './core/uploads'; import * as API from './resources/index'; import { APIPromise } from './core/api-promise'; +import { + APIKey, + APIKeyCreateParams, + APIKeyListParams, + APIKeyUpdateParams, + APIKeys, + APIKeysOffsetPagination, + CreateAPIKeyRequest, + CreatedAPIKey, + UpdateAPIKeyRequest, +} from './resources/api-keys'; import { AppListParams, AppListResponse, AppListResponsesOffsetPagination, Apps } from './resources/apps'; import { BrowserPool, @@ -928,6 +939,10 @@ export class Kernel { * Create and manage projects for resource isolation within an organization. */ projects: API.Projects = new API.Projects(this); + /** + * Create and manage API keys for organization and project-scoped access. + */ + apiKeys: API.APIKeys = new API.APIKeys(this); /** * Configure external credential providers like 1Password. */ @@ -945,6 +960,7 @@ Kernel.Extensions = Extensions; Kernel.BrowserPools = BrowserPools; Kernel.Credentials = Credentials; Kernel.Projects = Projects; +Kernel.APIKeys = APIKeys; Kernel.CredentialProviders = CredentialProviders; export declare namespace Kernel { @@ -1072,6 +1088,18 @@ export declare namespace Kernel { type ProjectListParams as ProjectListParams, }; + export { + APIKeys as APIKeys, + type APIKey as APIKey, + type CreateAPIKeyRequest as CreateAPIKeyRequest, + type CreatedAPIKey as CreatedAPIKey, + type UpdateAPIKeyRequest as UpdateAPIKeyRequest, + type APIKeysOffsetPagination as APIKeysOffsetPagination, + type APIKeyCreateParams as APIKeyCreateParams, + type APIKeyUpdateParams as APIKeyUpdateParams, + type APIKeyListParams as APIKeyListParams, + }; + export { CredentialProviders as CredentialProviders, type CreateCredentialProviderRequest as CreateCredentialProviderRequest, diff --git a/src/resources/api-keys.ts b/src/resources/api-keys.ts new file mode 100644 index 00000000..80052c58 --- /dev/null +++ b/src/resources/api-keys.ts @@ -0,0 +1,221 @@ +// 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 { OffsetPagination, type OffsetPaginationParams, PagePromise } from '../core/pagination'; +import { buildHeaders } from '../internal/headers'; +import { RequestOptions } from '../internal/request-options'; +import { path } from '../internal/utils/path'; + +/** + * Create and manage API keys for organization and project-scoped access. + */ +export class APIKeys extends APIResource { + /** + * Create a new API key within the authenticated organization. + * + * @example + * ```ts + * const createdAPIKey = await client.apiKeys.create({ + * name: 'staging', + * }); + * ``` + */ + create(body: APIKeyCreateParams, options?: RequestOptions): APIPromise { + return this._client.post('/org/api_keys', { body, ...options }); + } + + /** + * Retrieve an API key by ID for the authenticated organization. API keys are + * masked. + * + * @example + * ```ts + * const apiKey = await client.apiKeys.retrieve('id'); + * ``` + */ + retrieve(id: string, options?: RequestOptions): APIPromise { + return this._client.get(path`/org/api_keys/${id}`, options); + } + + /** + * Update an API key's name. + * + * @example + * ```ts + * const apiKey = await client.apiKeys.update('id', { + * name: 'new-api-name', + * }); + * ``` + */ + update(id: string, body: APIKeyUpdateParams, options?: RequestOptions): APIPromise { + return this._client.patch(path`/org/api_keys/${id}`, { body, ...options }); + } + + /** + * List API keys for the authenticated organization. API keys are masked. + * + * @example + * ```ts + * // Automatically fetches more pages as needed. + * for await (const apiKey of client.apiKeys.list()) { + * // ... + * } + * ``` + */ + list( + query: APIKeyListParams | null | undefined = {}, + options?: RequestOptions, + ): PagePromise { + return this._client.getAPIList('/org/api_keys', OffsetPagination, { query, ...options }); + } + + /** + * Delete an API key. + * + * @example + * ```ts + * await client.apiKeys.delete('id'); + * ``` + */ + delete(id: string, options?: RequestOptions): APIPromise { + return this._client.delete(path`/org/api_keys/${id}`, { + ...options, + headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), + }); + } +} + +export type APIKeysOffsetPagination = OffsetPagination; + +export interface APIKey { + /** + * Unique API key identifier + */ + id: string; + + /** + * When the API key was created + */ + created_at: string; + + created_by: APIKey.CreatedBy; + + /** + * When the API key expires + */ + expires_at: string | null; + + /** + * Masked version of the API key + */ + masked_key: string; + + /** + * API key name + */ + name: string; + + /** + * Project identifier for project-scoped API keys. Null means org-wide. + */ + project_id: string | null; + + /** + * Project name for project-scoped API keys. Null means the key is org-wide or the + * project name is unavailable. + */ + project_name: string | null; +} + +export namespace APIKey { + export interface CreatedBy { + /** + * Kernel user ID of the creator. + */ + id: string; + + /** + * Email address of the creator. + */ + email: string; + + /** + * Display name of the creator, if available. + */ + name: string | null; + } +} + +export interface CreateAPIKeyRequest { + /** + * API key name (1-255 characters) + */ + name: string; + + /** + * Number of days until expiry, up to 3650. Use null for never. + */ + days_to_expire?: number | null; + + /** + * Unique project identifier + */ + project_id?: string | null; +} + +/** + * API key returned immediately after creation. Includes the plaintext key once. + */ +export interface CreatedAPIKey extends APIKey { + /** + * Plaintext API key. Only returned once when the key is created. + */ + key: string; +} + +export interface UpdateAPIKeyRequest { + /** + * New API key name + */ + name: string; +} + +export interface APIKeyCreateParams { + /** + * API key name (1-255 characters) + */ + name: string; + + /** + * Number of days until expiry, up to 3650. Use null for never. + */ + days_to_expire?: number | null; + + /** + * Unique project identifier + */ + project_id?: string | null; +} + +export interface APIKeyUpdateParams { + /** + * New API key name + */ + name: string; +} + +export interface APIKeyListParams extends OffsetPaginationParams {} + +export declare namespace APIKeys { + export { + type APIKey as APIKey, + type CreateAPIKeyRequest as CreateAPIKeyRequest, + type CreatedAPIKey as CreatedAPIKey, + type UpdateAPIKeyRequest as UpdateAPIKeyRequest, + type APIKeysOffsetPagination as APIKeysOffsetPagination, + type APIKeyCreateParams as APIKeyCreateParams, + type APIKeyUpdateParams as APIKeyUpdateParams, + type APIKeyListParams as APIKeyListParams, + }; +} diff --git a/src/resources/index.ts b/src/resources/index.ts index 7c3cf90b..cc34c0bd 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -1,6 +1,17 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. export * from './shared'; +export { + APIKeys, + type APIKey, + type CreateAPIKeyRequest, + type CreatedAPIKey, + type UpdateAPIKeyRequest, + type APIKeyCreateParams, + type APIKeyUpdateParams, + type APIKeyListParams, + type APIKeysOffsetPagination, +} from './api-keys'; export { Apps, type AppListResponse, diff --git a/tests/api-resources/api-keys.test.ts b/tests/api-resources/api-keys.test.ts new file mode 100644 index 00000000..c39c2228 --- /dev/null +++ b/tests/api-resources/api-keys.test.ts @@ -0,0 +1,92 @@ +// 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 apiKeys', () => { + // Mock server tests are disabled + test.skip('create: only required params', async () => { + const responsePromise = client.apiKeys.create({ name: 'staging' }); + 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); + }); + + // Mock server tests are disabled + test.skip('create: required and optional params', async () => { + const response = await client.apiKeys.create({ + name: 'staging', + days_to_expire: 30, + project_id: 'proj_abc123', + }); + }); + + // Mock server tests are disabled + test.skip('retrieve', async () => { + const responsePromise = client.apiKeys.retrieve('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); + }); + + // Mock server tests are disabled + test.skip('update: only required params', async () => { + const responsePromise = client.apiKeys.update('id', { name: 'new-api-name' }); + 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); + }); + + // Mock server tests are disabled + test.skip('update: required and optional params', async () => { + const response = await client.apiKeys.update('id', { name: 'new-api-name' }); + }); + + // Mock server tests are disabled + test.skip('list', async () => { + const responsePromise = client.apiKeys.list(); + 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); + }); + + // Mock server tests are disabled + test.skip('list: 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.apiKeys.list({ limit: 100, offset: 0 }, { path: '/_stainless_unknown_path' }), + ).rejects.toThrow(Kernel.NotFoundError); + }); + + // Mock server tests are disabled + test.skip('delete', async () => { + const responsePromise = client.apiKeys.delete('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); + }); +}); From b564c3f758ff72a70dba8030f0fd17b7c7efb7e0 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 27 May 2026 17:08:54 +0000 Subject: [PATCH 403/551] feat: Fix API key request model SDK metadata --- .stats.yml | 4 ++-- api.md | 2 -- src/client.ts | 4 ---- src/resources/api-keys.ts | 26 -------------------------- src/resources/index.ts | 2 -- 5 files changed, 2 insertions(+), 36 deletions(-) diff --git a/.stats.yml b/.stats.yml index e86e3342..3cfc09d4 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 117 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-54d9016df9730e65881df9f694df4f33620b0c032f177849d36ccc426cd42fa8.yml +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-3b34d85c005a4058ac1faaea092615af577d12cee6e420f102de57339251672d.yml openapi_spec_hash: fad386b8e8712e6639ed9689e9dfc070 -config_hash: 58396d6c1fafaf72b26596b9117edf48 +config_hash: 0f222358f24700d1811c5d27078a3849 diff --git a/api.md b/api.md index e3b8c121..4ac5b01d 100644 --- a/api.md +++ b/api.md @@ -372,9 +372,7 @@ Methods: Types: - APIKey -- CreateAPIKeyRequest - CreatedAPIKey -- UpdateAPIKeyRequest Methods: diff --git a/src/client.ts b/src/client.ts index 90482593..30b48de1 100644 --- a/src/client.ts +++ b/src/client.ts @@ -26,9 +26,7 @@ import { APIKeyUpdateParams, APIKeys, APIKeysOffsetPagination, - CreateAPIKeyRequest, CreatedAPIKey, - UpdateAPIKeyRequest, } from './resources/api-keys'; import { AppListParams, AppListResponse, AppListResponsesOffsetPagination, Apps } from './resources/apps'; import { @@ -1091,9 +1089,7 @@ export declare namespace Kernel { export { APIKeys as APIKeys, type APIKey as APIKey, - type CreateAPIKeyRequest as CreateAPIKeyRequest, type CreatedAPIKey as CreatedAPIKey, - type UpdateAPIKeyRequest as UpdateAPIKeyRequest, type APIKeysOffsetPagination as APIKeysOffsetPagination, type APIKeyCreateParams as APIKeyCreateParams, type APIKeyUpdateParams as APIKeyUpdateParams, diff --git a/src/resources/api-keys.ts b/src/resources/api-keys.ts index 80052c58..cad02c32 100644 --- a/src/resources/api-keys.ts +++ b/src/resources/api-keys.ts @@ -147,23 +147,6 @@ export namespace APIKey { } } -export interface CreateAPIKeyRequest { - /** - * API key name (1-255 characters) - */ - name: string; - - /** - * Number of days until expiry, up to 3650. Use null for never. - */ - days_to_expire?: number | null; - - /** - * Unique project identifier - */ - project_id?: string | null; -} - /** * API key returned immediately after creation. Includes the plaintext key once. */ @@ -174,13 +157,6 @@ export interface CreatedAPIKey extends APIKey { key: string; } -export interface UpdateAPIKeyRequest { - /** - * New API key name - */ - name: string; -} - export interface APIKeyCreateParams { /** * API key name (1-255 characters) @@ -210,9 +186,7 @@ export interface APIKeyListParams extends OffsetPaginationParams {} export declare namespace APIKeys { export { type APIKey as APIKey, - type CreateAPIKeyRequest as CreateAPIKeyRequest, type CreatedAPIKey as CreatedAPIKey, - type UpdateAPIKeyRequest as UpdateAPIKeyRequest, type APIKeysOffsetPagination as APIKeysOffsetPagination, type APIKeyCreateParams as APIKeyCreateParams, type APIKeyUpdateParams as APIKeyUpdateParams, diff --git a/src/resources/index.ts b/src/resources/index.ts index cc34c0bd..985b7d04 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -4,9 +4,7 @@ export * from './shared'; export { APIKeys, type APIKey, - type CreateAPIKeyRequest, type CreatedAPIKey, - type UpdateAPIKeyRequest, type APIKeyCreateParams, type APIKeyUpdateParams, type APIKeyListParams, From 08d4cd1895a960eea30514c341719cb6c81ec639 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 27 May 2026 19:04:40 +0000 Subject: [PATCH 404/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index e2fcf21d..115a387a 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.57.0" + ".": "0.58.0" } diff --git a/package.json b/package.json index 95aff5be..0758b8f2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.57.0", + "version": "0.58.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 63fdbe05..d5defc55 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.57.0'; // x-release-please-version +export const VERSION = '0.58.0'; // x-release-please-version From 89a418ae3c93927d6181cc676cdaec799c823db1 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 27 May 2026 20:48:09 +0000 Subject: [PATCH 405/551] feat: Support Byteful mobile proxies --- .stats.yml | 4 +- src/resources/proxies.ts | 390 +-------------------------------------- 2 files changed, 12 insertions(+), 382 deletions(-) diff --git a/.stats.yml b/.stats.yml index 3cfc09d4..834590a5 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 117 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-3b34d85c005a4058ac1faaea092615af577d12cee6e420f102de57339251672d.yml -openapi_spec_hash: fad386b8e8712e6639ed9689e9dfc070 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-a32ac633a8f67f3844b6ccb7b97687aec2cf2e2c611df4157c223dfac16db806.yml +openapi_spec_hash: f8c9aabe60372f28ad9cceed42009274 config_hash: 0f222358f24700d1811c5d27078a3849 diff --git a/src/resources/proxies.ts b/src/resources/proxies.ts index b2eb5674..be5a4253 100644 --- a/src/resources/proxies.ts +++ b/src/resources/proxies.ts @@ -173,76 +173,7 @@ export namespace ProxyCreateResponse { */ export interface MobileProxyConfig { /** - * Autonomous system number. See https://bgp.potaroo.net/cidr/autnums.html - */ - asn?: string; - - /** - * Mobile carrier. - */ - carrier?: - | 'a1' - | 'aircel' - | 'airtel' - | 'att' - | 'celcom' - | 'chinamobile' - | 'claro' - | 'comcast' - | 'cox' - | 'digi' - | 'dt' - | 'docomo' - | 'dtac' - | 'etisalat' - | 'idea' - | 'kyivstar' - | 'meo' - | 'megafon' - | 'mtn' - | 'mtnza' - | 'mts' - | 'optus' - | 'orange' - | 'qwest' - | 'reliance_jio' - | 'robi' - | 'sprint' - | 'telefonica' - | 'telstra' - | 'tmobile' - | 'tigo' - | 'tim' - | 'verizon' - | 'vimpelcom' - | 'vodacomza' - | 'vodafone' - | 'vivo' - | 'zain' - | 'vivabo' - | 'telenormyanmar' - | 'kcelljsc' - | 'swisscom' - | 'singtel' - | 'asiacell' - | 'windit' - | 'cellc' - | 'ooredoo' - | 'drei' - | 'umobile' - | 'cableone' - | 'proximus' - | 'tele2' - | 'mobitel' - | 'o2' - | 'bouygues' - | 'free' - | 'sfr' - | 'digicel'; - - /** - * City name (no spaces, e.g. `sanfrancisco`). If provided, `country` must also be - * provided. + * Provider city alias. Mobile carrier routing can make observed geo vary. */ city?: string; @@ -252,14 +183,9 @@ export namespace ProxyCreateResponse { country?: string; /** - * Two-letter state code. + * US-only state code. Mobile carrier routing can make observed geo vary. */ state?: string; - - /** - * US ZIP code. - */ - zip?: string; } /** @@ -403,76 +329,7 @@ export namespace ProxyRetrieveResponse { */ export interface MobileProxyConfig { /** - * Autonomous system number. See https://bgp.potaroo.net/cidr/autnums.html - */ - asn?: string; - - /** - * Mobile carrier. - */ - carrier?: - | 'a1' - | 'aircel' - | 'airtel' - | 'att' - | 'celcom' - | 'chinamobile' - | 'claro' - | 'comcast' - | 'cox' - | 'digi' - | 'dt' - | 'docomo' - | 'dtac' - | 'etisalat' - | 'idea' - | 'kyivstar' - | 'meo' - | 'megafon' - | 'mtn' - | 'mtnza' - | 'mts' - | 'optus' - | 'orange' - | 'qwest' - | 'reliance_jio' - | 'robi' - | 'sprint' - | 'telefonica' - | 'telstra' - | 'tmobile' - | 'tigo' - | 'tim' - | 'verizon' - | 'vimpelcom' - | 'vodacomza' - | 'vodafone' - | 'vivo' - | 'zain' - | 'vivabo' - | 'telenormyanmar' - | 'kcelljsc' - | 'swisscom' - | 'singtel' - | 'asiacell' - | 'windit' - | 'cellc' - | 'ooredoo' - | 'drei' - | 'umobile' - | 'cableone' - | 'proximus' - | 'tele2' - | 'mobitel' - | 'o2' - | 'bouygues' - | 'free' - | 'sfr' - | 'digicel'; - - /** - * City name (no spaces, e.g. `sanfrancisco`). If provided, `country` must also be - * provided. + * Provider city alias. Mobile carrier routing can make observed geo vary. */ city?: string; @@ -482,14 +339,9 @@ export namespace ProxyRetrieveResponse { country?: string; /** - * Two-letter state code. + * US-only state code. Mobile carrier routing can make observed geo vary. */ state?: string; - - /** - * US ZIP code. - */ - zip?: string; } /** @@ -636,76 +488,7 @@ export namespace ProxyListResponse { */ export interface MobileProxyConfig { /** - * Autonomous system number. See https://bgp.potaroo.net/cidr/autnums.html - */ - asn?: string; - - /** - * Mobile carrier. - */ - carrier?: - | 'a1' - | 'aircel' - | 'airtel' - | 'att' - | 'celcom' - | 'chinamobile' - | 'claro' - | 'comcast' - | 'cox' - | 'digi' - | 'dt' - | 'docomo' - | 'dtac' - | 'etisalat' - | 'idea' - | 'kyivstar' - | 'meo' - | 'megafon' - | 'mtn' - | 'mtnza' - | 'mts' - | 'optus' - | 'orange' - | 'qwest' - | 'reliance_jio' - | 'robi' - | 'sprint' - | 'telefonica' - | 'telstra' - | 'tmobile' - | 'tigo' - | 'tim' - | 'verizon' - | 'vimpelcom' - | 'vodacomza' - | 'vodafone' - | 'vivo' - | 'zain' - | 'vivabo' - | 'telenormyanmar' - | 'kcelljsc' - | 'swisscom' - | 'singtel' - | 'asiacell' - | 'windit' - | 'cellc' - | 'ooredoo' - | 'drei' - | 'umobile' - | 'cableone' - | 'proximus' - | 'tele2' - | 'mobitel' - | 'o2' - | 'bouygues' - | 'free' - | 'sfr' - | 'digicel'; - - /** - * City name (no spaces, e.g. `sanfrancisco`). If provided, `country` must also be - * provided. + * Provider city alias. Mobile carrier routing can make observed geo vary. */ city?: string; @@ -715,14 +498,9 @@ export namespace ProxyListResponse { country?: string; /** - * Two-letter state code. + * US-only state code. Mobile carrier routing can make observed geo vary. */ state?: string; - - /** - * US ZIP code. - */ - zip?: string; } /** @@ -867,76 +645,7 @@ export namespace ProxyCheckResponse { */ export interface MobileProxyConfig { /** - * Autonomous system number. See https://bgp.potaroo.net/cidr/autnums.html - */ - asn?: string; - - /** - * Mobile carrier. - */ - carrier?: - | 'a1' - | 'aircel' - | 'airtel' - | 'att' - | 'celcom' - | 'chinamobile' - | 'claro' - | 'comcast' - | 'cox' - | 'digi' - | 'dt' - | 'docomo' - | 'dtac' - | 'etisalat' - | 'idea' - | 'kyivstar' - | 'meo' - | 'megafon' - | 'mtn' - | 'mtnza' - | 'mts' - | 'optus' - | 'orange' - | 'qwest' - | 'reliance_jio' - | 'robi' - | 'sprint' - | 'telefonica' - | 'telstra' - | 'tmobile' - | 'tigo' - | 'tim' - | 'verizon' - | 'vimpelcom' - | 'vodacomza' - | 'vodafone' - | 'vivo' - | 'zain' - | 'vivabo' - | 'telenormyanmar' - | 'kcelljsc' - | 'swisscom' - | 'singtel' - | 'asiacell' - | 'windit' - | 'cellc' - | 'ooredoo' - | 'drei' - | 'umobile' - | 'cableone' - | 'proximus' - | 'tele2' - | 'mobitel' - | 'o2' - | 'bouygues' - | 'free' - | 'sfr' - | 'digicel'; - - /** - * City name (no spaces, e.g. `sanfrancisco`). If provided, `country` must also be - * provided. + * Provider city alias. Mobile carrier routing can make observed geo vary. */ city?: string; @@ -946,14 +655,9 @@ export namespace ProxyCheckResponse { country?: string; /** - * Two-letter state code. + * US-only state code. Mobile carrier routing can make observed geo vary. */ state?: string; - - /** - * US ZIP code. - */ - zip?: string; } /** @@ -1077,76 +781,7 @@ export namespace ProxyCreateParams { */ export interface MobileProxyConfig { /** - * Autonomous system number. See https://bgp.potaroo.net/cidr/autnums.html - */ - asn?: string; - - /** - * Mobile carrier. - */ - carrier?: - | 'a1' - | 'aircel' - | 'airtel' - | 'att' - | 'celcom' - | 'chinamobile' - | 'claro' - | 'comcast' - | 'cox' - | 'digi' - | 'dt' - | 'docomo' - | 'dtac' - | 'etisalat' - | 'idea' - | 'kyivstar' - | 'meo' - | 'megafon' - | 'mtn' - | 'mtnza' - | 'mts' - | 'optus' - | 'orange' - | 'qwest' - | 'reliance_jio' - | 'robi' - | 'sprint' - | 'telefonica' - | 'telstra' - | 'tmobile' - | 'tigo' - | 'tim' - | 'verizon' - | 'vimpelcom' - | 'vodacomza' - | 'vodafone' - | 'vivo' - | 'zain' - | 'vivabo' - | 'telenormyanmar' - | 'kcelljsc' - | 'swisscom' - | 'singtel' - | 'asiacell' - | 'windit' - | 'cellc' - | 'ooredoo' - | 'drei' - | 'umobile' - | 'cableone' - | 'proximus' - | 'tele2' - | 'mobitel' - | 'o2' - | 'bouygues' - | 'free' - | 'sfr' - | 'digicel'; - - /** - * City name (no spaces, e.g. `sanfrancisco`). If provided, `country` must also be - * provided. + * Provider city alias. Mobile carrier routing can make observed geo vary. */ city?: string; @@ -1156,14 +791,9 @@ export namespace ProxyCreateParams { country?: string; /** - * Two-letter state code. + * US-only state code. Mobile carrier routing can make observed geo vary. */ state?: string; - - /** - * US ZIP code. - */ - zip?: string; } /** From d6ed33eabf652722e8a93915f749d97dfaf25a77 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 29 May 2026 16:18:58 +0000 Subject: [PATCH 406/551] codegen metadata --- .stats.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.stats.yml b/.stats.yml index 834590a5..190a6ab6 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 117 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-a32ac633a8f67f3844b6ccb7b97687aec2cf2e2c611df4157c223dfac16db806.yml -openapi_spec_hash: f8c9aabe60372f28ad9cceed42009274 -config_hash: 0f222358f24700d1811c5d27078a3849 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-04da2c2ed5f83c54f59f6c148abcf013cc37282fde2b3b5b263dffab927d5ba2.yml +openapi_spec_hash: 9b05d6877797e55051a83222fa7652d0 +config_hash: e0741f8035aea13f71e54e0fdb88eaa4 From ea1887901da22d67fce438522b53e5211ba8249a Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 29 May 2026 17:40:27 +0000 Subject: [PATCH 407/551] feat: api: surface category field on browser telemetry events --- .stats.yml | 4 +-- src/resources/browsers/telemetry.ts | 44 +++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 190a6ab6..f41061ca 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 117 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-04da2c2ed5f83c54f59f6c148abcf013cc37282fde2b3b5b263dffab927d5ba2.yml -openapi_spec_hash: 9b05d6877797e55051a83222fa7652d0 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-4bada2a5bdbde93018e5a1b1e80e134acbc5509cfdea94db6e4c5b799eba7b82.yml +openapi_spec_hash: e0d541d480f5663b1e6bd3bb19a0fe61 config_hash: e0741f8035aea13f71e54e0fdb88eaa4 diff --git a/src/resources/browsers/telemetry.ts b/src/resources/browsers/telemetry.ts index f9ff2d42..7706a190 100644 --- a/src/resources/browsers/telemetry.ts +++ b/src/resources/browsers/telemetry.ts @@ -108,6 +108,8 @@ export namespace BrowserCallStack { * source_url, and stack_trace. Fields not applicable to the source are absent. */ export interface BrowserConsoleErrorEvent { + category: 'console'; + /** * Provenance metadata identifying which producer emitted the event. */ @@ -188,6 +190,8 @@ export namespace BrowserConsoleErrorEvent { * A browser console log event (console.log, console.info, console.warn, etc.). */ export interface BrowserConsoleLogEvent { + category: 'console'; + /** * Provenance metadata identifying which producer emitted the event. */ @@ -323,6 +327,8 @@ export type BrowserHTTPHeaders = { [key: string]: unknown }; * A browser user click event captured via injected page script. */ export interface BrowserInteractionClickEvent { + category: 'interaction'; + /** * Provenance metadata identifying which producer emitted the event. */ @@ -386,6 +392,8 @@ export namespace BrowserInteractionClickEvent { * A browser keyboard event captured via injected page script. */ export interface BrowserInteractionKeyEvent { + category: 'interaction'; + /** * Provenance metadata identifying which producer emitted the event. */ @@ -440,6 +448,8 @@ export namespace BrowserInteractionKeyEvent { * captured via injected page script. */ export interface BrowserInteractionScrollSettledEvent { + category: 'interaction'; + /** * Provenance metadata identifying which producer emitted the event. */ @@ -505,6 +515,8 @@ export namespace BrowserInteractionScrollSettledEvent { * page_layout_settled) as unreliable until then. */ export interface BrowserMonitorDisconnectedEvent { + category: 'system'; + /** * Provenance metadata identifying which producer emitted the event. */ @@ -538,6 +550,8 @@ export namespace BrowserMonitorDisconnectedEvent { * The CDP session could not be initialized. */ export interface BrowserMonitorInitFailedEvent { + category: 'system'; + /** * Provenance metadata identifying which producer emitted the event. */ @@ -572,6 +586,8 @@ export namespace BrowserMonitorInitFailedEvent { * reconnection attempts. No further telemetry events will arrive on this session. */ export interface BrowserMonitorReconnectFailedEvent { + category: 'system'; + /** * Provenance metadata identifying which producer emitted the event. */ @@ -608,6 +624,8 @@ export namespace BrowserMonitorReconnectFailedEvent { * so navigation and network tracking restart fresh from this point. */ export interface BrowserMonitorReconnectedEvent { + category: 'system'; + /** * Provenance metadata identifying which producer emitted the event. */ @@ -641,6 +659,8 @@ export namespace BrowserMonitorReconnectedEvent { * A periodic screenshot of the browser viewport. */ export interface BrowserMonitorScreenshotEvent { + category: 'system'; + /** * Provenance metadata identifying which producer emitted the event. */ @@ -675,6 +695,8 @@ export namespace BrowserMonitorScreenshotEvent { * in-flight HTTP requests. */ export interface BrowserNetworkIdleEvent { + category: 'network'; + /** * Provenance metadata identifying which producer emitted the event. */ @@ -707,6 +729,8 @@ export interface BrowserNetworkIdleEvent { * populated in that case. */ export interface BrowserNetworkLoadingFailedEvent { + category: 'network'; + /** * Provenance metadata identifying which producer emitted the event. */ @@ -767,6 +791,8 @@ export namespace BrowserNetworkLoadingFailedEvent { * A browser network request sent event. */ export interface BrowserNetworkRequestEvent { + category: 'network'; + /** * Provenance metadata identifying which producer emitted the event. */ @@ -854,6 +880,8 @@ export namespace BrowserNetworkRequestEvent { * fully received, not when headers arrive. */ export interface BrowserNetworkResponseEvent { + category: 'network'; + /** * Provenance metadata identifying which producer emitted the event. */ @@ -934,6 +962,8 @@ export namespace BrowserNetworkResponseEvent { * A browser DOMContentLoaded event (CDP Page.domContentEventFired). */ export interface BrowserPageDomContentLoadedEvent { + category: 'page'; + /** * Provenance metadata identifying which producer emitted the event. */ @@ -980,6 +1010,8 @@ export namespace BrowserPageDomContentLoadedEvent { * the 1-second timer. */ export interface BrowserPageLayoutSettledEvent { + category: 'page'; + /** * Provenance metadata identifying which producer emitted the event. */ @@ -1009,6 +1041,8 @@ export interface BrowserPageLayoutSettledEvent { * A browser cumulative layout shift (CLS) event from the Performance Timeline API. */ export interface BrowserPageLayoutShiftEvent { + category: 'page'; + /** * Provenance metadata identifying which producer emitted the event. */ @@ -1087,6 +1121,8 @@ export namespace BrowserPageLayoutShiftEvent { * API. */ export interface BrowserPageLcpEvent { + category: 'page'; + /** * Provenance metadata identifying which producer emitted the event. */ @@ -1178,6 +1214,8 @@ export namespace BrowserPageLcpEvent { * A browser page load event (CDP Page.loadEventFired). */ export interface BrowserPageLoadEvent { + category: 'page'; + /** * Provenance metadata identifying which producer emitted the event. */ @@ -1224,6 +1262,8 @@ export namespace BrowserPageLoadEvent { * epoch. */ export interface BrowserPageNavigationEvent { + category: 'page'; + /** * Provenance metadata identifying which producer emitted the event. */ @@ -1290,6 +1330,8 @@ export namespace BrowserPageNavigationEvent { * Independent of network_idle; a single pending request does not block it. */ export interface BrowserPageNavigationSettledEvent { + category: 'page'; + /** * Provenance metadata identifying which producer emitted the event. */ @@ -1323,6 +1365,8 @@ export interface BrowserPageNavigationSettledEvent { * treat it as a special case. */ export interface BrowserPageTabOpenedEvent { + category: 'page'; + /** * Provenance metadata identifying which producer emitted the event. */ From 8b1aa80db18dc9cb5a6425c04c4b6f8a6daefc44 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 1 Jun 2026 14:20:33 +0000 Subject: [PATCH 408/551] fix(api): move batch + get_mouse_position into Browser Computer Controls tag --- .stats.yml | 4 ++-- src/resources/browsers/computer.ts | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index f41061ca..8ba534ce 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 117 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-4bada2a5bdbde93018e5a1b1e80e134acbc5509cfdea94db6e4c5b799eba7b82.yml -openapi_spec_hash: e0d541d480f5663b1e6bd3bb19a0fe61 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-7548abe9fea7553e12a128b31f7dc7fc33f2558a9f20d2eb33464db5f61ab3ea.yml +openapi_spec_hash: 4b701cc4b33a2c944a5a9b63e9f364a2 config_hash: e0741f8035aea13f71e54e0fdb88eaa4 diff --git a/src/resources/browsers/computer.ts b/src/resources/browsers/computer.ts index d67dac60..a8b8d443 100644 --- a/src/resources/browsers/computer.ts +++ b/src/resources/browsers/computer.ts @@ -6,6 +6,9 @@ import { buildHeaders } from '../../internal/headers'; import { RequestOptions } from '../../internal/request-options'; import { path } from '../../internal/utils/path'; +/** + * Control mouse, keyboard, and screen on the browser instance. + */ export class Computer extends APIResource { /** * Send an array of computer actions to execute in order on the browser instance. From 8501d24c052b23f647e3f3465c135da80b2397fc Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 1 Jun 2026 15:53:44 +0000 Subject: [PATCH 409/551] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 8ba534ce..e31b9566 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 117 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-7548abe9fea7553e12a128b31f7dc7fc33f2558a9f20d2eb33464db5f61ab3ea.yml -openapi_spec_hash: 4b701cc4b33a2c944a5a9b63e9f364a2 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-501a71a04e6a68427e378df10c7327025e3cb177f4550459b5a6eb752a177a25.yml +openapi_spec_hash: d38661081dd50fded2208424bb19157b config_hash: e0741f8035aea13f71e54e0fdb88eaa4 From 588fb62770b36199c7fb2eb5e6b3389d17b35f17 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 2 Jun 2026 15:22:08 +0000 Subject: [PATCH 410/551] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index e31b9566..8fee23fa 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 117 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-501a71a04e6a68427e378df10c7327025e3cb177f4550459b5a6eb752a177a25.yml -openapi_spec_hash: d38661081dd50fded2208424bb19157b +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-7988523e72ff96a93d2913e63ba27c5bb94af9893b94fceeeda64e0b43fb0663.yml +openapi_spec_hash: ce2ae9f9137d4c2bf947d446d00ebec8 config_hash: e0741f8035aea13f71e54e0fdb88eaa4 From 7f147f9fae05b22cdd7956cd3c35ada089f2e0f2 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 2 Jun 2026 21:01:42 +0000 Subject: [PATCH 411/551] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 8fee23fa..0dd6d527 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 117 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-7988523e72ff96a93d2913e63ba27c5bb94af9893b94fceeeda64e0b43fb0663.yml -openapi_spec_hash: ce2ae9f9137d4c2bf947d446d00ebec8 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-c8f49d6ea6355b703fa0e6cce4277df8954b9730ce4cdd3af5900f37769b40d9.yml +openapi_spec_hash: ca03a797fb8e4cc79b6be4513f2fc6e7 config_hash: e0741f8035aea13f71e54e0fdb88eaa4 From 77ec3ec60f70ee6e400e9d9b82a58148439d675a Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 3 Jun 2026 13:40:10 +0000 Subject: [PATCH 412/551] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 0dd6d527..a84f620b 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 117 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-c8f49d6ea6355b703fa0e6cce4277df8954b9730ce4cdd3af5900f37769b40d9.yml -openapi_spec_hash: ca03a797fb8e4cc79b6be4513f2fc6e7 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-a42305a37f0b2f42afb552acc9a5294c210a5278eb6067df803abe36da45c5b9.yml +openapi_spec_hash: 4140db7dd999fee4b02e76dfb7d003b5 config_hash: e0741f8035aea13f71e54e0fdb88eaa4 From 748ac069fee48b945a563b1d1be8dd620f488774 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 3 Jun 2026 15:29:22 +0000 Subject: [PATCH 413/551] feat(api): move browser telemetry SSE stream to /browsers/{id}/telemetry/stream --- .stats.yml | 6 +++--- api.md | 2 +- src/resources/browsers/telemetry.ts | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.stats.yml b/.stats.yml index a84f620b..5a5e5632 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 117 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-a42305a37f0b2f42afb552acc9a5294c210a5278eb6067df803abe36da45c5b9.yml -openapi_spec_hash: 4140db7dd999fee4b02e76dfb7d003b5 -config_hash: e0741f8035aea13f71e54e0fdb88eaa4 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-1acd8f0b76ab00e36b53cc3ca90b72b2199f3388b3e307890adb464b87f9a2d8.yml +openapi_spec_hash: 82003125c1c2c5d82d19270bafb4a6ca +config_hash: ede72e4ae65cc5a6d6927938b3455c46 diff --git a/api.md b/api.md index 4ac5b01d..86adf707 100644 --- a/api.md +++ b/api.md @@ -123,7 +123,7 @@ Types: Methods: -- client.browsers.telemetry.stream(id, { ...params }) -> TelemetryStreamResponse +- client.browsers.telemetry.stream(id, { ...params }) -> TelemetryStreamResponse ## Replays diff --git a/src/resources/browsers/telemetry.ts b/src/resources/browsers/telemetry.ts index 7706a190..74e83d07 100644 --- a/src/resources/browsers/telemetry.ts +++ b/src/resources/browsers/telemetry.ts @@ -35,7 +35,7 @@ export class Telemetry extends APIResource { options?: RequestOptions, ): APIPromise> { const { 'Last-Event-ID': lastEventID } = params ?? {}; - return this._client.get(path`/browsers/${id}/telemetry`, { + return this._client.get(path`/browsers/${id}/telemetry/stream`, { ...options, headers: buildHeaders([ { From be95e6c881e8137747645a156d0e74d03810556d Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 3 Jun 2026 15:35:41 +0000 Subject: [PATCH 414/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 115a387a..bfeb4872 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.58.0" + ".": "0.59.0" } diff --git a/package.json b/package.json index 0758b8f2..99d4f39a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.58.0", + "version": "0.59.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index d5defc55..7fd65e71 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.58.0'; // x-release-please-version +export const VERSION = '0.59.0'; // x-release-please-version From 78f5f54eba49c400412489d1a26211dd40afd531 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 3 Jun 2026 17:45:30 +0000 Subject: [PATCH 415/551] feat: Fix browser pool update schema --- .stats.yml | 4 +-- src/resources/browser-pools.ts | 15 +++++------ tests/api-resources/browser-pools.test.ts | 32 ++--------------------- 3 files changed, 11 insertions(+), 40 deletions(-) diff --git a/.stats.yml b/.stats.yml index 5a5e5632..57627cd0 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 117 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-1acd8f0b76ab00e36b53cc3ca90b72b2199f3388b3e307890adb464b87f9a2d8.yml -openapi_spec_hash: 82003125c1c2c5d82d19270bafb4a6ca +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-2d1337eec44e036b9c896b7db4691f0a12edfa79d3f28b611818bcedf62d44ee.yml +openapi_spec_hash: 30110dbbe733b16e40a6d0aa41d0c8c4 config_hash: ede72e4ae65cc5a6d6927938b3455c46 diff --git a/src/resources/browser-pools.ts b/src/resources/browser-pools.ts index dc1af440..c6e78492 100644 --- a/src/resources/browser-pools.ts +++ b/src/resources/browser-pools.ts @@ -48,7 +48,6 @@ export class BrowserPools extends APIResource { * ```ts * const browserPool = await client.browserPools.update( * 'id_or_name', - * { size: 10 }, * ); * ``` */ @@ -494,13 +493,6 @@ export interface BrowserPoolCreateParams { } export interface BrowserPoolUpdateParams { - /** - * Number of browsers to maintain in the pool. The maximum size is determined by - * your organization's pooled sessions limit (the sum of all pool sizes cannot - * exceed your limit). - */ - size: number; - /** * Custom Chrome enterprise policy overrides applied to all browsers in this pool. * Keys are Chrome enterprise policy names; values must match their expected types. @@ -554,6 +546,13 @@ export interface BrowserPoolUpdateParams { */ proxy_id?: string; + /** + * Number of browsers to maintain in the pool. The maximum size is determined by + * your organization's pooled sessions limit (the sum of all pool sizes cannot + * exceed your limit). + */ + size?: number; + /** * Optional URL to navigate to when a new browser is warmed into the pool. * Best-effort: failures to navigate do not fail pool fill. Only applied to diff --git a/tests/api-resources/browser-pools.test.ts b/tests/api-resources/browser-pools.test.ts index 7a473ba2..dff2eeda 100644 --- a/tests/api-resources/browser-pools.test.ts +++ b/tests/api-resources/browser-pools.test.ts @@ -60,8 +60,8 @@ describe('resource browserPools', () => { }); // Mock server tests are disabled - test.skip('update: only required params', async () => { - const responsePromise = client.browserPools.update('id_or_name', { size: 10 }); + test.skip('update', async () => { + const responsePromise = client.browserPools.update('id_or_name', {}); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -71,34 +71,6 @@ describe('resource browserPools', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Mock server tests are disabled - test.skip('update: required and optional params', async () => { - const response = await client.browserPools.update('id_or_name', { - size: 10, - chrome_policy: { foo: 'bar' }, - discard_all_idle: false, - extensions: [{ id: 'id', name: 'name' }], - fill_rate_per_minute: 0, - headless: false, - kiosk_mode: true, - name: 'my-pool', - profile: { - id: 'id', - name: 'name', - save_changes: true, - }, - proxy_id: 'proxy_id', - start_url: 'https://example.com', - stealth: true, - timeout_seconds: 60, - viewport: { - height: 800, - width: 1280, - refresh_rate: 60, - }, - }); - }); - // Mock server tests are disabled test.skip('list', async () => { const responsePromise = client.browserPools.list(); From d16a6f33a63645a249f7518e47afed6c9af14d68 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 3 Jun 2026 19:40:36 +0000 Subject: [PATCH 416/551] feat: Add API-backed API key management endpoints --- .stats.yml | 4 ++-- src/resources/api-keys.ts | 18 +++++++++++++++++- tests/api-resources/api-keys.test.ts | 11 ++++++++++- 3 files changed, 29 insertions(+), 4 deletions(-) diff --git a/.stats.yml b/.stats.yml index 57627cd0..9f173dc5 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 117 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-2d1337eec44e036b9c896b7db4691f0a12edfa79d3f28b611818bcedf62d44ee.yml -openapi_spec_hash: 30110dbbe733b16e40a6d0aa41d0c8c4 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-3a1db7f11a92b28681929255ada59d2317ee4db98b5ff5aa6ce142a0664058b3.yml +openapi_spec_hash: b3064eaa589ae2a84993686ad1a3ee43 config_hash: ede72e4ae65cc5a6d6927938b3455c46 diff --git a/src/resources/api-keys.ts b/src/resources/api-keys.ts index cad02c32..a855c962 100644 --- a/src/resources/api-keys.ts +++ b/src/resources/api-keys.ts @@ -181,7 +181,23 @@ export interface APIKeyUpdateParams { name: string; } -export interface APIKeyListParams extends OffsetPaginationParams {} +export interface APIKeyListParams extends OffsetPaginationParams { + /** + * Case-insensitive substring match against API key name, creator, and project. API + * key identifiers and masked keys match by exact value or prefix. + */ + query?: string; + + /** + * Field to sort API keys by. + */ + sort_by?: 'created_at' | 'name' | 'expires_at'; + + /** + * Sort direction for API keys. + */ + sort_direction?: 'asc' | 'desc'; +} export declare namespace APIKeys { export { diff --git a/tests/api-resources/api-keys.test.ts b/tests/api-resources/api-keys.test.ts index c39c2228..14a45a0d 100644 --- a/tests/api-resources/api-keys.test.ts +++ b/tests/api-resources/api-keys.test.ts @@ -74,7 +74,16 @@ describe('resource apiKeys', () => { test.skip('list: 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.apiKeys.list({ limit: 100, offset: 0 }, { path: '/_stainless_unknown_path' }), + client.apiKeys.list( + { + limit: 100, + offset: 0, + query: 'query', + sort_by: 'created_at', + sort_direction: 'asc', + }, + { path: '/_stainless_unknown_path' }, + ), ).rejects.toThrow(Kernel.NotFoundError); }); From ec14bae4f1988eebbe9f80f8c0550110314ba7ce Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 3 Jun 2026 19:56:02 +0000 Subject: [PATCH 417/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index bfeb4872..85b1765b 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.59.0" + ".": "0.60.0" } diff --git a/package.json b/package.json index 99d4f39a..89fa4923 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.59.0", + "version": "0.60.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 7fd65e71..3c00a63b 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.59.0'; // x-release-please-version +export const VERSION = '0.60.0'; // x-release-please-version From b0b471c74f87abd523539ffd5ac625c42ed3ca87 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 3 Jun 2026 20:39:37 +0000 Subject: [PATCH 418/551] feat: Add record_audio option to browser replay recording API --- .stats.yml | 4 ++-- src/resources/browsers/replays.ts | 6 ++++++ tests/api-resources/browsers/replays.test.ts | 6 +++++- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/.stats.yml b/.stats.yml index 9f173dc5..27228661 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 117 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-3a1db7f11a92b28681929255ada59d2317ee4db98b5ff5aa6ce142a0664058b3.yml -openapi_spec_hash: b3064eaa589ae2a84993686ad1a3ee43 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-33e46e6a0095c2ec39a51860ee4e133c5a21a80a90cbe9e52953c07e5e0295de.yml +openapi_spec_hash: 4aa466b9af39768b65a44b68ae0d1f6e config_hash: ede72e4ae65cc5a6d6927938b3455c46 diff --git a/src/resources/browsers/replays.ts b/src/resources/browsers/replays.ts index 6b944fac..1954856f 100644 --- a/src/resources/browsers/replays.ts +++ b/src/resources/browsers/replays.ts @@ -152,6 +152,12 @@ export interface ReplayStartParams { * Maximum recording duration in seconds. */ max_duration_in_seconds?: number; + + /** + * Record audio in addition to video. When false (the default), the recording is + * video-only. + */ + record_audio?: boolean; } export interface ReplayStopParams { diff --git a/tests/api-resources/browsers/replays.test.ts b/tests/api-resources/browsers/replays.test.ts index bd985e5a..672a7789 100644 --- a/tests/api-resources/browsers/replays.test.ts +++ b/tests/api-resources/browsers/replays.test.ts @@ -43,7 +43,11 @@ describe('resource replays', () => { await expect( client.browsers.replays.start( 'id', - { framerate: 1, max_duration_in_seconds: 1 }, + { + framerate: 1, + max_duration_in_seconds: 1, + record_audio: true, + }, { path: '/_stainless_unknown_path' }, ), ).rejects.toThrow(Kernel.NotFoundError); From 4f2987a4432cd88bf2c5817829e8ebaf060deac4 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 3 Jun 2026 20:42:07 +0000 Subject: [PATCH 419/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 85b1765b..c11d4bc2 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.60.0" + ".": "0.61.0" } diff --git a/package.json b/package.json index 89fa4923..1b427341 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.60.0", + "version": "0.61.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 3c00a63b..232058f3 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.60.0'; // x-release-please-version +export const VERSION = '0.61.0'; // x-release-please-version From f1db6d050a62b109bfbf131dc8851418562b36b3 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 3 Jun 2026 21:04:46 +0000 Subject: [PATCH 420/551] feat: api: paginate GET /proxies --- .stats.yml | 6 +- api.md | 2 +- src/client.ts | 4 + src/resources/index.ts | 2 + src/resources/proxies.ts | 234 ++++++++++++++-------------- tests/api-resources/proxies.test.ts | 8 + 6 files changed, 138 insertions(+), 118 deletions(-) diff --git a/.stats.yml b/.stats.yml index 27228661..032ac8ce 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 117 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-33e46e6a0095c2ec39a51860ee4e133c5a21a80a90cbe9e52953c07e5e0295de.yml -openapi_spec_hash: 4aa466b9af39768b65a44b68ae0d1f6e -config_hash: ede72e4ae65cc5a6d6927938b3455c46 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-f3e52a8a9d9e37f8b527bdcce63b39cf8807d138cf3570c9954ba7f42ef02375.yml +openapi_spec_hash: 2b787691eba1bb7bafb553528c09d5c0 +config_hash: e12afec516ced9520590c7a05af7a6f7 diff --git a/api.md b/api.md index 86adf707..adf1afd6 100644 --- a/api.md +++ b/api.md @@ -283,7 +283,7 @@ Methods: - client.proxies.create({ ...params }) -> ProxyCreateResponse - client.proxies.retrieve(id) -> ProxyRetrieveResponse -- client.proxies.list() -> ProxyListResponse +- client.proxies.list({ ...params }) -> ProxyListResponsesOffsetPagination - client.proxies.delete(id) -> void - client.proxies.check(id, { ...params }) -> ProxyCheckResponse diff --git a/src/client.ts b/src/client.ts index 30b48de1..726da979 100644 --- a/src/client.ts +++ b/src/client.ts @@ -104,7 +104,9 @@ import { ProxyCheckResponse, ProxyCreateParams, ProxyCreateResponse, + ProxyListParams, ProxyListResponse, + ProxyListResponsesOffsetPagination, ProxyRetrieveResponse, } from './resources/proxies'; import { Auth } from './resources/auth/auth'; @@ -1039,7 +1041,9 @@ export declare namespace Kernel { type ProxyRetrieveResponse as ProxyRetrieveResponse, type ProxyListResponse as ProxyListResponse, type ProxyCheckResponse as ProxyCheckResponse, + type ProxyListResponsesOffsetPagination as ProxyListResponsesOffsetPagination, type ProxyCreateParams as ProxyCreateParams, + type ProxyListParams as ProxyListParams, type ProxyCheckParams as ProxyCheckParams, }; diff --git a/src/resources/index.ts b/src/resources/index.ts index 985b7d04..473bc6f1 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -122,5 +122,7 @@ export { type ProxyListResponse, type ProxyCheckResponse, type ProxyCreateParams, + type ProxyListParams, type ProxyCheckParams, + type ProxyListResponsesOffsetPagination, } from './proxies'; diff --git a/src/resources/proxies.ts b/src/resources/proxies.ts index be5a4253..833ae00a 100644 --- a/src/resources/proxies.ts +++ b/src/resources/proxies.ts @@ -2,6 +2,7 @@ import { APIResource } from '../core/resource'; import { APIPromise } from '../core/api-promise'; +import { OffsetPagination, type OffsetPaginationParams, PagePromise } from '../core/pagination'; import { buildHeaders } from '../internal/headers'; import { RequestOptions } from '../internal/request-options'; import { path } from '../internal/utils/path'; @@ -27,8 +28,11 @@ export class Proxies extends APIResource { /** * List proxies owned by the caller's organization. */ - list(options?: RequestOptions): APIPromise { - return this._client.get('/proxies', options); + list( + query: ProxyListParams | null | undefined = {}, + options?: RequestOptions, + ): PagePromise { + return this._client.getAPIList('/proxies', OffsetPagination, { query, ...options }); } /** @@ -58,6 +62,8 @@ export class Proxies extends APIResource { } } +export type ProxyListResponsesOffsetPagination = OffsetPagination; + /** * Configuration for routing traffic through a proxy. */ @@ -370,163 +376,159 @@ export namespace ProxyRetrieveResponse { } } -export type ProxyListResponse = Array; +/** + * Configuration for routing traffic through a proxy. + */ +export interface ProxyListResponse { + /** + * Proxy type to use. In terms of quality for avoiding bot-detection, from best to + * worst: `mobile` > `residential` > `isp` > `datacenter`. + */ + type: 'datacenter' | 'isp' | 'residential' | 'mobile' | 'custom'; + + id?: string; + + /** + * Hostnames that should bypass the parent proxy and connect directly. + */ + bypass_hosts?: Array; + + /** + * Configuration specific to the selected proxy `type`. + */ + config?: + | ProxyListResponse.DatacenterProxyConfig + | ProxyListResponse.IspProxyConfig + | ProxyListResponse.ResidentialProxyConfig + | ProxyListResponse.MobileProxyConfig + | ProxyListResponse.CustomProxyConfig; + + /** + * IP address that the proxy uses when making requests. + */ + ip_address?: string; + + /** + * Timestamp of the last health check performed on this proxy. + */ + last_checked?: string; + + /** + * Readable name of the proxy. + */ + name?: string; + + /** + * Protocol to use for the proxy connection. + */ + protocol?: 'http' | 'https'; + + /** + * Current health status of the proxy. + */ + status?: 'available' | 'unavailable'; +} export namespace ProxyListResponse { /** - * Configuration for routing traffic through a proxy. + * Configuration for a datacenter proxy. */ - export interface ProxyListResponseItem { + export interface DatacenterProxyConfig { /** - * Proxy type to use. In terms of quality for avoiding bot-detection, from best to - * worst: `mobile` > `residential` > `isp` > `datacenter`. + * ISO 3166 country code. Defaults to US if not provided. */ - type: 'datacenter' | 'isp' | 'residential' | 'mobile' | 'custom'; - - id?: string; + country?: string; + } + /** + * Configuration for an ISP proxy. + */ + export interface IspProxyConfig { /** - * Hostnames that should bypass the parent proxy and connect directly. + * ISO 3166 country code. Defaults to US if not provided. */ - bypass_hosts?: Array; + country?: string; + } + /** + * Configuration for residential proxies. + */ + export interface ResidentialProxyConfig { /** - * Configuration specific to the selected proxy `type`. + * Autonomous system number. See https://bgp.potaroo.net/cidr/autnums.html */ - config?: - | ProxyListResponseItem.DatacenterProxyConfig - | ProxyListResponseItem.IspProxyConfig - | ProxyListResponseItem.ResidentialProxyConfig - | ProxyListResponseItem.MobileProxyConfig - | ProxyListResponseItem.CustomProxyConfig; + asn?: string; /** - * IP address that the proxy uses when making requests. + * City name (no spaces, e.g. `sanfrancisco`). If provided, `country` must also be + * provided. */ - ip_address?: string; + city?: string; /** - * Timestamp of the last health check performed on this proxy. + * ISO 3166 country code. */ - last_checked?: string; + country?: string; /** - * Readable name of the proxy. + * @deprecated Operating system of the residential device. */ - name?: string; + os?: 'windows' | 'macos' | 'android'; /** - * Protocol to use for the proxy connection. + * Two-letter state code. */ - protocol?: 'http' | 'https'; + state?: string; /** - * Current health status of the proxy. + * US ZIP code. */ - status?: 'available' | 'unavailable'; + zip?: string; } - export namespace ProxyListResponseItem { + /** + * Configuration for mobile proxies. + */ + export interface MobileProxyConfig { /** - * Configuration for a datacenter proxy. + * Provider city alias. Mobile carrier routing can make observed geo vary. */ - export interface DatacenterProxyConfig { - /** - * ISO 3166 country code. Defaults to US if not provided. - */ - country?: string; - } + city?: string; /** - * Configuration for an ISP proxy. + * ISO 3166 country code */ - export interface IspProxyConfig { - /** - * ISO 3166 country code. Defaults to US if not provided. - */ - country?: string; - } + country?: string; /** - * Configuration for residential proxies. + * US-only state code. Mobile carrier routing can make observed geo vary. */ - export interface ResidentialProxyConfig { - /** - * Autonomous system number. See https://bgp.potaroo.net/cidr/autnums.html - */ - asn?: string; - - /** - * City name (no spaces, e.g. `sanfrancisco`). If provided, `country` must also be - * provided. - */ - city?: string; - - /** - * ISO 3166 country code. - */ - country?: string; - - /** - * @deprecated Operating system of the residential device. - */ - os?: 'windows' | 'macos' | 'android'; - - /** - * Two-letter state code. - */ - state?: string; - - /** - * US ZIP code. - */ - zip?: string; - } + state?: string; + } + /** + * Configuration for a custom proxy (e.g., private proxy server). + */ + export interface CustomProxyConfig { /** - * Configuration for mobile proxies. + * Proxy host address or IP. */ - export interface MobileProxyConfig { - /** - * Provider city alias. Mobile carrier routing can make observed geo vary. - */ - city?: string; - - /** - * ISO 3166 country code - */ - country?: string; - - /** - * US-only state code. Mobile carrier routing can make observed geo vary. - */ - state?: string; - } + host: string; /** - * Configuration for a custom proxy (e.g., private proxy server). + * Proxy port. */ - export interface CustomProxyConfig { - /** - * Proxy host address or IP. - */ - host: string; - - /** - * Proxy port. - */ - port: number; + port: number; - /** - * Whether the proxy has a password. - */ - has_password?: boolean; + /** + * Whether the proxy has a password. + */ + has_password?: boolean; - /** - * Username for proxy authentication. - */ - username?: string; - } + /** + * Username for proxy authentication. + */ + username?: string; } } @@ -822,6 +824,8 @@ export namespace ProxyCreateParams { } } +export interface ProxyListParams extends OffsetPaginationParams {} + export interface ProxyCheckParams { /** * An optional URL to test reachability against. If provided, the proxy check will @@ -846,7 +850,9 @@ export declare namespace Proxies { type ProxyRetrieveResponse as ProxyRetrieveResponse, type ProxyListResponse as ProxyListResponse, type ProxyCheckResponse as ProxyCheckResponse, + type ProxyListResponsesOffsetPagination as ProxyListResponsesOffsetPagination, type ProxyCreateParams as ProxyCreateParams, + type ProxyListParams as ProxyListParams, type ProxyCheckParams as ProxyCheckParams, }; } diff --git a/tests/api-resources/proxies.test.ts b/tests/api-resources/proxies.test.ts index 63142f87..f4e09d94 100644 --- a/tests/api-resources/proxies.test.ts +++ b/tests/api-resources/proxies.test.ts @@ -55,6 +55,14 @@ describe('resource proxies', () => { expect(dataAndResponse.response).toBe(rawResponse); }); + // Mock server tests are disabled + test.skip('list: 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.proxies.list({ limit: 1, offset: 0 }, { path: '/_stainless_unknown_path' }), + ).rejects.toThrow(Kernel.NotFoundError); + }); + // Mock server tests are disabled test.skip('delete', async () => { const responsePromise = client.proxies.delete('id'); From 01e6efdea46f78c74d84b4473e34dc821ac347b6 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 3 Jun 2026 21:54:06 +0000 Subject: [PATCH 421/551] feat: api: paginate GET /browser_pools --- .stats.yml | 6 +++--- api.md | 3 +-- src/client.ts | 6 ++++-- src/resources/browser-pools.ts | 22 ++++++++++++++++------ src/resources/index.ts | 3 ++- tests/api-resources/browser-pools.test.ts | 8 ++++++++ 6 files changed, 34 insertions(+), 14 deletions(-) diff --git a/.stats.yml b/.stats.yml index 032ac8ce..d6e38f27 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 117 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-f3e52a8a9d9e37f8b527bdcce63b39cf8807d138cf3570c9954ba7f42ef02375.yml -openapi_spec_hash: 2b787691eba1bb7bafb553528c09d5c0 -config_hash: e12afec516ced9520590c7a05af7a6f7 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-e5524e6eeeedc614c05bf19896f1ce6c4f8a113de85c02952d6874d579651f70.yml +openapi_spec_hash: 7815a189a50e6aa9e283213cc78d041c +config_hash: 453b25a35834fd59a55a2315d1d50746 diff --git a/api.md b/api.md index adf1afd6..7d0a8506 100644 --- a/api.md +++ b/api.md @@ -307,7 +307,6 @@ Methods: Types: - BrowserPool -- BrowserPoolListResponse - BrowserPoolAcquireResponse Methods: @@ -315,7 +314,7 @@ Methods: - client.browserPools.create({ ...params }) -> BrowserPool - client.browserPools.retrieve(idOrName) -> BrowserPool - client.browserPools.update(idOrName, { ...params }) -> BrowserPool -- client.browserPools.list() -> BrowserPoolListResponse +- client.browserPools.list({ ...params }) -> BrowserPoolsOffsetPagination - client.browserPools.delete(idOrName, { ...params }) -> void - client.browserPools.acquire(idOrName, { ...params }) -> BrowserPoolAcquireResponse - client.browserPools.flush(idOrName) -> void diff --git a/src/client.ts b/src/client.ts index 726da979..d0529908 100644 --- a/src/client.ts +++ b/src/client.ts @@ -35,10 +35,11 @@ import { BrowserPoolAcquireResponse, BrowserPoolCreateParams, BrowserPoolDeleteParams, - BrowserPoolListResponse, + BrowserPoolListParams, BrowserPoolReleaseParams, BrowserPoolUpdateParams, BrowserPools, + BrowserPoolsOffsetPagination, } from './resources/browser-pools'; import { CreateCredentialProviderRequest, @@ -1058,10 +1059,11 @@ export declare namespace Kernel { export { BrowserPools as BrowserPools, type BrowserPool as BrowserPool, - type BrowserPoolListResponse as BrowserPoolListResponse, type BrowserPoolAcquireResponse as BrowserPoolAcquireResponse, + type BrowserPoolsOffsetPagination as BrowserPoolsOffsetPagination, type BrowserPoolCreateParams as BrowserPoolCreateParams, type BrowserPoolUpdateParams as BrowserPoolUpdateParams, + type BrowserPoolListParams as BrowserPoolListParams, type BrowserPoolDeleteParams as BrowserPoolDeleteParams, type BrowserPoolAcquireParams as BrowserPoolAcquireParams, type BrowserPoolReleaseParams as BrowserPoolReleaseParams, diff --git a/src/resources/browser-pools.ts b/src/resources/browser-pools.ts index c6e78492..3744c41e 100644 --- a/src/resources/browser-pools.ts +++ b/src/resources/browser-pools.ts @@ -5,6 +5,7 @@ import * as Shared from './shared'; import * as BrowsersAPI from './browsers/browsers'; import * as TelemetryAPI from './browsers/telemetry'; import { APIPromise } from '../core/api-promise'; +import { OffsetPagination, type OffsetPaginationParams, PagePromise } from '../core/pagination'; import { buildHeaders } from '../internal/headers'; import { RequestOptions } from '../internal/request-options'; import { path } from '../internal/utils/path'; @@ -60,11 +61,17 @@ export class BrowserPools extends APIResource { * * @example * ```ts - * const browserPools = await client.browserPools.list(); + * // Automatically fetches more pages as needed. + * for await (const browserPool of client.browserPools.list()) { + * // ... + * } * ``` */ - list(options?: RequestOptions): APIPromise { - return this._client.get('/browser_pools', options); + list( + query: BrowserPoolListParams | null | undefined = {}, + options?: RequestOptions, + ): PagePromise { + return this._client.getAPIList('/browser_pools', OffsetPagination, { query, ...options }); } /** @@ -143,6 +150,8 @@ export class BrowserPools extends APIResource { } } +export type BrowserPoolsOffsetPagination = OffsetPagination; + /** * A browser pool containing multiple identically configured browsers. */ @@ -276,8 +285,6 @@ export namespace BrowserPool { } } -export type BrowserPoolListResponse = Array; - export interface BrowserPoolAcquireResponse { /** * Websocket URL for Chrome DevTools Protocol connections to the browser session @@ -591,6 +598,8 @@ export interface BrowserPoolUpdateParams { viewport?: Shared.BrowserViewport; } +export interface BrowserPoolListParams extends OffsetPaginationParams {} + export interface BrowserPoolDeleteParams { /** * If true, force delete even if browsers are currently leased. Leased browsers @@ -624,10 +633,11 @@ export interface BrowserPoolReleaseParams { export declare namespace BrowserPools { export { type BrowserPool as BrowserPool, - type BrowserPoolListResponse as BrowserPoolListResponse, type BrowserPoolAcquireResponse as BrowserPoolAcquireResponse, + type BrowserPoolsOffsetPagination as BrowserPoolsOffsetPagination, type BrowserPoolCreateParams as BrowserPoolCreateParams, type BrowserPoolUpdateParams as BrowserPoolUpdateParams, + type BrowserPoolListParams as BrowserPoolListParams, type BrowserPoolDeleteParams as BrowserPoolDeleteParams, type BrowserPoolAcquireParams as BrowserPoolAcquireParams, type BrowserPoolReleaseParams as BrowserPoolReleaseParams, diff --git a/src/resources/index.ts b/src/resources/index.ts index 473bc6f1..6e1bca38 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -20,13 +20,14 @@ export { Auth } from './auth/auth'; export { BrowserPools, type BrowserPool, - type BrowserPoolListResponse, type BrowserPoolAcquireResponse, type BrowserPoolCreateParams, type BrowserPoolUpdateParams, + type BrowserPoolListParams, type BrowserPoolDeleteParams, type BrowserPoolAcquireParams, type BrowserPoolReleaseParams, + type BrowserPoolsOffsetPagination, } from './browser-pools'; export { Browsers, diff --git a/tests/api-resources/browser-pools.test.ts b/tests/api-resources/browser-pools.test.ts index dff2eeda..a7c39c3e 100644 --- a/tests/api-resources/browser-pools.test.ts +++ b/tests/api-resources/browser-pools.test.ts @@ -83,6 +83,14 @@ describe('resource browserPools', () => { expect(dataAndResponse.response).toBe(rawResponse); }); + // Mock server tests are disabled + test.skip('list: 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.browserPools.list({ limit: 1, offset: 0 }, { path: '/_stainless_unknown_path' }), + ).rejects.toThrow(Kernel.NotFoundError); + }); + // Mock server tests are disabled test.skip('delete', async () => { const responsePromise = client.browserPools.delete('id_or_name'); From 21a0378808fff243d037c4be103df258eb68849d Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 4 Jun 2026 14:29:12 +0000 Subject: [PATCH 422/551] feat: api: paginate GET /extensions --- .stats.yml | 6 +-- api.md | 2 +- src/client.ts | 4 ++ src/resources/extensions.ts | 70 +++++++++++++++----------- src/resources/index.ts | 2 + tests/api-resources/extensions.test.ts | 8 +++ 6 files changed, 59 insertions(+), 33 deletions(-) diff --git a/.stats.yml b/.stats.yml index d6e38f27..582e6b44 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 117 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-e5524e6eeeedc614c05bf19896f1ce6c4f8a113de85c02952d6874d579651f70.yml -openapi_spec_hash: 7815a189a50e6aa9e283213cc78d041c -config_hash: 453b25a35834fd59a55a2315d1d50746 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-9a76e7a837ac9ffbe0e9557d618ce9b676e052249e364e516c28ddb33b912019.yml +openapi_spec_hash: c0e5412cc95139f11a8b8635559bb985 +config_hash: 098a7f3fd134c8e4cbd3a44750892a18 diff --git a/api.md b/api.md index 7d0a8506..7a4781e8 100644 --- a/api.md +++ b/api.md @@ -296,7 +296,7 @@ Types: Methods: -- client.extensions.list() -> ExtensionListResponse +- client.extensions.list({ ...params }) -> ExtensionListResponsesOffsetPagination - client.extensions.delete(idOrName) -> void - client.extensions.download(idOrName) -> Response - client.extensions.downloadFromChromeStore({ ...params }) -> Response diff --git a/src/client.ts b/src/client.ts index d0529908..c0ca1a34 100644 --- a/src/client.ts +++ b/src/client.ts @@ -78,7 +78,9 @@ import { } from './resources/deployments'; import { ExtensionDownloadFromChromeStoreParams, + ExtensionListParams, ExtensionListResponse, + ExtensionListResponsesOffsetPagination, ExtensionUploadParams, ExtensionUploadResponse, Extensions, @@ -1052,6 +1054,8 @@ export declare namespace Kernel { Extensions as Extensions, type ExtensionListResponse as ExtensionListResponse, type ExtensionUploadResponse as ExtensionUploadResponse, + type ExtensionListResponsesOffsetPagination as ExtensionListResponsesOffsetPagination, + type ExtensionListParams as ExtensionListParams, type ExtensionDownloadFromChromeStoreParams as ExtensionDownloadFromChromeStoreParams, type ExtensionUploadParams as ExtensionUploadParams, }; diff --git a/src/resources/extensions.ts b/src/resources/extensions.ts index c9e282d2..e12233ed 100644 --- a/src/resources/extensions.ts +++ b/src/resources/extensions.ts @@ -2,6 +2,7 @@ import { APIResource } from '../core/resource'; import { APIPromise } from '../core/api-promise'; +import { OffsetPagination, type OffsetPaginationParams, PagePromise } from '../core/pagination'; import { type Uploadable } from '../core/uploads'; import { buildHeaders } from '../internal/headers'; import { RequestOptions } from '../internal/request-options'; @@ -17,11 +18,20 @@ export class Extensions extends APIResource { * * @example * ```ts - * const extensions = await client.extensions.list(); + * // Automatically fetches more pages as needed. + * for await (const extensionListResponse of client.extensions.list()) { + * // ... + * } * ``` */ - list(options?: RequestOptions): APIPromise { - return this._client.get('/extensions', options); + list( + query: ExtensionListParams | null | undefined = {}, + options?: RequestOptions, + ): PagePromise { + return this._client.getAPIList('/extensions', OffsetPagination, { + query, + ...options, + }); } /** @@ -103,39 +113,37 @@ export class Extensions extends APIResource { } } -export type ExtensionListResponse = Array; +export type ExtensionListResponsesOffsetPagination = OffsetPagination; -export namespace ExtensionListResponse { +/** + * A browser extension uploaded to Kernel. + */ +export interface ExtensionListResponse { /** - * A browser extension uploaded to Kernel. + * Unique identifier for the extension */ - export interface ExtensionListResponseItem { - /** - * Unique identifier for the extension - */ - id: string; + id: string; - /** - * Timestamp when the extension was created - */ - created_at: string; + /** + * Timestamp when the extension was created + */ + created_at: string; - /** - * Size of the extension archive in bytes - */ - size_bytes: number; + /** + * Size of the extension archive in bytes + */ + size_bytes: number; - /** - * Timestamp when the extension was last used - */ - last_used_at?: string | null; + /** + * Timestamp when the extension was last used + */ + last_used_at?: string | null; - /** - * Optional, easier-to-reference name for the extension. Must be unique within the - * project. - */ - name?: string | null; - } + /** + * Optional, easier-to-reference name for the extension. Must be unique within the + * project. + */ + name?: string | null; } /** @@ -169,6 +177,8 @@ export interface ExtensionUploadResponse { name?: string | null; } +export interface ExtensionListParams extends OffsetPaginationParams {} + export interface ExtensionDownloadFromChromeStoreParams { /** * Chrome Web Store URL for the extension. @@ -197,6 +207,8 @@ export declare namespace Extensions { export { type ExtensionListResponse as ExtensionListResponse, type ExtensionUploadResponse as ExtensionUploadResponse, + type ExtensionListResponsesOffsetPagination as ExtensionListResponsesOffsetPagination, + type ExtensionListParams as ExtensionListParams, type ExtensionDownloadFromChromeStoreParams as ExtensionDownloadFromChromeStoreParams, type ExtensionUploadParams as ExtensionUploadParams, }; diff --git a/src/resources/index.ts b/src/resources/index.ts index 6e1bca38..d261b196 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -87,8 +87,10 @@ export { Extensions, type ExtensionListResponse, type ExtensionUploadResponse, + type ExtensionListParams, type ExtensionDownloadFromChromeStoreParams, type ExtensionUploadParams, + type ExtensionListResponsesOffsetPagination, } from './extensions'; export { Invocations, diff --git a/tests/api-resources/extensions.test.ts b/tests/api-resources/extensions.test.ts index 9a00e8c4..8f03039f 100644 --- a/tests/api-resources/extensions.test.ts +++ b/tests/api-resources/extensions.test.ts @@ -20,6 +20,14 @@ describe('resource extensions', () => { expect(dataAndResponse.response).toBe(rawResponse); }); + // Mock server tests are disabled + test.skip('list: 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.extensions.list({ limit: 1, offset: 0 }, { path: '/_stainless_unknown_path' }), + ).rejects.toThrow(Kernel.NotFoundError); + }); + // Mock server tests are disabled test.skip('delete', async () => { const responsePromise = client.extensions.delete('id_or_name'); From b90ba14153523640cac7886ebd662cdb547976c7 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 4 Jun 2026 15:04:10 +0000 Subject: [PATCH 423/551] feat: api: paginate GET /org/credential_providers --- .stats.yml | 6 ++--- api.md | 3 +-- src/client.ts | 6 +++-- src/resources/credential-providers.ts | 26 ++++++++++++++----- src/resources/index.ts | 3 ++- .../credential-providers.test.ts | 8 ++++++ 6 files changed, 37 insertions(+), 15 deletions(-) diff --git a/.stats.yml b/.stats.yml index 582e6b44..5ea72073 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 117 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-9a76e7a837ac9ffbe0e9557d618ce9b676e052249e364e516c28ddb33b912019.yml -openapi_spec_hash: c0e5412cc95139f11a8b8635559bb985 -config_hash: 098a7f3fd134c8e4cbd3a44750892a18 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-e6c711f0d29a7d956cc8ca621440da966c1f1575b1205d01328b1099edf1c517.yml +openapi_spec_hash: c06e7e36de1c6f9b29b54a6e3dc08ee5 +config_hash: 36159c262d293fbeacf513ab600a1729 diff --git a/api.md b/api.md index 7a4781e8..9880356b 100644 --- a/api.md +++ b/api.md @@ -390,7 +390,6 @@ Types: - CredentialProviderItem - CredentialProviderTestResult - UpdateCredentialProviderRequest -- CredentialProviderListResponse - CredentialProviderListItemsResponse Methods: @@ -398,7 +397,7 @@ Methods: - client.credentialProviders.create({ ...params }) -> CredentialProvider - client.credentialProviders.retrieve(id) -> CredentialProvider - client.credentialProviders.update(id, { ...params }) -> CredentialProvider -- client.credentialProviders.list() -> CredentialProviderListResponse +- client.credentialProviders.list({ ...params }) -> CredentialProvidersOffsetPagination - client.credentialProviders.delete(id) -> void - client.credentialProviders.listItems(id) -> CredentialProviderListItemsResponse - client.credentialProviders.test(id) -> CredentialProviderTestResult diff --git a/src/client.ts b/src/client.ts index c0ca1a34..961b89b1 100644 --- a/src/client.ts +++ b/src/client.ts @@ -47,10 +47,11 @@ import { CredentialProviderCreateParams, CredentialProviderItem, CredentialProviderListItemsResponse, - CredentialProviderListResponse, + CredentialProviderListParams, CredentialProviderTestResult, CredentialProviderUpdateParams, CredentialProviders, + CredentialProvidersOffsetPagination, UpdateCredentialProviderRequest, } from './resources/credential-providers'; import { @@ -1113,10 +1114,11 @@ export declare namespace Kernel { type CredentialProviderItem as CredentialProviderItem, type CredentialProviderTestResult as CredentialProviderTestResult, type UpdateCredentialProviderRequest as UpdateCredentialProviderRequest, - type CredentialProviderListResponse as CredentialProviderListResponse, type CredentialProviderListItemsResponse as CredentialProviderListItemsResponse, + type CredentialProvidersOffsetPagination as CredentialProvidersOffsetPagination, type CredentialProviderCreateParams as CredentialProviderCreateParams, type CredentialProviderUpdateParams as CredentialProviderUpdateParams, + type CredentialProviderListParams as CredentialProviderListParams, }; export type AppAction = API.AppAction; diff --git a/src/resources/credential-providers.ts b/src/resources/credential-providers.ts index 091015c6..5386ac06 100644 --- a/src/resources/credential-providers.ts +++ b/src/resources/credential-providers.ts @@ -2,6 +2,7 @@ import { APIResource } from '../core/resource'; import { APIPromise } from '../core/api-promise'; +import { OffsetPagination, type OffsetPaginationParams, PagePromise } from '../core/pagination'; import { buildHeaders } from '../internal/headers'; import { RequestOptions } from '../internal/request-options'; import { path } from '../internal/utils/path'; @@ -63,12 +64,20 @@ export class CredentialProviders extends APIResource { * * @example * ```ts - * const credentialProviders = - * await client.credentialProviders.list(); + * // Automatically fetches more pages as needed. + * for await (const credentialProvider of client.credentialProviders.list()) { + * // ... + * } * ``` */ - list(options?: RequestOptions): APIPromise { - return this._client.get('/org/credential_providers', options); + list( + query: CredentialProviderListParams | null | undefined = {}, + options?: RequestOptions, + ): PagePromise { + return this._client.getAPIList('/org/credential_providers', OffsetPagination, { + query, + ...options, + }); } /** @@ -115,6 +124,8 @@ export class CredentialProviders extends APIResource { } } +export type CredentialProvidersOffsetPagination = OffsetPagination; + /** * Request to create an external credential provider */ @@ -280,8 +291,6 @@ export interface UpdateCredentialProviderRequest { priority?: number; } -export type CredentialProviderListResponse = Array; - export interface CredentialProviderListItemsResponse { items?: Array; } @@ -335,6 +344,8 @@ export interface CredentialProviderUpdateParams { priority?: number; } +export interface CredentialProviderListParams extends OffsetPaginationParams {} + export declare namespace CredentialProviders { export { type CreateCredentialProviderRequest as CreateCredentialProviderRequest, @@ -342,9 +353,10 @@ export declare namespace CredentialProviders { type CredentialProviderItem as CredentialProviderItem, type CredentialProviderTestResult as CredentialProviderTestResult, type UpdateCredentialProviderRequest as UpdateCredentialProviderRequest, - type CredentialProviderListResponse as CredentialProviderListResponse, type CredentialProviderListItemsResponse as CredentialProviderListItemsResponse, + type CredentialProvidersOffsetPagination as CredentialProvidersOffsetPagination, type CredentialProviderCreateParams as CredentialProviderCreateParams, type CredentialProviderUpdateParams as CredentialProviderUpdateParams, + type CredentialProviderListParams as CredentialProviderListParams, }; } diff --git a/src/resources/index.ts b/src/resources/index.ts index d261b196..26038839 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -55,10 +55,11 @@ export { type CredentialProviderItem, type CredentialProviderTestResult, type UpdateCredentialProviderRequest, - type CredentialProviderListResponse, type CredentialProviderListItemsResponse, type CredentialProviderCreateParams, type CredentialProviderUpdateParams, + type CredentialProviderListParams, + type CredentialProvidersOffsetPagination, } from './credential-providers'; export { Credentials, diff --git a/tests/api-resources/credential-providers.test.ts b/tests/api-resources/credential-providers.test.ts index 439b9a1a..ae64be3e 100644 --- a/tests/api-resources/credential-providers.test.ts +++ b/tests/api-resources/credential-providers.test.ts @@ -70,6 +70,14 @@ describe('resource credentialProviders', () => { expect(dataAndResponse.response).toBe(rawResponse); }); + // Mock server tests are disabled + test.skip('list: 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.credentialProviders.list({ limit: 1, offset: 0 }, { path: '/_stainless_unknown_path' }), + ).rejects.toThrow(Kernel.NotFoundError); + }); + // Mock server tests are disabled test.skip('delete', async () => { const responsePromise = client.credentialProviders.delete('id'); From 7300b7000339f4718fcc222dad542d2cf6b7fb57 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 4 Jun 2026 15:39:55 +0000 Subject: [PATCH 424/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index c11d4bc2..4f40d13b 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.61.0" + ".": "0.62.0" } diff --git a/package.json b/package.json index 1b427341..29db9412 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.61.0", + "version": "0.62.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 232058f3..59e6a166 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.61.0'; // x-release-please-version +export const VERSION = '0.62.0'; // x-release-please-version From bcf36d9429707c0a20b30427173739ed3a578864 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 4 Jun 2026 19:39:16 +0000 Subject: [PATCH 425/551] feat(api): allow setting a custom name on a browser session at create time --- .stats.yml | 4 +-- src/resources/browser-pools.ts | 5 ++++ src/resources/browsers/browsers.ts | 29 ++++++++++++++++++- src/resources/invocations.ts | 5 ++++ tests/api-resources/browsers/browsers.test.ts | 1 + 5 files changed, 41 insertions(+), 3 deletions(-) diff --git a/.stats.yml b/.stats.yml index 5ea72073..b8e42864 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 117 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-e6c711f0d29a7d956cc8ca621440da966c1f1575b1205d01328b1099edf1c517.yml -openapi_spec_hash: c06e7e36de1c6f9b29b54a6e3dc08ee5 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-e7925f5cb9626a47fd24470851ff4149c27bc89795f75e8641c618fff93a076c.yml +openapi_spec_hash: 955d4bf81e9838b0732c0e52716a2030 config_hash: 36159c262d293fbeacf513ab600a1729 diff --git a/src/resources/browser-pools.ts b/src/resources/browser-pools.ts index 3744c41e..41ae1cd9 100644 --- a/src/resources/browser-pools.ts +++ b/src/resources/browser-pools.ts @@ -355,6 +355,11 @@ export interface BrowserPoolAcquireResponse { */ kiosk_mode?: boolean; + /** + * Human-readable name of the browser session, if one was set at creation. + */ + name?: string; + /** * Browser pool this session was acquired from, if any. */ diff --git a/src/resources/browsers/browsers.ts b/src/resources/browsers/browsers.ts index 911837bb..d5bf116a 100644 --- a/src/resources/browsers/browsers.ts +++ b/src/resources/browsers/browsers.ts @@ -379,6 +379,11 @@ export interface BrowserCreateResponse { */ kiosk_mode?: boolean; + /** + * Human-readable name of the browser session, if one was set at creation. + */ + name?: string; + /** * Browser pool this session was acquired from, if any. */ @@ -500,6 +505,11 @@ export interface BrowserRetrieveResponse { */ kiosk_mode?: boolean; + /** + * Human-readable name of the browser session, if one was set at creation. + */ + name?: string; + /** * Browser pool this session was acquired from, if any. */ @@ -621,6 +631,11 @@ export interface BrowserUpdateResponse { */ kiosk_mode?: boolean; + /** + * Human-readable name of the browser session, if one was set at creation. + */ + name?: string; + /** * Browser pool this session was acquired from, if any. */ @@ -742,6 +757,11 @@ export interface BrowserListResponse { */ kiosk_mode?: boolean; + /** + * Human-readable name of the browser session, if one was set at creation. + */ + name?: string; + /** * Browser pool this session was acquired from, if any. */ @@ -855,6 +875,13 @@ export interface BrowserCreateParams { */ kiosk_mode?: boolean; + /** + * Optional human-readable name for the browser session, used to find it later in + * the dashboard. Must be unique among active sessions within the project. Set at + * creation time only. + */ + name?: string; + /** * Profile selection for the browser session. Provide either id or name. If * specified, the matching profile will be loaded into the browser session. @@ -1030,7 +1057,7 @@ export interface BrowserListParams extends OffsetPaginationParams { include_deleted?: boolean; /** - * Search browsers by session ID, profile ID, proxy ID, or pool name. + * Search browsers by name, session ID, profile ID, proxy ID, or pool name. */ query?: string; diff --git a/src/resources/invocations.ts b/src/resources/invocations.ts index b99efb4e..104fa849 100644 --- a/src/resources/invocations.ts +++ b/src/resources/invocations.ts @@ -488,6 +488,11 @@ export namespace InvocationListBrowsersResponse { */ kiosk_mode?: boolean; + /** + * Human-readable name of the browser session, if one was set at creation. + */ + name?: string; + /** * Browser pool this session was acquired from, if any. */ diff --git a/tests/api-resources/browsers/browsers.test.ts b/tests/api-resources/browsers/browsers.test.ts index 370bfc5e..f4d9233a 100644 --- a/tests/api-resources/browsers/browsers.test.ts +++ b/tests/api-resources/browsers/browsers.test.ts @@ -32,6 +32,7 @@ describe('resource browsers', () => { headless: false, invocation_id: 'rr33xuugxj9h0bkf1rdt2bet', kiosk_mode: true, + name: 'amazon-scrape-1', profile: { id: 'id', name: 'name', From 8d0bd48340736a068dfb72f3715a757e23ec6f3e Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 4 Jun 2026 22:07:41 +0000 Subject: [PATCH 426/551] docs(api): use neutral example for browser session name field --- .stats.yml | 4 ++-- tests/api-resources/browsers/browsers.test.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.stats.yml b/.stats.yml index b8e42864..afee3b79 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 117 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-e7925f5cb9626a47fd24470851ff4149c27bc89795f75e8641c618fff93a076c.yml -openapi_spec_hash: 955d4bf81e9838b0732c0e52716a2030 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-152175b971564fc089733419adff5f79aa5556cb264bea7be5ca7582fda82b61.yml +openapi_spec_hash: 054e48b4743d014f0ec199757990e2c3 config_hash: 36159c262d293fbeacf513ab600a1729 diff --git a/tests/api-resources/browsers/browsers.test.ts b/tests/api-resources/browsers/browsers.test.ts index f4d9233a..9428311e 100644 --- a/tests/api-resources/browsers/browsers.test.ts +++ b/tests/api-resources/browsers/browsers.test.ts @@ -32,7 +32,7 @@ describe('resource browsers', () => { headless: false, invocation_id: 'rr33xuugxj9h0bkf1rdt2bet', kiosk_mode: true, - name: 'amazon-scrape-1', + name: 'checkout-flow-1', profile: { id: 'id', name: 'name', From 8fbc38c7227b1a6ec6047154529541c055982a60 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 4 Jun 2026 22:18:58 +0000 Subject: [PATCH 427/551] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index afee3b79..c2258b3d 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 117 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-152175b971564fc089733419adff5f79aa5556cb264bea7be5ca7582fda82b61.yml -openapi_spec_hash: 054e48b4743d014f0ec199757990e2c3 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-d0f7d8820ee342b6b8e32d5c08620d7a31135a6aabbe8266118b54269fbabb9d.yml +openapi_spec_hash: 371eb419c25eb160fbc0135e45c133d1 config_hash: 36159c262d293fbeacf513ab600a1729 From f1fb3ca2595a41884d61ccfad5c2086c88ac2ea1 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 5 Jun 2026 15:36:44 +0000 Subject: [PATCH 428/551] feat(api): allow setting key-value tags on a browser session at create time --- .stats.yml | 6 +- api.md | 1 + src/client.ts | 5 +- src/internal/qs/LICENSE.md | 13 + src/internal/qs/README.md | 3 + src/internal/qs/formats.ts | 10 + src/internal/qs/index.ts | 13 + src/internal/qs/stringify.ts | 385 +++ src/internal/qs/types.ts | 71 + src/internal/qs/utils.ts | 265 ++ src/internal/utils/query.ts | 20 +- src/resources/browser-pools.ts | 6 + src/resources/browsers/browsers.ts | 43 + src/resources/browsers/index.ts | 1 + src/resources/index.ts | 1 + src/resources/invocations.ts | 6 + tests/api-resources/browsers/browsers.test.ts | 2 + tests/qs/empty-keys-cases.ts | 271 ++ tests/qs/stringify.test.ts | 2232 +++++++++++++++++ tests/qs/utils.test.ts | 169 ++ tests/stringifyQuery.test.ts | 6 - 21 files changed, 3499 insertions(+), 30 deletions(-) create mode 100644 src/internal/qs/LICENSE.md create mode 100644 src/internal/qs/README.md create mode 100644 src/internal/qs/formats.ts create mode 100644 src/internal/qs/index.ts create mode 100644 src/internal/qs/stringify.ts create mode 100644 src/internal/qs/types.ts create mode 100644 src/internal/qs/utils.ts create mode 100644 tests/qs/empty-keys-cases.ts create mode 100644 tests/qs/stringify.test.ts create mode 100644 tests/qs/utils.test.ts diff --git a/.stats.yml b/.stats.yml index c2258b3d..b53121ed 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 117 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-d0f7d8820ee342b6b8e32d5c08620d7a31135a6aabbe8266118b54269fbabb9d.yml -openapi_spec_hash: 371eb419c25eb160fbc0135e45c133d1 -config_hash: 36159c262d293fbeacf513ab600a1729 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-8f84f4214a8024d8ea62ee639eeaf2fa26900fabe23c8b87accb41d529a0bf4f.yml +openapi_spec_hash: db14f415438b3d338d9376bddc83a5cf +config_hash: 590bf8cb85948cf1e63b7b5ef60686c8 diff --git a/api.md b/api.md index 9880356b..337b12a3 100644 --- a/api.md +++ b/api.md @@ -69,6 +69,7 @@ Types: - BrowserPoolRef - BrowserUsage - Profile +- Tags - BrowserCreateResponse - BrowserRetrieveResponse - BrowserUpdateResponse diff --git a/src/client.ts b/src/client.ts index 961b89b1..9a215e06 100644 --- a/src/client.ts +++ b/src/client.ts @@ -131,6 +131,7 @@ import { BrowserUsage, Browsers, Profile, + Tags, } from './resources/browsers/browsers'; import { CreateProjectRequest, @@ -371,9 +372,6 @@ export class Kernel { return buildHeaders([{ Authorization: `Bearer ${this.apiKey}` }]); } - /** - * Basic re-implementation of `qs.stringify` for primitive types. - */ protected stringifyQuery(query: object | Record): string { return stringifyQuery(query); } @@ -1017,6 +1015,7 @@ export declare namespace Kernel { type BrowserPoolRef as BrowserPoolRef, type BrowserUsage as BrowserUsage, type Profile as Profile, + type Tags as Tags, type BrowserCreateResponse as BrowserCreateResponse, type BrowserRetrieveResponse as BrowserRetrieveResponse, type BrowserUpdateResponse as BrowserUpdateResponse, diff --git a/src/internal/qs/LICENSE.md b/src/internal/qs/LICENSE.md new file mode 100644 index 00000000..3fda1573 --- /dev/null +++ b/src/internal/qs/LICENSE.md @@ -0,0 +1,13 @@ +BSD 3-Clause License + +Copyright (c) 2014, Nathan LaFreniere and other [contributors](https://github.com/puruvj/neoqs/graphs/contributors) All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/src/internal/qs/README.md b/src/internal/qs/README.md new file mode 100644 index 00000000..67ae04ec --- /dev/null +++ b/src/internal/qs/README.md @@ -0,0 +1,3 @@ +# qs + +This is a vendored version of [neoqs](https://github.com/PuruVJ/neoqs) which is a TypeScript rewrite of [qs](https://github.com/ljharb/qs), a query string library. diff --git a/src/internal/qs/formats.ts b/src/internal/qs/formats.ts new file mode 100644 index 00000000..e76a742f --- /dev/null +++ b/src/internal/qs/formats.ts @@ -0,0 +1,10 @@ +import type { Format } from './types'; + +export const default_format: Format = 'RFC3986'; +export const default_formatter = (v: PropertyKey) => String(v); +export const formatters: Record string> = { + RFC1738: (v: PropertyKey) => String(v).replace(/%20/g, '+'), + RFC3986: default_formatter, +}; +export const RFC1738 = 'RFC1738'; +export const RFC3986 = 'RFC3986'; diff --git a/src/internal/qs/index.ts b/src/internal/qs/index.ts new file mode 100644 index 00000000..c3a3620d --- /dev/null +++ b/src/internal/qs/index.ts @@ -0,0 +1,13 @@ +import { default_format, formatters, RFC1738, RFC3986 } from './formats'; + +const formats = { + formatters, + RFC1738, + RFC3986, + default: default_format, +}; + +export { stringify } from './stringify'; +export { formats }; + +export type { DefaultDecoder, DefaultEncoder, Format, ParseOptions, StringifyOptions } from './types'; diff --git a/src/internal/qs/stringify.ts b/src/internal/qs/stringify.ts new file mode 100644 index 00000000..7e71387f --- /dev/null +++ b/src/internal/qs/stringify.ts @@ -0,0 +1,385 @@ +import { encode, is_buffer, maybe_map, has } from './utils'; +import { default_format, default_formatter, formatters } from './formats'; +import type { NonNullableProperties, StringifyOptions } from './types'; +import { isArray } from '../utils/values'; + +const array_prefix_generators = { + brackets(prefix: PropertyKey) { + return String(prefix) + '[]'; + }, + comma: 'comma', + indices(prefix: PropertyKey, key: string) { + return String(prefix) + '[' + key + ']'; + }, + repeat(prefix: PropertyKey) { + return String(prefix); + }, +}; + +const push_to_array = function (arr: any[], value_or_array: any) { + Array.prototype.push.apply(arr, isArray(value_or_array) ? value_or_array : [value_or_array]); +}; + +let toISOString; + +const defaults = { + addQueryPrefix: false, + allowDots: false, + allowEmptyArrays: false, + arrayFormat: 'indices', + charset: 'utf-8', + charsetSentinel: false, + delimiter: '&', + encode: true, + encodeDotInKeys: false, + encoder: encode, + encodeValuesOnly: false, + format: default_format, + formatter: default_formatter, + /** @deprecated */ + indices: false, + serializeDate(date) { + return (toISOString ??= Function.prototype.call.bind(Date.prototype.toISOString))(date); + }, + skipNulls: false, + strictNullHandling: false, +} as NonNullableProperties; + +function is_non_nullish_primitive(v: unknown): v is string | number | boolean | symbol | bigint { + return ( + typeof v === 'string' || + typeof v === 'number' || + typeof v === 'boolean' || + typeof v === 'symbol' || + typeof v === 'bigint' + ); +} + +const sentinel = {}; + +function inner_stringify( + object: any, + prefix: PropertyKey, + generateArrayPrefix: StringifyOptions['arrayFormat'] | ((prefix: string, key: string) => string), + commaRoundTrip: boolean, + allowEmptyArrays: boolean, + strictNullHandling: boolean, + skipNulls: boolean, + encodeDotInKeys: boolean, + encoder: StringifyOptions['encoder'], + filter: StringifyOptions['filter'], + sort: StringifyOptions['sort'], + allowDots: StringifyOptions['allowDots'], + serializeDate: StringifyOptions['serializeDate'], + format: StringifyOptions['format'], + formatter: StringifyOptions['formatter'], + encodeValuesOnly: boolean, + charset: StringifyOptions['charset'], + sideChannel: WeakMap, +) { + let obj = object; + + let tmp_sc = sideChannel; + let step = 0; + let find_flag = false; + while ((tmp_sc = tmp_sc.get(sentinel)) !== void undefined && !find_flag) { + // Where object last appeared in the ref tree + const pos = tmp_sc.get(object); + step += 1; + if (typeof pos !== 'undefined') { + if (pos === step) { + throw new RangeError('Cyclic object value'); + } else { + find_flag = true; // Break while + } + } + if (typeof tmp_sc.get(sentinel) === 'undefined') { + step = 0; + } + } + + if (typeof filter === 'function') { + obj = filter(prefix, obj); + } else if (obj instanceof Date) { + obj = serializeDate?.(obj); + } else if (generateArrayPrefix === 'comma' && isArray(obj)) { + obj = maybe_map(obj, function (value) { + if (value instanceof Date) { + return serializeDate?.(value); + } + return value; + }); + } + + if (obj === null) { + if (strictNullHandling) { + return encoder && !encodeValuesOnly ? + // @ts-expect-error + encoder(prefix, defaults.encoder, charset, 'key', format) + : prefix; + } + + obj = ''; + } + + if (is_non_nullish_primitive(obj) || is_buffer(obj)) { + if (encoder) { + const key_value = + encodeValuesOnly ? prefix + // @ts-expect-error + : encoder(prefix, defaults.encoder, charset, 'key', format); + return [ + formatter?.(key_value) + + '=' + + // @ts-expect-error + formatter?.(encoder(obj, defaults.encoder, charset, 'value', format)), + ]; + } + return [formatter?.(prefix) + '=' + formatter?.(String(obj))]; + } + + const values: string[] = []; + + if (typeof obj === 'undefined') { + return values; + } + + let obj_keys; + if (generateArrayPrefix === 'comma' && isArray(obj)) { + // we need to join elements in + if (encodeValuesOnly && encoder) { + // @ts-expect-error values only + obj = maybe_map(obj, encoder); + } + obj_keys = [{ value: obj.length > 0 ? obj.join(',') || null : void undefined }]; + } else if (isArray(filter)) { + obj_keys = filter; + } else { + const keys = Object.keys(obj); + obj_keys = sort ? keys.sort(sort) : keys; + } + + const encoded_prefix = encodeDotInKeys ? String(prefix).replace(/\./g, '%2E') : String(prefix); + + const adjusted_prefix = + commaRoundTrip && isArray(obj) && obj.length === 1 ? encoded_prefix + '[]' : encoded_prefix; + + if (allowEmptyArrays && isArray(obj) && obj.length === 0) { + return adjusted_prefix + '[]'; + } + + for (let j = 0; j < obj_keys.length; ++j) { + const key = obj_keys[j]; + const value = + // @ts-ignore + typeof key === 'object' && typeof key.value !== 'undefined' ? key.value : obj[key as any]; + + if (skipNulls && value === null) { + continue; + } + + // @ts-ignore + const encoded_key = allowDots && encodeDotInKeys ? (key as any).replace(/\./g, '%2E') : key; + const key_prefix = + isArray(obj) ? + typeof generateArrayPrefix === 'function' ? + generateArrayPrefix(adjusted_prefix, encoded_key) + : adjusted_prefix + : adjusted_prefix + (allowDots ? '.' + encoded_key : '[' + encoded_key + ']'); + + sideChannel.set(object, step); + const valueSideChannel = new WeakMap(); + valueSideChannel.set(sentinel, sideChannel); + push_to_array( + values, + inner_stringify( + value, + key_prefix, + generateArrayPrefix, + commaRoundTrip, + allowEmptyArrays, + strictNullHandling, + skipNulls, + encodeDotInKeys, + // @ts-ignore + generateArrayPrefix === 'comma' && encodeValuesOnly && isArray(obj) ? null : encoder, + filter, + sort, + allowDots, + serializeDate, + format, + formatter, + encodeValuesOnly, + charset, + valueSideChannel, + ), + ); + } + + return values; +} + +function normalize_stringify_options( + opts: StringifyOptions = defaults, +): NonNullableProperties> & { indices?: boolean } { + if (typeof opts.allowEmptyArrays !== 'undefined' && typeof opts.allowEmptyArrays !== 'boolean') { + throw new TypeError('`allowEmptyArrays` option can only be `true` or `false`, when provided'); + } + + if (typeof opts.encodeDotInKeys !== 'undefined' && typeof opts.encodeDotInKeys !== 'boolean') { + throw new TypeError('`encodeDotInKeys` option can only be `true` or `false`, when provided'); + } + + if (opts.encoder !== null && typeof opts.encoder !== 'undefined' && typeof opts.encoder !== 'function') { + throw new TypeError('Encoder has to be a function.'); + } + + const charset = opts.charset || defaults.charset; + if (typeof opts.charset !== 'undefined' && opts.charset !== 'utf-8' && opts.charset !== 'iso-8859-1') { + throw new TypeError('The charset option must be either utf-8, iso-8859-1, or undefined'); + } + + let format = default_format; + if (typeof opts.format !== 'undefined') { + if (!has(formatters, opts.format)) { + throw new TypeError('Unknown format option provided.'); + } + format = opts.format; + } + const formatter = formatters[format]; + + let filter = defaults.filter; + if (typeof opts.filter === 'function' || isArray(opts.filter)) { + filter = opts.filter; + } + + let arrayFormat: StringifyOptions['arrayFormat']; + if (opts.arrayFormat && opts.arrayFormat in array_prefix_generators) { + arrayFormat = opts.arrayFormat; + } else if ('indices' in opts) { + arrayFormat = opts.indices ? 'indices' : 'repeat'; + } else { + arrayFormat = defaults.arrayFormat; + } + + if ('commaRoundTrip' in opts && typeof opts.commaRoundTrip !== 'boolean') { + throw new TypeError('`commaRoundTrip` must be a boolean, or absent'); + } + + const allowDots = + typeof opts.allowDots === 'undefined' ? + !!opts.encodeDotInKeys === true ? + true + : defaults.allowDots + : !!opts.allowDots; + + return { + addQueryPrefix: typeof opts.addQueryPrefix === 'boolean' ? opts.addQueryPrefix : defaults.addQueryPrefix, + // @ts-ignore + allowDots: allowDots, + allowEmptyArrays: + typeof opts.allowEmptyArrays === 'boolean' ? !!opts.allowEmptyArrays : defaults.allowEmptyArrays, + arrayFormat: arrayFormat, + charset: charset, + charsetSentinel: + typeof opts.charsetSentinel === 'boolean' ? opts.charsetSentinel : defaults.charsetSentinel, + commaRoundTrip: !!opts.commaRoundTrip, + delimiter: typeof opts.delimiter === 'undefined' ? defaults.delimiter : opts.delimiter, + encode: typeof opts.encode === 'boolean' ? opts.encode : defaults.encode, + encodeDotInKeys: + typeof opts.encodeDotInKeys === 'boolean' ? opts.encodeDotInKeys : defaults.encodeDotInKeys, + encoder: typeof opts.encoder === 'function' ? opts.encoder : defaults.encoder, + encodeValuesOnly: + typeof opts.encodeValuesOnly === 'boolean' ? opts.encodeValuesOnly : defaults.encodeValuesOnly, + filter: filter, + format: format, + formatter: formatter, + serializeDate: typeof opts.serializeDate === 'function' ? opts.serializeDate : defaults.serializeDate, + skipNulls: typeof opts.skipNulls === 'boolean' ? opts.skipNulls : defaults.skipNulls, + // @ts-ignore + sort: typeof opts.sort === 'function' ? opts.sort : null, + strictNullHandling: + typeof opts.strictNullHandling === 'boolean' ? opts.strictNullHandling : defaults.strictNullHandling, + }; +} + +export function stringify(object: any, opts: StringifyOptions = {}) { + let obj = object; + const options = normalize_stringify_options(opts); + + let obj_keys: PropertyKey[] | undefined; + let filter; + + if (typeof options.filter === 'function') { + filter = options.filter; + obj = filter('', obj); + } else if (isArray(options.filter)) { + filter = options.filter; + obj_keys = filter; + } + + const keys: string[] = []; + + if (typeof obj !== 'object' || obj === null) { + return ''; + } + + const generateArrayPrefix = array_prefix_generators[options.arrayFormat]; + const commaRoundTrip = generateArrayPrefix === 'comma' && options.commaRoundTrip; + + if (!obj_keys) { + obj_keys = Object.keys(obj); + } + + if (options.sort) { + obj_keys.sort(options.sort); + } + + const sideChannel = new WeakMap(); + for (let i = 0; i < obj_keys.length; ++i) { + const key = obj_keys[i]!; + + if (options.skipNulls && obj[key] === null) { + continue; + } + push_to_array( + keys, + inner_stringify( + obj[key], + key, + // @ts-expect-error + generateArrayPrefix, + commaRoundTrip, + options.allowEmptyArrays, + options.strictNullHandling, + options.skipNulls, + options.encodeDotInKeys, + options.encode ? options.encoder : null, + options.filter, + options.sort, + options.allowDots, + options.serializeDate, + options.format, + options.formatter, + options.encodeValuesOnly, + options.charset, + sideChannel, + ), + ); + } + + const joined = keys.join(options.delimiter); + let prefix = options.addQueryPrefix === true ? '?' : ''; + + if (options.charsetSentinel) { + if (options.charset === 'iso-8859-1') { + // encodeURIComponent('✓'), the "numeric entity" representation of a checkmark + prefix += 'utf8=%26%2310003%3B&'; + } else { + // encodeURIComponent('✓') + prefix += 'utf8=%E2%9C%93&'; + } + } + + return joined.length > 0 ? prefix + joined : ''; +} diff --git a/src/internal/qs/types.ts b/src/internal/qs/types.ts new file mode 100644 index 00000000..7c28dbb4 --- /dev/null +++ b/src/internal/qs/types.ts @@ -0,0 +1,71 @@ +export type Format = 'RFC1738' | 'RFC3986'; + +export type DefaultEncoder = (str: any, defaultEncoder?: any, charset?: string) => string; +export type DefaultDecoder = (str: string, decoder?: any, charset?: string) => string; + +export type BooleanOptional = boolean | undefined; + +export type StringifyBaseOptions = { + delimiter?: string; + allowDots?: boolean; + encodeDotInKeys?: boolean; + strictNullHandling?: boolean; + skipNulls?: boolean; + encode?: boolean; + encoder?: ( + str: any, + defaultEncoder: DefaultEncoder, + charset: string, + type: 'key' | 'value', + format?: Format, + ) => string; + filter?: Array | ((prefix: PropertyKey, value: any) => any); + arrayFormat?: 'indices' | 'brackets' | 'repeat' | 'comma'; + indices?: boolean; + sort?: ((a: PropertyKey, b: PropertyKey) => number) | null; + serializeDate?: (d: Date) => string; + format?: 'RFC1738' | 'RFC3986'; + formatter?: (str: PropertyKey) => string; + encodeValuesOnly?: boolean; + addQueryPrefix?: boolean; + charset?: 'utf-8' | 'iso-8859-1'; + charsetSentinel?: boolean; + allowEmptyArrays?: boolean; + commaRoundTrip?: boolean; +}; + +export type StringifyOptions = StringifyBaseOptions; + +export type ParseBaseOptions = { + comma?: boolean; + delimiter?: string | RegExp; + depth?: number | false; + decoder?: (str: string, defaultDecoder: DefaultDecoder, charset: string, type: 'key' | 'value') => any; + arrayLimit?: number; + parseArrays?: boolean; + plainObjects?: boolean; + allowPrototypes?: boolean; + allowSparse?: boolean; + parameterLimit?: number; + strictDepth?: boolean; + strictNullHandling?: boolean; + ignoreQueryPrefix?: boolean; + charset?: 'utf-8' | 'iso-8859-1'; + charsetSentinel?: boolean; + interpretNumericEntities?: boolean; + allowEmptyArrays?: boolean; + duplicates?: 'combine' | 'first' | 'last'; + allowDots?: boolean; + decodeDotInKeys?: boolean; +}; + +export type ParseOptions = ParseBaseOptions; + +export type ParsedQs = { + [key: string]: undefined | string | string[] | ParsedQs | ParsedQs[]; +}; + +// Type to remove null or undefined union from each property +export type NonNullableProperties = { + [K in keyof T]-?: Exclude; +}; diff --git a/src/internal/qs/utils.ts b/src/internal/qs/utils.ts new file mode 100644 index 00000000..4cd56579 --- /dev/null +++ b/src/internal/qs/utils.ts @@ -0,0 +1,265 @@ +import { RFC1738 } from './formats'; +import type { DefaultEncoder, Format } from './types'; +import { isArray } from '../utils/values'; + +export let has = (obj: object, key: PropertyKey): boolean => ( + (has = (Object as any).hasOwn ?? Function.prototype.call.bind(Object.prototype.hasOwnProperty)), + has(obj, key) +); + +const hex_table = /* @__PURE__ */ (() => { + const array = []; + for (let i = 0; i < 256; ++i) { + array.push('%' + ((i < 16 ? '0' : '') + i.toString(16)).toUpperCase()); + } + + return array; +})(); + +function compact_queue>(queue: Array<{ obj: T; prop: string }>) { + while (queue.length > 1) { + const item = queue.pop(); + if (!item) continue; + + const obj = item.obj[item.prop]; + + if (isArray(obj)) { + const compacted: unknown[] = []; + + for (let j = 0; j < obj.length; ++j) { + if (typeof obj[j] !== 'undefined') { + compacted.push(obj[j]); + } + } + + // @ts-ignore + item.obj[item.prop] = compacted; + } + } +} + +function array_to_object(source: any[], options: { plainObjects: boolean }) { + const obj = options && options.plainObjects ? Object.create(null) : {}; + for (let i = 0; i < source.length; ++i) { + if (typeof source[i] !== 'undefined') { + obj[i] = source[i]; + } + } + + return obj; +} + +export function merge( + target: any, + source: any, + options: { plainObjects?: boolean; allowPrototypes?: boolean } = {}, +) { + if (!source) { + return target; + } + + if (typeof source !== 'object') { + if (isArray(target)) { + target.push(source); + } else if (target && typeof target === 'object') { + if ((options && (options.plainObjects || options.allowPrototypes)) || !has(Object.prototype, source)) { + target[source] = true; + } + } else { + return [target, source]; + } + + return target; + } + + if (!target || typeof target !== 'object') { + return [target].concat(source); + } + + let mergeTarget = target; + if (isArray(target) && !isArray(source)) { + // @ts-ignore + mergeTarget = array_to_object(target, options); + } + + if (isArray(target) && isArray(source)) { + source.forEach(function (item, i) { + if (has(target, i)) { + const targetItem = target[i]; + if (targetItem && typeof targetItem === 'object' && item && typeof item === 'object') { + target[i] = merge(targetItem, item, options); + } else { + target.push(item); + } + } else { + target[i] = item; + } + }); + return target; + } + + return Object.keys(source).reduce(function (acc, key) { + const value = source[key]; + + if (has(acc, key)) { + acc[key] = merge(acc[key], value, options); + } else { + acc[key] = value; + } + return acc; + }, mergeTarget); +} + +export function assign_single_source(target: any, source: any) { + return Object.keys(source).reduce(function (acc, key) { + acc[key] = source[key]; + return acc; + }, target); +} + +export function decode(str: string, _: any, charset: string) { + const strWithoutPlus = str.replace(/\+/g, ' '); + if (charset === 'iso-8859-1') { + // unescape never throws, no try...catch needed: + return strWithoutPlus.replace(/%[0-9a-f]{2}/gi, unescape); + } + // utf-8 + try { + return decodeURIComponent(strWithoutPlus); + } catch (e) { + return strWithoutPlus; + } +} + +const limit = 1024; + +export const encode: ( + str: any, + defaultEncoder: DefaultEncoder, + charset: string, + type: 'key' | 'value', + format: Format, +) => string = (str, _defaultEncoder, charset, _kind, format: Format) => { + // This code was originally written by Brian White for the io.js core querystring library. + // It has been adapted here for stricter adherence to RFC 3986 + if (str.length === 0) { + return str; + } + + let string = str; + if (typeof str === 'symbol') { + string = Symbol.prototype.toString.call(str); + } else if (typeof str !== 'string') { + string = String(str); + } + + if (charset === 'iso-8859-1') { + return escape(string).replace(/%u[0-9a-f]{4}/gi, function ($0) { + return '%26%23' + parseInt($0.slice(2), 16) + '%3B'; + }); + } + + let out = ''; + for (let j = 0; j < string.length; j += limit) { + const segment = string.length >= limit ? string.slice(j, j + limit) : string; + const arr = []; + + for (let i = 0; i < segment.length; ++i) { + let c = segment.charCodeAt(i); + if ( + c === 0x2d || // - + c === 0x2e || // . + c === 0x5f || // _ + c === 0x7e || // ~ + (c >= 0x30 && c <= 0x39) || // 0-9 + (c >= 0x41 && c <= 0x5a) || // a-z + (c >= 0x61 && c <= 0x7a) || // A-Z + (format === RFC1738 && (c === 0x28 || c === 0x29)) // ( ) + ) { + arr[arr.length] = segment.charAt(i); + continue; + } + + if (c < 0x80) { + arr[arr.length] = hex_table[c]; + continue; + } + + if (c < 0x800) { + arr[arr.length] = hex_table[0xc0 | (c >> 6)]! + hex_table[0x80 | (c & 0x3f)]; + continue; + } + + if (c < 0xd800 || c >= 0xe000) { + arr[arr.length] = + hex_table[0xe0 | (c >> 12)]! + hex_table[0x80 | ((c >> 6) & 0x3f)] + hex_table[0x80 | (c & 0x3f)]; + continue; + } + + i += 1; + c = 0x10000 + (((c & 0x3ff) << 10) | (segment.charCodeAt(i) & 0x3ff)); + + arr[arr.length] = + hex_table[0xf0 | (c >> 18)]! + + hex_table[0x80 | ((c >> 12) & 0x3f)] + + hex_table[0x80 | ((c >> 6) & 0x3f)] + + hex_table[0x80 | (c & 0x3f)]; + } + + out += arr.join(''); + } + + return out; +}; + +export function compact(value: any) { + const queue = [{ obj: { o: value }, prop: 'o' }]; + const refs = []; + + for (let i = 0; i < queue.length; ++i) { + const item = queue[i]; + // @ts-ignore + const obj = item.obj[item.prop]; + + const keys = Object.keys(obj); + for (let j = 0; j < keys.length; ++j) { + const key = keys[j]!; + const val = obj[key]; + if (typeof val === 'object' && val !== null && refs.indexOf(val) === -1) { + queue.push({ obj: obj, prop: key }); + refs.push(val); + } + } + } + + compact_queue(queue); + + return value; +} + +export function is_regexp(obj: any) { + return Object.prototype.toString.call(obj) === '[object RegExp]'; +} + +export function is_buffer(obj: any) { + if (!obj || typeof obj !== 'object') { + return false; + } + + return !!(obj.constructor && obj.constructor.isBuffer && obj.constructor.isBuffer(obj)); +} + +export function combine(a: any, b: any) { + return [].concat(a, b); +} + +export function maybe_map(val: T[], fn: (v: T) => T) { + if (isArray(val)) { + const mapped = []; + for (let i = 0; i < val.length; i += 1) { + mapped.push(fn(val[i]!)); + } + return mapped; + } + return fn(val); +} diff --git a/src/internal/utils/query.ts b/src/internal/utils/query.ts index 50550d3c..0139cacb 100644 --- a/src/internal/utils/query.ts +++ b/src/internal/utils/query.ts @@ -1,23 +1,7 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { KernelError } from '../../core/error'; +import * as qs from '../qs/stringify'; -/** - * Basic re-implementation of `qs.stringify` for primitive types. - */ export function stringifyQuery(query: object | Record) { - return Object.entries(query) - .filter(([_, value]) => typeof value !== 'undefined') - .map(([key, value]) => { - if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') { - return `${encodeURIComponent(key)}=${encodeURIComponent(value)}`; - } - if (value === null) { - return `${encodeURIComponent(key)}=`; - } - throw new KernelError( - `Cannot stringify type ${typeof value}; Expected string, number, boolean, or null. If you need to pass nested query parameters, you can manually encode them, e.g. { query: { 'foo[key1]': value1, 'foo[key2]': value2 } }, and please open a GitHub issue requesting better support for your use case.`, - ); - }) - .join('&'); + return qs.stringify(query, { arrayFormat: 'comma' }); } diff --git a/src/resources/browser-pools.ts b/src/resources/browser-pools.ts index 41ae1cd9..06e6832b 100644 --- a/src/resources/browser-pools.ts +++ b/src/resources/browser-pools.ts @@ -384,6 +384,12 @@ export interface BrowserPoolAcquireResponse { */ start_url?: string; + /** + * User-defined key-value tags that were set on this browser session, if any. + * Echoed back when present. + */ + tags?: BrowsersAPI.Tags; + /** * Active telemetry configuration for the session, if any. */ diff --git a/src/resources/browsers/browsers.ts b/src/resources/browsers/browsers.ts index d5bf116a..d3d61374 100644 --- a/src/resources/browsers/browsers.ts +++ b/src/resources/browsers/browsers.ts @@ -309,6 +309,11 @@ export interface Profile { updated_at?: string; } +/** + * User-defined key-value tags. + */ +export type Tags = { [key: string]: string }; + export interface BrowserCreateResponse { /** * Websocket URL for Chrome DevTools Protocol connections to the browser session @@ -408,6 +413,12 @@ export interface BrowserCreateResponse { */ start_url?: string; + /** + * User-defined key-value tags that were set on this browser session, if any. + * Echoed back when present. + */ + tags?: Tags; + /** * Active telemetry configuration for the session, if any. */ @@ -534,6 +545,12 @@ export interface BrowserRetrieveResponse { */ start_url?: string; + /** + * User-defined key-value tags that were set on this browser session, if any. + * Echoed back when present. + */ + tags?: Tags; + /** * Active telemetry configuration for the session, if any. */ @@ -660,6 +677,12 @@ export interface BrowserUpdateResponse { */ start_url?: string; + /** + * User-defined key-value tags that were set on this browser session, if any. + * Echoed back when present. + */ + tags?: Tags; + /** * Active telemetry configuration for the session, if any. */ @@ -786,6 +809,12 @@ export interface BrowserListResponse { */ start_url?: string; + /** + * User-defined key-value tags that were set on this browser session, if any. + * Echoed back when present. + */ + tags?: Tags; + /** * Active telemetry configuration for the session, if any. */ @@ -908,6 +937,12 @@ export interface BrowserCreateParams { */ stealth?: boolean; + /** + * Optional user-defined key-value tags for the browser session, used to find and + * group sessions later. Set at creation time only. Up to 50 pairs. + */ + tags?: Tags; + /** * Telemetry configuration for the browser session. Set enabled to true to start * capture using VM defaults, or provide browser category settings. If omitted, @@ -1066,6 +1101,13 @@ export interface BrowserListParams extends OffsetPaginationParams { * "deleted" returns only soft-deleted sessions, "all" returns both. */ status?: 'active' | 'deleted' | 'all'; + + /** + * Filter sessions by tag key-value pairs using deepObject style, e.g. + * ?tags[team]=backend&tags[env]=staging. Multiple pairs are ANDed: a session must + * match every supplied pair exactly. + */ + tags?: { [key: string]: string }; } export interface BrowserCurlParams { @@ -1135,6 +1177,7 @@ export declare namespace Browsers { type BrowserPoolRef as BrowserPoolRef, type BrowserUsage as BrowserUsage, type Profile as Profile, + type Tags as Tags, type BrowserCreateResponse as BrowserCreateResponse, type BrowserRetrieveResponse as BrowserRetrieveResponse, type BrowserUpdateResponse as BrowserUpdateResponse, diff --git a/src/resources/browsers/index.ts b/src/resources/browsers/index.ts index 98ba2d8b..08e2fdec 100644 --- a/src/resources/browsers/index.ts +++ b/src/resources/browsers/index.ts @@ -5,6 +5,7 @@ export { type BrowserPoolRef, type BrowserUsage, type Profile, + type Tags, type BrowserCreateResponse, type BrowserRetrieveResponse, type BrowserUpdateResponse, diff --git a/src/resources/index.ts b/src/resources/index.ts index 26038839..d92fde23 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -34,6 +34,7 @@ export { type BrowserPoolRef, type BrowserUsage, type Profile, + type Tags, type BrowserCreateResponse, type BrowserRetrieveResponse, type BrowserUpdateResponse, diff --git a/src/resources/invocations.ts b/src/resources/invocations.ts index 104fa849..ce731966 100644 --- a/src/resources/invocations.ts +++ b/src/resources/invocations.ts @@ -517,6 +517,12 @@ export namespace InvocationListBrowsersResponse { */ start_url?: string; + /** + * User-defined key-value tags that were set on this browser session, if any. + * Echoed back when present. + */ + tags?: BrowsersAPI.Tags; + /** * Active telemetry configuration for the session, if any. */ diff --git a/tests/api-resources/browsers/browsers.test.ts b/tests/api-resources/browsers/browsers.test.ts index 9428311e..0d2e506e 100644 --- a/tests/api-resources/browsers/browsers.test.ts +++ b/tests/api-resources/browsers/browsers.test.ts @@ -41,6 +41,7 @@ describe('resource browsers', () => { proxy_id: 'proxy_id', start_url: 'https://example.com', stealth: true, + tags: { team: 'backend', env: 'staging' }, telemetry: { browser: { console: { enabled: true }, @@ -121,6 +122,7 @@ describe('resource browsers', () => { offset: 0, query: 'query', status: 'active', + tags: { foo: 'string' }, }, { path: '/_stainless_unknown_path' }, ), diff --git a/tests/qs/empty-keys-cases.ts b/tests/qs/empty-keys-cases.ts new file mode 100644 index 00000000..ea2c1b0a --- /dev/null +++ b/tests/qs/empty-keys-cases.ts @@ -0,0 +1,271 @@ +export const empty_test_cases = [ + { + input: '&', + with_empty_keys: {}, + stringify_output: { + brackets: '', + indices: '', + repeat: '', + }, + no_empty_keys: {}, + }, + { + input: '&&', + with_empty_keys: {}, + stringify_output: { + brackets: '', + indices: '', + repeat: '', + }, + no_empty_keys: {}, + }, + { + input: '&=', + with_empty_keys: { '': '' }, + stringify_output: { + brackets: '=', + indices: '=', + repeat: '=', + }, + no_empty_keys: {}, + }, + { + input: '&=&', + with_empty_keys: { '': '' }, + stringify_output: { + brackets: '=', + indices: '=', + repeat: '=', + }, + no_empty_keys: {}, + }, + { + input: '&=&=', + with_empty_keys: { '': ['', ''] }, + stringify_output: { + brackets: '[]=&[]=', + indices: '[0]=&[1]=', + repeat: '=&=', + }, + no_empty_keys: {}, + }, + { + input: '&=&=&', + with_empty_keys: { '': ['', ''] }, + stringify_output: { + brackets: '[]=&[]=', + indices: '[0]=&[1]=', + repeat: '=&=', + }, + no_empty_keys: {}, + }, + { + input: '=', + with_empty_keys: { '': '' }, + no_empty_keys: {}, + stringify_output: { + brackets: '=', + indices: '=', + repeat: '=', + }, + }, + { + input: '=&', + with_empty_keys: { '': '' }, + stringify_output: { + brackets: '=', + indices: '=', + repeat: '=', + }, + no_empty_keys: {}, + }, + { + input: '=&&&', + with_empty_keys: { '': '' }, + stringify_output: { + brackets: '=', + indices: '=', + repeat: '=', + }, + no_empty_keys: {}, + }, + { + input: '=&=&=&', + with_empty_keys: { '': ['', '', ''] }, + stringify_output: { + brackets: '[]=&[]=&[]=', + indices: '[0]=&[1]=&[2]=', + repeat: '=&=&=', + }, + no_empty_keys: {}, + }, + { + input: '=&a[]=b&a[1]=c', + with_empty_keys: { '': '', a: ['b', 'c'] }, + stringify_output: { + brackets: '=&a[]=b&a[]=c', + indices: '=&a[0]=b&a[1]=c', + repeat: '=&a=b&a=c', + }, + no_empty_keys: { a: ['b', 'c'] }, + }, + { + input: '=a', + with_empty_keys: { '': 'a' }, + no_empty_keys: {}, + stringify_output: { + brackets: '=a', + indices: '=a', + repeat: '=a', + }, + }, + { + input: 'a==a', + with_empty_keys: { a: '=a' }, + no_empty_keys: { a: '=a' }, + stringify_output: { + brackets: 'a==a', + indices: 'a==a', + repeat: 'a==a', + }, + }, + { + input: '=&a[]=b', + with_empty_keys: { '': '', a: ['b'] }, + stringify_output: { + brackets: '=&a[]=b', + indices: '=&a[0]=b', + repeat: '=&a=b', + }, + no_empty_keys: { a: ['b'] }, + }, + { + input: '=&a[]=b&a[]=c&a[2]=d', + with_empty_keys: { '': '', a: ['b', 'c', 'd'] }, + stringify_output: { + brackets: '=&a[]=b&a[]=c&a[]=d', + indices: '=&a[0]=b&a[1]=c&a[2]=d', + repeat: '=&a=b&a=c&a=d', + }, + no_empty_keys: { a: ['b', 'c', 'd'] }, + }, + { + input: '=a&=b', + with_empty_keys: { '': ['a', 'b'] }, + stringify_output: { + brackets: '[]=a&[]=b', + indices: '[0]=a&[1]=b', + repeat: '=a&=b', + }, + no_empty_keys: {}, + }, + { + input: '=a&foo=b', + with_empty_keys: { '': 'a', foo: 'b' }, + no_empty_keys: { foo: 'b' }, + stringify_output: { + brackets: '=a&foo=b', + indices: '=a&foo=b', + repeat: '=a&foo=b', + }, + }, + { + input: 'a[]=b&a=c&=', + with_empty_keys: { '': '', a: ['b', 'c'] }, + stringify_output: { + brackets: '=&a[]=b&a[]=c', + indices: '=&a[0]=b&a[1]=c', + repeat: '=&a=b&a=c', + }, + no_empty_keys: { a: ['b', 'c'] }, + }, + { + input: 'a[]=b&a=c&=', + with_empty_keys: { '': '', a: ['b', 'c'] }, + stringify_output: { + brackets: '=&a[]=b&a[]=c', + indices: '=&a[0]=b&a[1]=c', + repeat: '=&a=b&a=c', + }, + no_empty_keys: { a: ['b', 'c'] }, + }, + { + input: 'a[0]=b&a=c&=', + with_empty_keys: { '': '', a: ['b', 'c'] }, + stringify_output: { + brackets: '=&a[]=b&a[]=c', + indices: '=&a[0]=b&a[1]=c', + repeat: '=&a=b&a=c', + }, + no_empty_keys: { a: ['b', 'c'] }, + }, + { + input: 'a=b&a[]=c&=', + with_empty_keys: { '': '', a: ['b', 'c'] }, + stringify_output: { + brackets: '=&a[]=b&a[]=c', + indices: '=&a[0]=b&a[1]=c', + repeat: '=&a=b&a=c', + }, + no_empty_keys: { a: ['b', 'c'] }, + }, + { + input: 'a=b&a[0]=c&=', + with_empty_keys: { '': '', a: ['b', 'c'] }, + stringify_output: { + brackets: '=&a[]=b&a[]=c', + indices: '=&a[0]=b&a[1]=c', + repeat: '=&a=b&a=c', + }, + no_empty_keys: { a: ['b', 'c'] }, + }, + { + input: '[]=a&[]=b& []=1', + with_empty_keys: { '': ['a', 'b'], ' ': ['1'] }, + stringify_output: { + brackets: '[]=a&[]=b& []=1', + indices: '[0]=a&[1]=b& [0]=1', + repeat: '=a&=b& =1', + }, + no_empty_keys: { 0: 'a', 1: 'b', ' ': ['1'] }, + }, + { + input: '[0]=a&[1]=b&a[0]=1&a[1]=2', + with_empty_keys: { '': ['a', 'b'], a: ['1', '2'] }, + no_empty_keys: { 0: 'a', 1: 'b', a: ['1', '2'] }, + stringify_output: { + brackets: '[]=a&[]=b&a[]=1&a[]=2', + indices: '[0]=a&[1]=b&a[0]=1&a[1]=2', + repeat: '=a&=b&a=1&a=2', + }, + }, + { + input: '[deep]=a&[deep]=2', + with_empty_keys: { '': { deep: ['a', '2'] } }, + stringify_output: { + brackets: '[deep][]=a&[deep][]=2', + indices: '[deep][0]=a&[deep][1]=2', + repeat: '[deep]=a&[deep]=2', + }, + no_empty_keys: { deep: ['a', '2'] }, + }, + { + input: '%5B0%5D=a&%5B1%5D=b', + with_empty_keys: { '': ['a', 'b'] }, + stringify_output: { + brackets: '[]=a&[]=b', + indices: '[0]=a&[1]=b', + repeat: '=a&=b', + }, + no_empty_keys: { 0: 'a', 1: 'b' }, + }, +] satisfies { + input: string; + with_empty_keys: Record; + stringify_output: { + brackets: string; + indices: string; + repeat: string; + }; + no_empty_keys: Record; +}[]; diff --git a/tests/qs/stringify.test.ts b/tests/qs/stringify.test.ts new file mode 100644 index 00000000..391155e1 --- /dev/null +++ b/tests/qs/stringify.test.ts @@ -0,0 +1,2232 @@ +import iconv from 'iconv-lite'; +import { stringify } from '@onkernel/sdk/internal/qs'; +import { encode } from '@onkernel/sdk/internal/qs/utils'; +import { StringifyOptions } from '@onkernel/sdk/internal/qs/types'; +import { empty_test_cases } from './empty-keys-cases'; +import assert from 'assert'; + +describe('stringify()', function () { + test('stringifies a querystring object', function () { + expect(stringify({ a: 'b' })).toBe('a=b'); + expect(stringify({ a: 1 })).toBe('a=1'); + expect(stringify({ a: 1, b: 2 })).toBe('a=1&b=2'); + expect(stringify({ a: 'A_Z' })).toBe('a=A_Z'); + expect(stringify({ a: '€' })).toBe('a=%E2%82%AC'); + expect(stringify({ a: '' })).toBe('a=%EE%80%80'); + expect(stringify({ a: 'א' })).toBe('a=%D7%90'); + expect(stringify({ a: '𐐷' })).toBe('a=%F0%90%90%B7'); + }); + + test('stringifies falsy values', function () { + expect(stringify(undefined)).toBe(''); + expect(stringify(null)).toBe(''); + expect(stringify(null, { strictNullHandling: true })).toBe(''); + expect(stringify(false)).toBe(''); + expect(stringify(0)).toBe(''); + }); + + test('stringifies symbols', function () { + expect(stringify(Symbol.iterator)).toBe(''); + expect(stringify([Symbol.iterator])).toBe('0=Symbol%28Symbol.iterator%29'); + expect(stringify({ a: Symbol.iterator })).toBe('a=Symbol%28Symbol.iterator%29'); + expect(stringify({ a: [Symbol.iterator] }, { encodeValuesOnly: true, arrayFormat: 'brackets' })).toBe( + 'a[]=Symbol%28Symbol.iterator%29', + ); + }); + + test('stringifies bigints', function () { + var three = BigInt(3); + // @ts-expect-error + var encodeWithN = function (value, defaultEncoder, charset) { + var result = defaultEncoder(value, defaultEncoder, charset); + return typeof value === 'bigint' ? result + 'n' : result; + }; + + expect(stringify(three)).toBe(''); + expect(stringify([three])).toBe('0=3'); + expect(stringify([three], { encoder: encodeWithN })).toBe('0=3n'); + expect(stringify({ a: three })).toBe('a=3'); + expect(stringify({ a: three }, { encoder: encodeWithN })).toBe('a=3n'); + expect(stringify({ a: [three] }, { encodeValuesOnly: true, arrayFormat: 'brackets' })).toBe('a[]=3'); + expect( + stringify({ a: [three] }, { encodeValuesOnly: true, encoder: encodeWithN, arrayFormat: 'brackets' }), + ).toBe('a[]=3n'); + }); + + test('encodes dot in key of object when encodeDotInKeys and allowDots is provided', function () { + expect( + stringify({ 'name.obj': { first: 'John', last: 'Doe' } }, { allowDots: false, encodeDotInKeys: false }), + ).toBe('name.obj%5Bfirst%5D=John&name.obj%5Blast%5D=Doe'); + expect( + stringify({ 'name.obj': { first: 'John', last: 'Doe' } }, { allowDots: true, encodeDotInKeys: false }), + ).toBe('name.obj.first=John&name.obj.last=Doe'); + expect( + stringify({ 'name.obj': { first: 'John', last: 'Doe' } }, { allowDots: false, encodeDotInKeys: true }), + ).toBe('name%252Eobj%5Bfirst%5D=John&name%252Eobj%5Blast%5D=Doe'); + expect( + stringify({ 'name.obj': { first: 'John', last: 'Doe' } }, { allowDots: true, encodeDotInKeys: true }), + ).toBe('name%252Eobj.first=John&name%252Eobj.last=Doe'); + + // st.equal( + // stringify( + // { 'name.obj.subobject': { 'first.godly.name': 'John', last: 'Doe' } }, + // { allowDots: false, encodeDotInKeys: false }, + // ), + // 'name.obj.subobject%5Bfirst.godly.name%5D=John&name.obj.subobject%5Blast%5D=Doe', + // 'with allowDots false and encodeDotInKeys false', + // ); + // st.equal( + // stringify( + // { 'name.obj.subobject': { 'first.godly.name': 'John', last: 'Doe' } }, + // { allowDots: true, encodeDotInKeys: false }, + // ), + // 'name.obj.subobject.first.godly.name=John&name.obj.subobject.last=Doe', + // 'with allowDots false and encodeDotInKeys false', + // ); + // st.equal( + // stringify( + // { 'name.obj.subobject': { 'first.godly.name': 'John', last: 'Doe' } }, + // { allowDots: false, encodeDotInKeys: true }, + // ), + // 'name%252Eobj%252Esubobject%5Bfirst.godly.name%5D=John&name%252Eobj%252Esubobject%5Blast%5D=Doe', + // 'with allowDots false and encodeDotInKeys true', + // ); + // st.equal( + // stringify( + // { 'name.obj.subobject': { 'first.godly.name': 'John', last: 'Doe' } }, + // { allowDots: true, encodeDotInKeys: true }, + // ), + // 'name%252Eobj%252Esubobject.first%252Egodly%252Ename=John&name%252Eobj%252Esubobject.last=Doe', + // 'with allowDots true and encodeDotInKeys true', + // ); + expect( + stringify( + { 'name.obj.subobject': { 'first.godly.name': 'John', last: 'Doe' } }, + { allowDots: false, encodeDotInKeys: false }, + ), + ).toBe('name.obj.subobject%5Bfirst.godly.name%5D=John&name.obj.subobject%5Blast%5D=Doe'); + expect( + stringify( + { 'name.obj.subobject': { 'first.godly.name': 'John', last: 'Doe' } }, + { allowDots: true, encodeDotInKeys: false }, + ), + ).toBe('name.obj.subobject.first.godly.name=John&name.obj.subobject.last=Doe'); + expect( + stringify( + { 'name.obj.subobject': { 'first.godly.name': 'John', last: 'Doe' } }, + { allowDots: false, encodeDotInKeys: true }, + ), + ).toBe('name%252Eobj%252Esubobject%5Bfirst.godly.name%5D=John&name%252Eobj%252Esubobject%5Blast%5D=Doe'); + expect( + stringify( + { 'name.obj.subobject': { 'first.godly.name': 'John', last: 'Doe' } }, + { allowDots: true, encodeDotInKeys: true }, + ), + ).toBe('name%252Eobj%252Esubobject.first%252Egodly%252Ename=John&name%252Eobj%252Esubobject.last=Doe'); + }); + + test('should encode dot in key of object, and automatically set allowDots to `true` when encodeDotInKeys is true and allowDots in undefined', function () { + // st.equal( + // stringify( + // { 'name.obj.subobject': { 'first.godly.name': 'John', last: 'Doe' } }, + // { encodeDotInKeys: true }, + // ), + // 'name%252Eobj%252Esubobject.first%252Egodly%252Ename=John&name%252Eobj%252Esubobject.last=Doe', + // 'with allowDots undefined and encodeDotInKeys true', + // ); + expect( + stringify( + { 'name.obj.subobject': { 'first.godly.name': 'John', last: 'Doe' } }, + { encodeDotInKeys: true }, + ), + ).toBe('name%252Eobj%252Esubobject.first%252Egodly%252Ename=John&name%252Eobj%252Esubobject.last=Doe'); + }); + + test('should encode dot in key of object when encodeDotInKeys and allowDots is provided, and nothing else when encodeValuesOnly is provided', function () { + // st.equal( + // stringify( + // { 'name.obj': { first: 'John', last: 'Doe' } }, + // { + // encodeDotInKeys: true, + // allowDots: true, + // encodeValuesOnly: true, + // }, + // ), + // 'name%2Eobj.first=John&name%2Eobj.last=Doe', + // ); + expect( + stringify( + { 'name.obj': { first: 'John', last: 'Doe' } }, + { + encodeDotInKeys: true, + allowDots: true, + encodeValuesOnly: true, + }, + ), + ).toBe('name%2Eobj.first=John&name%2Eobj.last=Doe'); + + // st.equal( + // stringify( + // { 'name.obj.subobject': { 'first.godly.name': 'John', last: 'Doe' } }, + // { allowDots: true, encodeDotInKeys: true, encodeValuesOnly: true }, + // ), + // 'name%2Eobj%2Esubobject.first%2Egodly%2Ename=John&name%2Eobj%2Esubobject.last=Doe', + // ); + expect( + stringify( + { 'name.obj.subobject': { 'first.godly.name': 'John', last: 'Doe' } }, + { allowDots: true, encodeDotInKeys: true, encodeValuesOnly: true }, + ), + ).toBe('name%2Eobj%2Esubobject.first%2Egodly%2Ename=John&name%2Eobj%2Esubobject.last=Doe'); + }); + + test('throws when `commaRoundTrip` is not a boolean', function () { + // st['throws']( + // function () { + // stringify({}, { commaRoundTrip: 'not a boolean' }); + // }, + // TypeError, + // 'throws when `commaRoundTrip` is not a boolean', + // ); + expect(() => { + // @ts-expect-error + stringify({}, { commaRoundTrip: 'not a boolean' }); + }).toThrow(TypeError); + }); + + test('throws when `encodeDotInKeys` is not a boolean', function () { + // st['throws'](function () { + // stringify({ a: [], b: 'zz' }, { encodeDotInKeys: 'foobar' }); + // }, TypeError); + expect(() => { + // @ts-expect-error + stringify({ a: [], b: 'zz' }, { encodeDotInKeys: 'foobar' }); + }).toThrow(TypeError); + + // st['throws'](function () { + // stringify({ a: [], b: 'zz' }, { encodeDotInKeys: 0 }); + // }, TypeError); + expect(() => { + // @ts-expect-error + stringify({ a: [], b: 'zz' }, { encodeDotInKeys: 0 }); + }).toThrow(TypeError); + + // st['throws'](function () { + // stringify({ a: [], b: 'zz' }, { encodeDotInKeys: NaN }); + // }, TypeError); + expect(() => { + // @ts-expect-error + stringify({ a: [], b: 'zz' }, { encodeDotInKeys: NaN }); + }).toThrow(TypeError); + + // st['throws'](function () { + // stringify({ a: [], b: 'zz' }, { encodeDotInKeys: null }); + // }, TypeError); + expect(() => { + // @ts-expect-error + stringify({ a: [], b: 'zz' }, { encodeDotInKeys: null }); + }).toThrow(TypeError); + }); + + test('adds query prefix', function () { + // st.equal(stringify({ a: 'b' }, { addQueryPrefix: true }), '?a=b'); + expect(stringify({ a: 'b' }, { addQueryPrefix: true })).toBe('?a=b'); + }); + + test('with query prefix, outputs blank string given an empty object', function () { + // st.equal(stringify({}, { addQueryPrefix: true }), ''); + expect(stringify({}, { addQueryPrefix: true })).toBe(''); + }); + + test('stringifies nested falsy values', function () { + // st.equal(stringify({ a: { b: { c: null } } }), 'a%5Bb%5D%5Bc%5D='); + // st.equal( + // stringify({ a: { b: { c: null } } }, { strictNullHandling: true }), + // 'a%5Bb%5D%5Bc%5D', + // ); + // st.equal(stringify({ a: { b: { c: false } } }), 'a%5Bb%5D%5Bc%5D=false'); + expect(stringify({ a: { b: { c: null } } })).toBe('a%5Bb%5D%5Bc%5D='); + expect(stringify({ a: { b: { c: null } } }, { strictNullHandling: true })).toBe('a%5Bb%5D%5Bc%5D'); + expect(stringify({ a: { b: { c: false } } })).toBe('a%5Bb%5D%5Bc%5D=false'); + }); + + test('stringifies a nested object', function () { + // st.equal(stringify({ a: { b: 'c' } }), 'a%5Bb%5D=c'); + // st.equal(stringify({ a: { b: { c: { d: 'e' } } } }), 'a%5Bb%5D%5Bc%5D%5Bd%5D=e'); + expect(stringify({ a: { b: 'c' } })).toBe('a%5Bb%5D=c'); + expect(stringify({ a: { b: { c: { d: 'e' } } } })).toBe('a%5Bb%5D%5Bc%5D%5Bd%5D=e'); + }); + + test('`allowDots` option: stringifies a nested object with dots notation', function () { + // st.equal(stringify({ a: { b: 'c' } }, { allowDots: true }), 'a.b=c'); + // st.equal(stringify({ a: { b: { c: { d: 'e' } } } }, { allowDots: true }), 'a.b.c.d=e'); + expect(stringify({ a: { b: 'c' } }, { allowDots: true })).toBe('a.b=c'); + expect(stringify({ a: { b: { c: { d: 'e' } } } }, { allowDots: true })).toBe('a.b.c.d=e'); + }); + + test('stringifies an array value', function () { + // st.equal( + // stringify({ a: ['b', 'c', 'd'] }, { arrayFormat: 'indices' }), + // 'a%5B0%5D=b&a%5B1%5D=c&a%5B2%5D=d', + // 'indices => indices', + // ); + // st.equal( + // stringify({ a: ['b', 'c', 'd'] }, { arrayFormat: 'brackets' }), + // 'a%5B%5D=b&a%5B%5D=c&a%5B%5D=d', + // 'brackets => brackets', + // ); + // st.equal( + // stringify({ a: ['b', 'c', 'd'] }, { arrayFormat: 'comma' }), + // 'a=b%2Cc%2Cd', + // 'comma => comma', + // ); + // st.equal( + // stringify({ a: ['b', 'c', 'd'] }, { arrayFormat: 'comma', commaRoundTrip: true }), + // 'a=b%2Cc%2Cd', + // 'comma round trip => comma', + // ); + // st.equal( + // stringify({ a: ['b', 'c', 'd'] }), + // 'a%5B0%5D=b&a%5B1%5D=c&a%5B2%5D=d', + // 'default => indices', + // ); + expect(stringify({ a: ['b', 'c', 'd'] }, { arrayFormat: 'indices' })).toBe( + 'a%5B0%5D=b&a%5B1%5D=c&a%5B2%5D=d', + ); + expect(stringify({ a: ['b', 'c', 'd'] }, { arrayFormat: 'brackets' })).toBe( + 'a%5B%5D=b&a%5B%5D=c&a%5B%5D=d', + ); + expect(stringify({ a: ['b', 'c', 'd'] }, { arrayFormat: 'comma' })).toBe('a=b%2Cc%2Cd'); + expect(stringify({ a: ['b', 'c', 'd'] }, { arrayFormat: 'comma', commaRoundTrip: true })).toBe( + 'a=b%2Cc%2Cd', + ); + expect(stringify({ a: ['b', 'c', 'd'] })).toBe('a%5B0%5D=b&a%5B1%5D=c&a%5B2%5D=d'); + }); + + test('`skipNulls` option', function () { + // st.equal( + // stringify({ a: 'b', c: null }, { skipNulls: true }), + // 'a=b', + // 'omits nulls when asked', + // ); + expect(stringify({ a: 'b', c: null }, { skipNulls: true })).toBe('a=b'); + + // st.equal( + // stringify({ a: { b: 'c', d: null } }, { skipNulls: true }), + // 'a%5Bb%5D=c', + // 'omits nested nulls when asked', + // ); + expect(stringify({ a: { b: 'c', d: null } }, { skipNulls: true })).toBe('a%5Bb%5D=c'); + }); + + test('omits array indices when asked', function () { + // st.equal(stringify({ a: ['b', 'c', 'd'] }, { indices: false }), 'a=b&a=c&a=d'); + expect(stringify({ a: ['b', 'c', 'd'] }, { indices: false })).toBe('a=b&a=c&a=d'); + }); + + test('omits object key/value pair when value is empty array', function () { + // st.equal(stringify({ a: [], b: 'zz' }), 'b=zz'); + expect(stringify({ a: [], b: 'zz' })).toBe('b=zz'); + }); + + test('should not omit object key/value pair when value is empty array and when asked', function () { + // st.equal(stringify({ a: [], b: 'zz' }), 'b=zz'); + // st.equal(stringify({ a: [], b: 'zz' }, { allowEmptyArrays: false }), 'b=zz'); + // st.equal(stringify({ a: [], b: 'zz' }, { allowEmptyArrays: true }), 'a[]&b=zz'); + expect(stringify({ a: [], b: 'zz' })).toBe('b=zz'); + expect(stringify({ a: [], b: 'zz' }, { allowEmptyArrays: false })).toBe('b=zz'); + expect(stringify({ a: [], b: 'zz' }, { allowEmptyArrays: true })).toBe('a[]&b=zz'); + }); + + test('should throw when allowEmptyArrays is not of type boolean', function () { + // st['throws'](function () { + // stringify({ a: [], b: 'zz' }, { allowEmptyArrays: 'foobar' }); + // }, TypeError); + expect(() => { + // @ts-expect-error + stringify({ a: [], b: 'zz' }, { allowEmptyArrays: 'foobar' }); + }).toThrow(TypeError); + + // st['throws'](function () { + // stringify({ a: [], b: 'zz' }, { allowEmptyArrays: 0 }); + // }, TypeError); + expect(() => { + // @ts-expect-error + stringify({ a: [], b: 'zz' }, { allowEmptyArrays: 0 }); + }).toThrow(TypeError); + + // st['throws'](function () { + // stringify({ a: [], b: 'zz' }, { allowEmptyArrays: NaN }); + // }, TypeError); + expect(() => { + // @ts-expect-error + stringify({ a: [], b: 'zz' }, { allowEmptyArrays: NaN }); + }).toThrow(TypeError); + + // st['throws'](function () { + // stringify({ a: [], b: 'zz' }, { allowEmptyArrays: null }); + // }, TypeError); + expect(() => { + // @ts-expect-error + stringify({ a: [], b: 'zz' }, { allowEmptyArrays: null }); + }).toThrow(TypeError); + }); + + test('allowEmptyArrays + strictNullHandling', function () { + // st.equal( + // stringify({ testEmptyArray: [] }, { strictNullHandling: true, allowEmptyArrays: true }), + // 'testEmptyArray[]', + // ); + expect(stringify({ testEmptyArray: [] }, { strictNullHandling: true, allowEmptyArrays: true })).toBe( + 'testEmptyArray[]', + ); + }); + + describe('stringifies an array value with one item vs multiple items', function () { + test('non-array item', function () { + // s2t.equal( + // stringify({ a: 'c' }, { encodeValuesOnly: true, arrayFormat: 'indices' }), + // 'a=c', + // ); + // s2t.equal( + // stringify({ a: 'c' }, { encodeValuesOnly: true, arrayFormat: 'brackets' }), + // 'a=c', + // ); + // s2t.equal(stringify({ a: 'c' }, { encodeValuesOnly: true, arrayFormat: 'comma' }), 'a=c'); + // s2t.equal(stringify({ a: 'c' }, { encodeValuesOnly: true }), 'a=c'); + expect(stringify({ a: 'c' }, { encodeValuesOnly: true, arrayFormat: 'indices' })).toBe('a=c'); + expect(stringify({ a: 'c' }, { encodeValuesOnly: true, arrayFormat: 'brackets' })).toBe('a=c'); + expect(stringify({ a: 'c' }, { encodeValuesOnly: true, arrayFormat: 'comma' })).toBe('a=c'); + expect(stringify({ a: 'c' }, { encodeValuesOnly: true })).toBe('a=c'); + }); + + test('array with a single item', function () { + // s2t.equal( + // stringify({ a: ['c'] }, { encodeValuesOnly: true, arrayFormat: 'indices' }), + // 'a[0]=c', + // ); + // s2t.equal( + // stringify({ a: ['c'] }, { encodeValuesOnly: true, arrayFormat: 'brackets' }), + // 'a[]=c', + // ); + // s2t.equal( + // stringify({ a: ['c'] }, { encodeValuesOnly: true, arrayFormat: 'comma' }), + // 'a=c', + // ); + // s2t.equal( + // stringify( + // { a: ['c'] }, + // { encodeValuesOnly: true, arrayFormat: 'comma', commaRoundTrip: true }, + // ), + // 'a[]=c', + // ); // so it parses back as an array + // s2t.equal(stringify({ a: ['c'] }, { encodeValuesOnly: true }), 'a[0]=c'); + expect(stringify({ a: ['c'] }, { encodeValuesOnly: true, arrayFormat: 'indices' })).toBe('a[0]=c'); + expect(stringify({ a: ['c'] }, { encodeValuesOnly: true, arrayFormat: 'brackets' })).toBe('a[]=c'); + expect(stringify({ a: ['c'] }, { encodeValuesOnly: true, arrayFormat: 'comma' })).toBe('a=c'); + expect( + stringify({ a: ['c'] }, { encodeValuesOnly: true, arrayFormat: 'comma', commaRoundTrip: true }), + ).toBe('a[]=c'); + expect(stringify({ a: ['c'] }, { encodeValuesOnly: true })).toBe('a[0]=c'); + }); + + test('array with multiple items', function () { + // s2t.equal( + // stringify({ a: ['c', 'd'] }, { encodeValuesOnly: true, arrayFormat: 'indices' }), + // 'a[0]=c&a[1]=d', + // ); + // s2t.equal( + // stringify({ a: ['c', 'd'] }, { encodeValuesOnly: true, arrayFormat: 'brackets' }), + // 'a[]=c&a[]=d', + // ); + // s2t.equal( + // stringify({ a: ['c', 'd'] }, { encodeValuesOnly: true, arrayFormat: 'comma' }), + // 'a=c,d', + // ); + // s2t.equal( + // stringify( + // { a: ['c', 'd'] }, + // { encodeValuesOnly: true, arrayFormat: 'comma', commaRoundTrip: true }, + // ), + // 'a=c,d', + // ); + // s2t.equal(stringify({ a: ['c', 'd'] }, { encodeValuesOnly: true }), 'a[0]=c&a[1]=d'); + expect(stringify({ a: ['c', 'd'] }, { encodeValuesOnly: true, arrayFormat: 'indices' })).toBe( + 'a[0]=c&a[1]=d', + ); + expect(stringify({ a: ['c', 'd'] }, { encodeValuesOnly: true, arrayFormat: 'brackets' })).toBe( + 'a[]=c&a[]=d', + ); + expect(stringify({ a: ['c', 'd'] }, { encodeValuesOnly: true, arrayFormat: 'comma' })).toBe('a=c,d'); + expect( + stringify({ a: ['c', 'd'] }, { encodeValuesOnly: true, arrayFormat: 'comma', commaRoundTrip: true }), + ).toBe('a=c,d'); + expect(stringify({ a: ['c', 'd'] }, { encodeValuesOnly: true })).toBe('a[0]=c&a[1]=d'); + }); + + test('array with multiple items with a comma inside', function () { + // s2t.equal( + // stringify({ a: ['c,d', 'e'] }, { encodeValuesOnly: true, arrayFormat: 'comma' }), + // 'a=c%2Cd,e', + // ); + // s2t.equal(stringify({ a: ['c,d', 'e'] }, { arrayFormat: 'comma' }), 'a=c%2Cd%2Ce'); + expect(stringify({ a: ['c,d', 'e'] }, { encodeValuesOnly: true, arrayFormat: 'comma' })).toBe( + 'a=c%2Cd,e', + ); + expect(stringify({ a: ['c,d', 'e'] }, { arrayFormat: 'comma' })).toBe('a=c%2Cd%2Ce'); + + // s2t.equal( + // stringify( + // { a: ['c,d', 'e'] }, + // { encodeValuesOnly: true, arrayFormat: 'comma', commaRoundTrip: true }, + // ), + // 'a=c%2Cd,e', + // ); + // s2t.equal( + // stringify({ a: ['c,d', 'e'] }, { arrayFormat: 'comma', commaRoundTrip: true }), + // 'a=c%2Cd%2Ce', + // ); + expect( + stringify( + { a: ['c,d', 'e'] }, + { encodeValuesOnly: true, arrayFormat: 'comma', commaRoundTrip: true }, + ), + ).toBe('a=c%2Cd,e'); + expect(stringify({ a: ['c,d', 'e'] }, { arrayFormat: 'comma', commaRoundTrip: true })).toBe( + 'a=c%2Cd%2Ce', + ); + }); + }); + + test('stringifies a nested array value', function () { + expect(stringify({ a: { b: ['c', 'd'] } }, { encodeValuesOnly: true, arrayFormat: 'indices' })).toBe( + 'a[b][0]=c&a[b][1]=d', + ); + expect(stringify({ a: { b: ['c', 'd'] } }, { encodeValuesOnly: true, arrayFormat: 'brackets' })).toBe( + 'a[b][]=c&a[b][]=d', + ); + expect(stringify({ a: { b: ['c', 'd'] } }, { encodeValuesOnly: true, arrayFormat: 'comma' })).toBe( + 'a[b]=c,d', + ); + expect(stringify({ a: { b: ['c', 'd'] } }, { encodeValuesOnly: true })).toBe('a[b][0]=c&a[b][1]=d'); + }); + + test('stringifies comma and empty array values', function () { + // st.equal( + // stringify({ a: [',', '', 'c,d%'] }, { encode: false, arrayFormat: 'indices' }), + // 'a[0]=,&a[1]=&a[2]=c,d%', + // ); + // st.equal( + // stringify({ a: [',', '', 'c,d%'] }, { encode: false, arrayFormat: 'brackets' }), + // 'a[]=,&a[]=&a[]=c,d%', + // ); + // st.equal( + // stringify({ a: [',', '', 'c,d%'] }, { encode: false, arrayFormat: 'comma' }), + // 'a=,,,c,d%', + // ); + // st.equal( + // stringify({ a: [',', '', 'c,d%'] }, { encode: false, arrayFormat: 'repeat' }), + // 'a=,&a=&a=c,d%', + // ); + expect(stringify({ a: [',', '', 'c,d%'] }, { encode: false, arrayFormat: 'indices' })).toBe( + 'a[0]=,&a[1]=&a[2]=c,d%', + ); + expect(stringify({ a: [',', '', 'c,d%'] }, { encode: false, arrayFormat: 'brackets' })).toBe( + 'a[]=,&a[]=&a[]=c,d%', + ); + expect(stringify({ a: [',', '', 'c,d%'] }, { encode: false, arrayFormat: 'comma' })).toBe('a=,,,c,d%'); + expect(stringify({ a: [',', '', 'c,d%'] }, { encode: false, arrayFormat: 'repeat' })).toBe( + 'a=,&a=&a=c,d%', + ); + + // st.equal( + // stringify( + // { a: [',', '', 'c,d%'] }, + // { encode: true, encodeValuesOnly: true, arrayFormat: 'indices' }, + // ), + // 'a[0]=%2C&a[1]=&a[2]=c%2Cd%25', + // ); + // st.equal( + // stringify( + // { a: [',', '', 'c,d%'] }, + // { encode: true, encodeValuesOnly: true, arrayFormat: 'brackets' }, + // ), + // 'a[]=%2C&a[]=&a[]=c%2Cd%25', + // ); + // st.equal( + // stringify( + // { a: [',', '', 'c,d%'] }, + // { encode: true, encodeValuesOnly: true, arrayFormat: 'comma' }, + // ), + // 'a=%2C,,c%2Cd%25', + // ); + // st.equal( + // stringify( + // { a: [',', '', 'c,d%'] }, + // { encode: true, encodeValuesOnly: true, arrayFormat: 'repeat' }, + // ), + // 'a=%2C&a=&a=c%2Cd%25', + // ); + expect( + stringify({ a: [',', '', 'c,d%'] }, { encode: true, encodeValuesOnly: false, arrayFormat: 'indices' }), + ).toBe('a%5B0%5D=%2C&a%5B1%5D=&a%5B2%5D=c%2Cd%25'); + expect( + stringify({ a: [',', '', 'c,d%'] }, { encode: true, encodeValuesOnly: true, arrayFormat: 'brackets' }), + ).toBe('a[]=%2C&a[]=&a[]=c%2Cd%25'); + expect( + stringify({ a: [',', '', 'c,d%'] }, { encode: true, encodeValuesOnly: false, arrayFormat: 'comma' }), + ).toBe('a=%2C%2C%2Cc%2Cd%25'); + expect( + stringify({ a: [',', '', 'c,d%'] }, { encode: true, encodeValuesOnly: false, arrayFormat: 'repeat' }), + ).toBe('a=%2C&a=&a=c%2Cd%25'); + + // st.equal( + // stringify( + // { a: [',', '', 'c,d%'] }, + // { encode: true, encodeValuesOnly: false, arrayFormat: 'indices' }, + // ), + // 'a%5B0%5D=%2C&a%5B1%5D=&a%5B2%5D=c%2Cd%25', + // ); + // st.equal( + // stringify( + // { a: [',', '', 'c,d%'] }, + // { encode: true, encodeValuesOnly: false, arrayFormat: 'brackets' }, + // ), + // 'a%5B%5D=%2C&a%5B%5D=&a%5B%5D=c%2Cd%25', + // ); + // st.equal( + // stringify( + // { a: [',', '', 'c,d%'] }, + // { encode: true, encodeValuesOnly: false, arrayFormat: 'comma' }, + // ), + // 'a=%2C%2C%2Cc%2Cd%25', + // ); + // st.equal( + // stringify( + // { a: [',', '', 'c,d%'] }, + // { encode: true, encodeValuesOnly: false, arrayFormat: 'repeat' }, + // ), + // 'a=%2C&a=&a=c%2Cd%25', + // ); + expect( + stringify({ a: [',', '', 'c,d%'] }, { encode: true, encodeValuesOnly: false, arrayFormat: 'repeat' }), + ).toBe('a=%2C&a=&a=c%2Cd%25'); + expect( + stringify({ a: [',', '', 'c,d%'] }, { encode: true, encodeValuesOnly: false, arrayFormat: 'indices' }), + ).toBe('a%5B0%5D=%2C&a%5B1%5D=&a%5B2%5D=c%2Cd%25'); + expect( + stringify({ a: [',', '', 'c,d%'] }, { encode: true, encodeValuesOnly: true, arrayFormat: 'brackets' }), + ).toBe('a[]=%2C&a[]=&a[]=c%2Cd%25'); + expect( + stringify({ a: [',', '', 'c,d%'] }, { encode: true, encodeValuesOnly: false, arrayFormat: 'comma' }), + ).toBe('a=%2C%2C%2Cc%2Cd%25'); + expect( + stringify({ a: [',', '', 'c,d%'] }, { encode: true, encodeValuesOnly: false, arrayFormat: 'repeat' }), + ).toBe('a=%2C&a=&a=c%2Cd%25'); + }); + + test('stringifies comma and empty non-array values', function () { + // st.equal( + // stringify({ a: ',', b: '', c: 'c,d%' }, { encode: false, arrayFormat: 'indices' }), + // 'a=,&b=&c=c,d%', + // ); + // st.equal( + // stringify({ a: ',', b: '', c: 'c,d%' }, { encode: false, arrayFormat: 'brackets' }), + // 'a=,&b=&c=c,d%', + // ); + // st.equal( + // stringify({ a: ',', b: '', c: 'c,d%' }, { encode: false, arrayFormat: 'comma' }), + // 'a=,&b=&c=c,d%', + // ); + // st.equal( + // stringify({ a: ',', b: '', c: 'c,d%' }, { encode: false, arrayFormat: 'repeat' }), + // 'a=,&b=&c=c,d%', + // ); + expect(stringify({ a: ',', b: '', c: 'c,d%' }, { encode: false, arrayFormat: 'indices' })).toBe( + 'a=,&b=&c=c,d%', + ); + expect(stringify({ a: ',', b: '', c: 'c,d%' }, { encode: false, arrayFormat: 'brackets' })).toBe( + 'a=,&b=&c=c,d%', + ); + + // st.equal( + // stringify( + // { a: ',', b: '', c: 'c,d%' }, + // { encode: true, encodeValuesOnly: true, arrayFormat: 'indices' }, + // ), + // 'a=%2C&b=&c=c%2Cd%25', + // ); + // st.equal( + // stringify( + // { a: ',', b: '', c: 'c,d%' }, + // { encode: true, encodeValuesOnly: true, arrayFormat: 'brackets' }, + // ), + // 'a=%2C&b=&c=c%2Cd%25', + // ); + // st.equal( + // stringify( + // { a: ',', b: '', c: 'c,d%' }, + // { encode: true, encodeValuesOnly: true, arrayFormat: 'comma' }, + // ), + // 'a=%2C&b=&c=c%2Cd%25', + // ); + // st.equal( + // stringify( + // { a: ',', b: '', c: 'c,d%' }, + // { encode: true, encodeValuesOnly: true, arrayFormat: 'repeat' }, + // ), + // 'a=%2C&b=&c=c%2Cd%25', + // ); + expect( + stringify( + { a: ',', b: '', c: 'c,d%' }, + { encode: true, encodeValuesOnly: true, arrayFormat: 'indices' }, + ), + ).toBe('a=%2C&b=&c=c%2Cd%25'); + expect( + stringify( + { a: ',', b: '', c: 'c,d%' }, + { encode: true, encodeValuesOnly: true, arrayFormat: 'brackets' }, + ), + ).toBe('a=%2C&b=&c=c%2Cd%25'); + expect( + stringify({ a: ',', b: '', c: 'c,d%' }, { encode: true, encodeValuesOnly: true, arrayFormat: 'comma' }), + ).toBe('a=%2C&b=&c=c%2Cd%25'); + expect( + stringify( + { a: ',', b: '', c: 'c,d%' }, + { encode: true, encodeValuesOnly: true, arrayFormat: 'repeat' }, + ), + ).toBe('a=%2C&b=&c=c%2Cd%25'); + + // st.equal( + // stringify( + // { a: ',', b: '', c: 'c,d%' }, + // { encode: true, encodeValuesOnly: false, arrayFormat: 'indices' }, + // ), + // 'a=%2C&b=&c=c%2Cd%25', + // ); + // st.equal( + // stringify( + // { a: ',', b: '', c: 'c,d%' }, + // { encode: true, encodeValuesOnly: false, arrayFormat: 'brackets' }, + // ), + // 'a=%2C&b=&c=c%2Cd%25', + // ); + // st.equal( + // stringify( + // { a: ',', b: '', c: 'c,d%' }, + // { encode: true, encodeValuesOnly: false, arrayFormat: 'comma' }, + // ), + // 'a=%2C&b=&c=c%2Cd%25', + // ); + // st.equal( + // stringify( + // { a: ',', b: '', c: 'c,d%' }, + // { encode: true, encodeValuesOnly: false, arrayFormat: 'repeat' }, + // ), + // 'a=%2C&b=&c=c%2Cd%25', + // ); + expect( + stringify( + { a: ',', b: '', c: 'c,d%' }, + { encode: true, encodeValuesOnly: false, arrayFormat: 'indices' }, + ), + ).toBe('a=%2C&b=&c=c%2Cd%25'); + expect( + stringify( + { a: ',', b: '', c: 'c,d%' }, + { encode: true, encodeValuesOnly: false, arrayFormat: 'brackets' }, + ), + ).toBe('a=%2C&b=&c=c%2Cd%25'); + expect( + stringify( + { a: ',', b: '', c: 'c,d%' }, + { encode: true, encodeValuesOnly: false, arrayFormat: 'comma' }, + ), + ).toBe('a=%2C&b=&c=c%2Cd%25'); + expect( + stringify( + { a: ',', b: '', c: 'c,d%' }, + { encode: true, encodeValuesOnly: false, arrayFormat: 'repeat' }, + ), + ).toBe('a=%2C&b=&c=c%2Cd%25'); + }); + + test('stringifies a nested array value with dots notation', function () { + // st.equal( + // stringify( + // { a: { b: ['c', 'd'] } }, + // { allowDots: true, encodeValuesOnly: true, arrayFormat: 'indices' }, + // ), + // 'a.b[0]=c&a.b[1]=d', + // 'indices: stringifies with dots + indices', + // ); + // st.equal( + // stringify( + // { a: { b: ['c', 'd'] } }, + // { allowDots: true, encodeValuesOnly: true, arrayFormat: 'brackets' }, + // ), + // 'a.b[]=c&a.b[]=d', + // 'brackets: stringifies with dots + brackets', + // ); + // st.equal( + // stringify( + // { a: { b: ['c', 'd'] } }, + // { allowDots: true, encodeValuesOnly: true, arrayFormat: 'comma' }, + // ), + // 'a.b=c,d', + // 'comma: stringifies with dots + comma', + // ); + // st.equal( + // stringify({ a: { b: ['c', 'd'] } }, { allowDots: true, encodeValuesOnly: true }), + // 'a.b[0]=c&a.b[1]=d', + // 'default: stringifies with dots + indices', + // ); + expect( + stringify( + { a: { b: ['c', 'd'] } }, + { allowDots: true, encodeValuesOnly: true, arrayFormat: 'indices' }, + ), + ).toBe('a.b[0]=c&a.b[1]=d'); + expect( + stringify( + { a: { b: ['c', 'd'] } }, + { allowDots: true, encodeValuesOnly: true, arrayFormat: 'brackets' }, + ), + ).toBe('a.b[]=c&a.b[]=d'); + expect( + stringify({ a: { b: ['c', 'd'] } }, { allowDots: true, encodeValuesOnly: true, arrayFormat: 'comma' }), + ).toBe('a.b=c,d'); + expect(stringify({ a: { b: ['c', 'd'] } }, { allowDots: true, encodeValuesOnly: true })).toBe( + 'a.b[0]=c&a.b[1]=d', + ); + }); + + test('stringifies an object inside an array', function () { + // st.equal( + // stringify({ a: [{ b: 'c' }] }, { arrayFormat: 'indices', encodeValuesOnly: true }), + // 'a[0][b]=c', + // 'indices => indices', + // ); + // st.equal( + // stringify({ a: [{ b: 'c' }] }, { arrayFormat: 'repeat', encodeValuesOnly: true }), + // 'a[b]=c', + // 'repeat => repeat', + // ); + // st.equal( + // stringify({ a: [{ b: 'c' }] }, { arrayFormat: 'brackets', encodeValuesOnly: true }), + // 'a[][b]=c', + // 'brackets => brackets', + // ); + // st.equal( + // stringify({ a: [{ b: 'c' }] }, { encodeValuesOnly: true }), + // 'a[0][b]=c', + // 'default => indices', + // ); + expect(stringify({ a: [{ b: 'c' }] }, { arrayFormat: 'indices', encodeValuesOnly: true })).toBe( + 'a[0][b]=c', + ); + expect(stringify({ a: [{ b: 'c' }] }, { arrayFormat: 'repeat', encodeValuesOnly: true })).toBe('a[b]=c'); + expect(stringify({ a: [{ b: 'c' }] }, { arrayFormat: 'brackets', encodeValuesOnly: true })).toBe( + 'a[][b]=c', + ); + expect(stringify({ a: [{ b: 'c' }] }, { encodeValuesOnly: true })).toBe('a[0][b]=c'); + + // st.equal( + // stringify({ a: [{ b: { c: [1] } }] }, { arrayFormat: 'indices', encodeValuesOnly: true }), + // 'a[0][b][c][0]=1', + // 'indices => indices', + // ); + // st.equal( + // stringify({ a: [{ b: { c: [1] } }] }, { arrayFormat: 'repeat', encodeValuesOnly: true }), + // 'a[b][c]=1', + // 'repeat => repeat', + // ); + // st.equal( + // stringify({ a: [{ b: { c: [1] } }] }, { arrayFormat: 'brackets', encodeValuesOnly: true }), + // 'a[][b][c][]=1', + // 'brackets => brackets', + // ); + // st.equal( + // stringify({ a: [{ b: { c: [1] } }] }, { encodeValuesOnly: true }), + // 'a[0][b][c][0]=1', + // 'default => indices', + // ); + expect(stringify({ a: [{ b: { c: [1] } }] }, { arrayFormat: 'indices', encodeValuesOnly: true })).toBe( + 'a[0][b][c][0]=1', + ); + expect(stringify({ a: [{ b: { c: [1] } }] }, { arrayFormat: 'repeat', encodeValuesOnly: true })).toBe( + 'a[b][c]=1', + ); + expect(stringify({ a: [{ b: { c: [1] } }] }, { arrayFormat: 'brackets', encodeValuesOnly: true })).toBe( + 'a[][b][c][]=1', + ); + expect(stringify({ a: [{ b: { c: [1] } }] }, { encodeValuesOnly: true })).toBe('a[0][b][c][0]=1'); + }); + + test('stringifies an array with mixed objects and primitives', function () { + // st.equal( + // stringify({ a: [{ b: 1 }, 2, 3] }, { encodeValuesOnly: true, arrayFormat: 'indices' }), + // 'a[0][b]=1&a[1]=2&a[2]=3', + // 'indices => indices', + // ); + // st.equal( + // stringify({ a: [{ b: 1 }, 2, 3] }, { encodeValuesOnly: true, arrayFormat: 'brackets' }), + // 'a[][b]=1&a[]=2&a[]=3', + // 'brackets => brackets', + // ); + // st.equal( + // stringify({ a: [{ b: 1 }, 2, 3] }, { encodeValuesOnly: true, arrayFormat: 'comma' }), + // '???', + // 'brackets => brackets', + // { skip: 'TODO: figure out what this should do' }, + // ); + // st.equal( + // stringify({ a: [{ b: 1 }, 2, 3] }, { encodeValuesOnly: true }), + // 'a[0][b]=1&a[1]=2&a[2]=3', + // 'default => indices', + // ); + expect(stringify({ a: [{ b: 1 }, 2, 3] }, { encodeValuesOnly: true, arrayFormat: 'indices' })).toBe( + 'a[0][b]=1&a[1]=2&a[2]=3', + ); + expect(stringify({ a: [{ b: 1 }, 2, 3] }, { encodeValuesOnly: true, arrayFormat: 'brackets' })).toBe( + 'a[][b]=1&a[]=2&a[]=3', + ); + // !Skipped: Figure out what this should do + // expect( + // stringify({ a: [{ b: 1 }, 2, 3] }, { encodeValuesOnly: true, arrayFormat: 'comma' }), + // ).toBe('???'); + expect(stringify({ a: [{ b: 1 }, 2, 3] }, { encodeValuesOnly: true })).toBe('a[0][b]=1&a[1]=2&a[2]=3'); + }); + + test('stringifies an object inside an array with dots notation', function () { + // st.equal( + // stringify({ a: [{ b: 'c' }] }, { allowDots: true, encode: false, arrayFormat: 'indices' }), + // 'a[0].b=c', + // 'indices => indices', + // ); + // st.equal( + // stringify( + // { a: [{ b: 'c' }] }, + // { allowDots: true, encode: false, arrayFormat: 'brackets' }, + // ), + // 'a[].b=c', + // 'brackets => brackets', + // ); + // st.equal( + // stringify({ a: [{ b: 'c' }] }, { allowDots: true, encode: false }), + // 'a[0].b=c', + // 'default => indices', + // ); + expect(stringify({ a: [{ b: 'c' }] }, { allowDots: true, encode: false, arrayFormat: 'indices' })).toBe( + 'a[0].b=c', + ); + expect(stringify({ a: [{ b: 'c' }] }, { allowDots: true, encode: false, arrayFormat: 'brackets' })).toBe( + 'a[].b=c', + ); + expect(stringify({ a: [{ b: 'c' }] }, { allowDots: true, encode: false })).toBe('a[0].b=c'); + + // st.equal( + // stringify( + // { a: [{ b: { c: [1] } }] }, + // { allowDots: true, encode: false, arrayFormat: 'indices' }, + // ), + // 'a[0].b.c[0]=1', + // 'indices => indices', + // ); + // st.equal( + // stringify( + // { a: [{ b: { c: [1] } }] }, + // { allowDots: true, encode: false, arrayFormat: 'brackets' }, + // ), + // 'a[].b.c[]=1', + // 'brackets => brackets', + // ); + // st.equal( + // stringify({ a: [{ b: { c: [1] } }] }, { allowDots: true, encode: false }), + // 'a[0].b.c[0]=1', + // 'default => indices', + // ); + expect( + stringify({ a: [{ b: { c: [1] } }] }, { allowDots: true, encode: false, arrayFormat: 'indices' }), + ).toBe('a[0].b.c[0]=1'); + expect( + stringify({ a: [{ b: { c: [1] } }] }, { allowDots: true, encode: false, arrayFormat: 'brackets' }), + ).toBe('a[].b.c[]=1'); + expect(stringify({ a: [{ b: { c: [1] } }] }, { allowDots: true, encode: false })).toBe('a[0].b.c[0]=1'); + }); + + test('does not omit object keys when indices = false', function () { + // st.equal(stringify({ a: [{ b: 'c' }] }, { indices: false }), 'a%5Bb%5D=c'); + expect(stringify({ a: [{ b: 'c' }] }, { indices: false })).toBe('a%5Bb%5D=c'); + }); + + test('uses indices notation for arrays when indices=true', function () { + // st.equal(stringify({ a: ['b', 'c'] }, { indices: true }), 'a%5B0%5D=b&a%5B1%5D=c'); + expect(stringify({ a: ['b', 'c'] }, { indices: true })).toBe('a%5B0%5D=b&a%5B1%5D=c'); + }); + + test('uses indices notation for arrays when no arrayFormat is specified', function () { + // st.equal(stringify({ a: ['b', 'c'] }), 'a%5B0%5D=b&a%5B1%5D=c'); + expect(stringify({ a: ['b', 'c'] })).toBe('a%5B0%5D=b&a%5B1%5D=c'); + }); + + test('uses indices notation for arrays when arrayFormat=indices', function () { + // st.equal(stringify({ a: ['b', 'c'] }, { arrayFormat: 'indices' }), 'a%5B0%5D=b&a%5B1%5D=c'); + expect(stringify({ a: ['b', 'c'] }, { arrayFormat: 'indices' })).toBe('a%5B0%5D=b&a%5B1%5D=c'); + }); + + test('uses repeat notation for arrays when arrayFormat=repeat', function () { + // st.equal(stringify({ a: ['b', 'c'] }, { arrayFormat: 'repeat' }), 'a=b&a=c'); + expect(stringify({ a: ['b', 'c'] }, { arrayFormat: 'repeat' })).toBe('a=b&a=c'); + }); + + test('uses brackets notation for arrays when arrayFormat=brackets', function () { + // st.equal(stringify({ a: ['b', 'c'] }, { arrayFormat: 'brackets' }), 'a%5B%5D=b&a%5B%5D=c'); + expect(stringify({ a: ['b', 'c'] }, { arrayFormat: 'brackets' })).toBe('a%5B%5D=b&a%5B%5D=c'); + }); + + test('stringifies a complicated object', function () { + // st.equal(stringify({ a: { b: 'c', d: 'e' } }), 'a%5Bb%5D=c&a%5Bd%5D=e'); + expect(stringify({ a: { b: 'c', d: 'e' } })).toBe('a%5Bb%5D=c&a%5Bd%5D=e'); + }); + + test('stringifies an empty value', function () { + // st.equal(stringify({ a: '' }), 'a='); + // st.equal(stringify({ a: null }, { strictNullHandling: true }), 'a'); + expect(stringify({ a: '' })).toBe('a='); + expect(stringify({ a: null }, { strictNullHandling: true })).toBe('a'); + + // st.equal(stringify({ a: '', b: '' }), 'a=&b='); + // st.equal(stringify({ a: null, b: '' }, { strictNullHandling: true }), 'a&b='); + expect(stringify({ a: '', b: '' })).toBe('a=&b='); + expect(stringify({ a: null, b: '' }, { strictNullHandling: true })).toBe('a&b='); + + // st.equal(stringify({ a: { b: '' } }), 'a%5Bb%5D='); + // st.equal(stringify({ a: { b: null } }, { strictNullHandling: true }), 'a%5Bb%5D'); + // st.equal(stringify({ a: { b: null } }, { strictNullHandling: false }), 'a%5Bb%5D='); + expect(stringify({ a: { b: '' } })).toBe('a%5Bb%5D='); + expect(stringify({ a: { b: null } }, { strictNullHandling: true })).toBe('a%5Bb%5D'); + expect(stringify({ a: { b: null } }, { strictNullHandling: false })).toBe('a%5Bb%5D='); + }); + + test('stringifies an empty array in different arrayFormat', function () { + // st.equal(stringify({ a: [], b: [null], c: 'c' }, { encode: false }), 'b[0]=&c=c'); + expect(stringify({ a: [], b: [null], c: 'c' }, { encode: false })).toBe('b[0]=&c=c'); + // arrayFormat default + // st.equal( + // stringify({ a: [], b: [null], c: 'c' }, { encode: false, arrayFormat: 'indices' }), + // 'b[0]=&c=c', + // ); + // st.equal( + // stringify({ a: [], b: [null], c: 'c' }, { encode: false, arrayFormat: 'brackets' }), + // 'b[]=&c=c', + // ); + // st.equal( + // stringify({ a: [], b: [null], c: 'c' }, { encode: false, arrayFormat: 'repeat' }), + // 'b=&c=c', + // ); + // st.equal( + // stringify({ a: [], b: [null], c: 'c' }, { encode: false, arrayFormat: 'comma' }), + // 'b=&c=c', + // ); + // st.equal( + // stringify( + // { a: [], b: [null], c: 'c' }, + // { encode: false, arrayFormat: 'comma', commaRoundTrip: true }, + // ), + // 'b[]=&c=c', + // ); + expect(stringify({ a: [], b: [null], c: 'c' }, { encode: false, arrayFormat: 'indices' })).toBe( + 'b[0]=&c=c', + ); + expect(stringify({ a: [], b: [null], c: 'c' }, { encode: false, arrayFormat: 'brackets' })).toBe( + 'b[]=&c=c', + ); + expect(stringify({ a: [], b: [null], c: 'c' }, { encode: false, arrayFormat: 'repeat' })).toBe('b=&c=c'); + expect(stringify({ a: [], b: [null], c: 'c' }, { encode: false, arrayFormat: 'comma' })).toBe('b=&c=c'); + expect( + stringify({ a: [], b: [null], c: 'c' }, { encode: false, arrayFormat: 'comma', commaRoundTrip: true }), + ).toBe('b[]=&c=c'); + + // with strictNullHandling + // st.equal( + // stringify( + // { a: [], b: [null], c: 'c' }, + // { encode: false, arrayFormat: 'indices', strictNullHandling: true }, + // ), + // 'b[0]&c=c', + // ); + // st.equal( + // stringify( + // { a: [], b: [null], c: 'c' }, + // { encode: false, arrayFormat: 'brackets', strictNullHandling: true }, + // ), + // 'b[]&c=c', + // ); + // st.equal( + // stringify( + // { a: [], b: [null], c: 'c' }, + // { encode: false, arrayFormat: 'repeat', strictNullHandling: true }, + // ), + // 'b&c=c', + // ); + // st.equal( + // stringify( + // { a: [], b: [null], c: 'c' }, + // { encode: false, arrayFormat: 'comma', strictNullHandling: true }, + // ), + // 'b&c=c', + // ); + // st.equal( + // stringify( + // { a: [], b: [null], c: 'c' }, + // { encode: false, arrayFormat: 'comma', strictNullHandling: true, commaRoundTrip: true }, + // ), + // 'b[]&c=c', + // ); + + expect( + stringify( + { a: [], b: [null], c: 'c' }, + { encode: false, arrayFormat: 'indices', strictNullHandling: true }, + ), + ).toBe('b[0]&c=c'); + expect( + stringify( + { a: [], b: [null], c: 'c' }, + { encode: false, arrayFormat: 'brackets', strictNullHandling: true }, + ), + ).toBe('b[]&c=c'); + expect( + stringify( + { a: [], b: [null], c: 'c' }, + { encode: false, arrayFormat: 'repeat', strictNullHandling: true }, + ), + ).toBe('b&c=c'); + expect( + stringify( + { a: [], b: [null], c: 'c' }, + { encode: false, arrayFormat: 'comma', strictNullHandling: true }, + ), + ).toBe('b&c=c'); + expect( + stringify( + { a: [], b: [null], c: 'c' }, + { encode: false, arrayFormat: 'comma', strictNullHandling: true, commaRoundTrip: true }, + ), + ).toBe('b[]&c=c'); + + // with skipNulls + // st.equal( + // stringify( + // { a: [], b: [null], c: 'c' }, + // { encode: false, arrayFormat: 'indices', skipNulls: true }, + // ), + // 'c=c', + // ); + // st.equal( + // stringify( + // { a: [], b: [null], c: 'c' }, + // { encode: false, arrayFormat: 'brackets', skipNulls: true }, + // ), + // 'c=c', + // ); + // st.equal( + // stringify( + // { a: [], b: [null], c: 'c' }, + // { encode: false, arrayFormat: 'repeat', skipNulls: true }, + // ), + // 'c=c', + // ); + // st.equal( + // stringify( + // { a: [], b: [null], c: 'c' }, + // { encode: false, arrayFormat: 'comma', skipNulls: true }, + // ), + // 'c=c', + // ); + expect( + stringify({ a: [], b: [null], c: 'c' }, { encode: false, arrayFormat: 'indices', skipNulls: true }), + ).toBe('c=c'); + expect( + stringify({ a: [], b: [null], c: 'c' }, { encode: false, arrayFormat: 'brackets', skipNulls: true }), + ).toBe('c=c'); + expect( + stringify({ a: [], b: [null], c: 'c' }, { encode: false, arrayFormat: 'repeat', skipNulls: true }), + ).toBe('c=c'); + expect( + stringify({ a: [], b: [null], c: 'c' }, { encode: false, arrayFormat: 'comma', skipNulls: true }), + ).toBe('c=c'); + }); + + test('stringifies a null object', function () { + var obj = Object.create(null); + obj.a = 'b'; + // st.equal(stringify(obj), 'a=b'); + expect(stringify(obj)).toBe('a=b'); + }); + + test('returns an empty string for invalid input', function () { + // st.equal(stringify(undefined), ''); + // st.equal(stringify(false), ''); + // st.equal(stringify(null), ''); + // st.equal(stringify(''), ''); + expect(stringify(undefined)).toBe(''); + expect(stringify(false)).toBe(''); + expect(stringify(null)).toBe(''); + expect(stringify('')).toBe(''); + }); + + test('stringifies an object with a null object as a child', function () { + var obj = { a: Object.create(null) }; + + obj.a.b = 'c'; + // st.equal(stringify(obj), 'a%5Bb%5D=c'); + expect(stringify(obj)).toBe('a%5Bb%5D=c'); + }); + + test('drops keys with a value of undefined', function () { + // st.equal(stringify({ a: undefined }), ''); + expect(stringify({ a: undefined })).toBe(''); + + // st.equal( + // stringify({ a: { b: undefined, c: null } }, { strictNullHandling: true }), + // 'a%5Bc%5D', + // ); + // st.equal( + // stringify({ a: { b: undefined, c: null } }, { strictNullHandling: false }), + // 'a%5Bc%5D=', + // ); + // st.equal(stringify({ a: { b: undefined, c: '' } }), 'a%5Bc%5D='); + expect(stringify({ a: { b: undefined, c: null } }, { strictNullHandling: true })).toBe('a%5Bc%5D'); + expect(stringify({ a: { b: undefined, c: null } }, { strictNullHandling: false })).toBe('a%5Bc%5D='); + expect(stringify({ a: { b: undefined, c: '' } })).toBe('a%5Bc%5D='); + }); + + test('url encodes values', function () { + // st.equal(stringify({ a: 'b c' }), 'a=b%20c'); + expect(stringify({ a: 'b c' })).toBe('a=b%20c'); + }); + + test('stringifies a date', function () { + var now = new Date(); + var str = 'a=' + encodeURIComponent(now.toISOString()); + // st.equal(stringify({ a: now }), str); + expect(stringify({ a: now })).toBe(str); + }); + + test('stringifies the weird object from qs', function () { + // st.equal( + // stringify({ 'my weird field': '~q1!2"\'w$5&7/z8)?' }), + // 'my%20weird%20field=~q1%212%22%27w%245%267%2Fz8%29%3F', + // ); + expect(stringify({ 'my weird field': '~q1!2"\'w$5&7/z8)?' })).toBe( + 'my%20weird%20field=~q1%212%22%27w%245%267%2Fz8%29%3F', + ); + }); + + // TODO: Investigate how to to intercept in vitest + // TODO(rob) + test('skips properties that are part of the object prototype', function () { + // st.intercept(Object.prototype, 'crash', { value: 'test' }); + // @ts-expect-error + Object.prototype.crash = 'test'; + + // st.equal(stringify({ a: 'b' }), 'a=b'); + // st.equal(stringify({ a: { b: 'c' } }), 'a%5Bb%5D=c'); + expect(stringify({ a: 'b' })).toBe('a=b'); + expect(stringify({ a: { b: 'c' } })).toBe('a%5Bb%5D=c'); + }); + + test('stringifies boolean values', function () { + // st.equal(stringify({ a: true }), 'a=true'); + // st.equal(stringify({ a: { b: true } }), 'a%5Bb%5D=true'); + // st.equal(stringify({ b: false }), 'b=false'); + // st.equal(stringify({ b: { c: false } }), 'b%5Bc%5D=false'); + expect(stringify({ a: true })).toBe('a=true'); + expect(stringify({ a: { b: true } })).toBe('a%5Bb%5D=true'); + expect(stringify({ b: false })).toBe('b=false'); + expect(stringify({ b: { c: false } })).toBe('b%5Bc%5D=false'); + }); + + test('stringifies buffer values', function () { + // st.equal(stringify({ a: Buffer.from('test') }), 'a=test'); + // st.equal(stringify({ a: { b: Buffer.from('test') } }), 'a%5Bb%5D=test'); + }); + + test('stringifies an object using an alternative delimiter', function () { + // st.equal(stringify({ a: 'b', c: 'd' }, { delimiter: ';' }), 'a=b;c=d'); + expect(stringify({ a: 'b', c: 'd' }, { delimiter: ';' })).toBe('a=b;c=d'); + }); + + // We dont target environments which dont even have Buffer + // test('does not blow up when Buffer global is missing', function () { + // var restore = mockProperty(global, 'Buffer', { delete: true }); + + // var result = stringify({ a: 'b', c: 'd' }); + + // restore(); + + // st.equal(result, 'a=b&c=d'); + // st.end(); + // }); + + test('does not crash when parsing circular references', function () { + var a: any = {}; + a.b = a; + + // st['throws']( + // function () { + // stringify({ 'foo[bar]': 'baz', 'foo[baz]': a }); + // }, + // /RangeError: Cyclic object value/, + // 'cyclic values throw', + // ); + expect(() => { + stringify({ 'foo[bar]': 'baz', 'foo[baz]': a }); + }).toThrow('Cyclic object value'); + + var circular: any = { + a: 'value', + }; + circular.a = circular; + // st['throws']( + // function () { + // stringify(circular); + // }, + // /RangeError: Cyclic object value/, + // 'cyclic values throw', + // ); + expect(() => { + stringify(circular); + }).toThrow('Cyclic object value'); + + var arr = ['a']; + // st.doesNotThrow(function () { + // stringify({ x: arr, y: arr }); + // }, 'non-cyclic values do not throw'); + expect(() => { + stringify({ x: arr, y: arr }); + }).not.toThrow(); + }); + + test('non-circular duplicated references can still work', function () { + var hourOfDay = { + function: 'hour_of_day', + }; + + var p1 = { + function: 'gte', + arguments: [hourOfDay, 0], + }; + var p2 = { + function: 'lte', + arguments: [hourOfDay, 23], + }; + + // st.equal( + // stringify( + // { filters: { $and: [p1, p2] } }, + // { encodeValuesOnly: true, arrayFormat: 'indices' }, + // ), + // 'filters[$and][0][function]=gte&filters[$and][0][arguments][0][function]=hour_of_day&filters[$and][0][arguments][1]=0&filters[$and][1][function]=lte&filters[$and][1][arguments][0][function]=hour_of_day&filters[$and][1][arguments][1]=23', + // ); + // st.equal( + // stringify( + // { filters: { $and: [p1, p2] } }, + // { encodeValuesOnly: true, arrayFormat: 'brackets' }, + // ), + // 'filters[$and][][function]=gte&filters[$and][][arguments][][function]=hour_of_day&filters[$and][][arguments][]=0&filters[$and][][function]=lte&filters[$and][][arguments][][function]=hour_of_day&filters[$and][][arguments][]=23', + // ); + // st.equal( + // stringify( + // { filters: { $and: [p1, p2] } }, + // { encodeValuesOnly: true, arrayFormat: 'repeat' }, + // ), + // 'filters[$and][function]=gte&filters[$and][arguments][function]=hour_of_day&filters[$and][arguments]=0&filters[$and][function]=lte&filters[$and][arguments][function]=hour_of_day&filters[$and][arguments]=23', + // ); + expect( + stringify({ filters: { $and: [p1, p2] } }, { encodeValuesOnly: true, arrayFormat: 'indices' }), + ).toBe( + 'filters[$and][0][function]=gte&filters[$and][0][arguments][0][function]=hour_of_day&filters[$and][0][arguments][1]=0&filters[$and][1][function]=lte&filters[$and][1][arguments][0][function]=hour_of_day&filters[$and][1][arguments][1]=23', + ); + expect( + stringify({ filters: { $and: [p1, p2] } }, { encodeValuesOnly: true, arrayFormat: 'brackets' }), + ).toBe( + 'filters[$and][][function]=gte&filters[$and][][arguments][][function]=hour_of_day&filters[$and][][arguments][]=0&filters[$and][][function]=lte&filters[$and][][arguments][][function]=hour_of_day&filters[$and][][arguments][]=23', + ); + expect( + stringify({ filters: { $and: [p1, p2] } }, { encodeValuesOnly: true, arrayFormat: 'repeat' }), + ).toBe( + 'filters[$and][function]=gte&filters[$and][arguments][function]=hour_of_day&filters[$and][arguments]=0&filters[$and][function]=lte&filters[$and][arguments][function]=hour_of_day&filters[$and][arguments]=23', + ); + }); + + test('selects properties when filter=array', function () { + // st.equal(stringify({ a: 'b' }, { filter: ['a'] }), 'a=b'); + // st.equal(stringify({ a: 1 }, { filter: [] }), ''); + expect(stringify({ a: 'b' }, { filter: ['a'] })).toBe('a=b'); + expect(stringify({ a: 1 }, { filter: [] })).toBe(''); + + // st.equal( + // stringify( + // { a: { b: [1, 2, 3, 4], c: 'd' }, c: 'f' }, + // { filter: ['a', 'b', 0, 2], arrayFormat: 'indices' }, + // ), + // 'a%5Bb%5D%5B0%5D=1&a%5Bb%5D%5B2%5D=3', + // 'indices => indices', + // ); + // st.equal( + // stringify( + // { a: { b: [1, 2, 3, 4], c: 'd' }, c: 'f' }, + // { filter: ['a', 'b', 0, 2], arrayFormat: 'brackets' }, + // ), + // 'a%5Bb%5D%5B%5D=1&a%5Bb%5D%5B%5D=3', + // 'brackets => brackets', + // ); + // st.equal( + // stringify({ a: { b: [1, 2, 3, 4], c: 'd' }, c: 'f' }, { filter: ['a', 'b', 0, 2] }), + // 'a%5Bb%5D%5B0%5D=1&a%5Bb%5D%5B2%5D=3', + // 'default => indices', + // ); + expect(stringify({ a: { b: [1, 2, 3, 4], c: 'd' }, c: 'f' }, { filter: ['a', 'b', 0, 2] })).toBe( + 'a%5Bb%5D%5B0%5D=1&a%5Bb%5D%5B2%5D=3', + ); + expect( + stringify( + { a: { b: [1, 2, 3, 4], c: 'd' }, c: 'f' }, + { filter: ['a', 'b', 0, 2], arrayFormat: 'indices' }, + ), + ).toBe('a%5Bb%5D%5B0%5D=1&a%5Bb%5D%5B2%5D=3'); + expect( + stringify( + { a: { b: [1, 2, 3, 4], c: 'd' }, c: 'f' }, + { filter: ['a', 'b', 0, 2], arrayFormat: 'brackets' }, + ), + ).toBe('a%5Bb%5D%5B%5D=1&a%5Bb%5D%5B%5D=3'); + }); + + test('supports custom representations when filter=function', function () { + var calls = 0; + var obj = { a: 'b', c: 'd', e: { f: new Date(1257894000000) } }; + var filterFunc: StringifyOptions['filter'] = function (prefix, value) { + calls += 1; + if (calls === 1) { + // st.equal(prefix, '', 'prefix is empty'); + // st.equal(value, obj); + expect(prefix).toBe(''); + expect(value).toBe(obj); + } else if (prefix === 'c') { + return void 0; + } else if (value instanceof Date) { + // st.equal(prefix, 'e[f]'); + expect(prefix).toBe('e[f]'); + return value.getTime(); + } + return value; + }; + + // st.equal(stringify(obj, { filter: filterFunc }), 'a=b&e%5Bf%5D=1257894000000'); + // st.equal(calls, 5); + expect(stringify(obj, { filter: filterFunc })).toBe('a=b&e%5Bf%5D=1257894000000'); + expect(calls).toBe(5); + }); + + test('can disable uri encoding', function () { + // st.equal(stringify({ a: 'b' }, { encode: false }), 'a=b'); + // st.equal(stringify({ a: { b: 'c' } }, { encode: false }), 'a[b]=c'); + // st.equal( + // stringify({ a: 'b', c: null }, { strictNullHandling: true, encode: false }), + // 'a=b&c', + // ); + expect(stringify({ a: 'b' }, { encode: false })).toBe('a=b'); + expect(stringify({ a: { b: 'c' } }, { encode: false })).toBe('a[b]=c'); + expect(stringify({ a: 'b', c: null }, { strictNullHandling: true, encode: false })).toBe('a=b&c'); + }); + + test('can sort the keys', function () { + // @ts-expect-error + var sort: NonNullable = function (a: string, b: string) { + return a.localeCompare(b); + }; + // st.equal(stringify({ a: 'c', z: 'y', b: 'f' }, { sort: sort }), 'a=c&b=f&z=y'); + // st.equal( + // stringify({ a: 'c', z: { j: 'a', i: 'b' }, b: 'f' }, { sort: sort }), + // 'a=c&b=f&z%5Bi%5D=b&z%5Bj%5D=a', + // ); + expect(stringify({ a: 'c', z: 'y', b: 'f' }, { sort: sort })).toBe('a=c&b=f&z=y'); + expect(stringify({ a: 'c', z: { j: 'a', i: 'b' }, b: 'f' }, { sort: sort })).toBe( + 'a=c&b=f&z%5Bi%5D=b&z%5Bj%5D=a', + ); + }); + + test('can sort the keys at depth 3 or more too', function () { + // @ts-expect-error + var sort: NonNullable = function (a: string, b: string) { + return a.localeCompare(b); + }; + // st.equal( + // stringify( + // { a: 'a', z: { zj: { zjb: 'zjb', zja: 'zja' }, zi: { zib: 'zib', zia: 'zia' } }, b: 'b' }, + // { sort: sort, encode: false }, + // ), + // 'a=a&b=b&z[zi][zia]=zia&z[zi][zib]=zib&z[zj][zja]=zja&z[zj][zjb]=zjb', + // ); + // st.equal( + // stringify( + // { a: 'a', z: { zj: { zjb: 'zjb', zja: 'zja' }, zi: { zib: 'zib', zia: 'zia' } }, b: 'b' }, + // { sort: null, encode: false }, + // ), + // 'a=a&z[zj][zjb]=zjb&z[zj][zja]=zja&z[zi][zib]=zib&z[zi][zia]=zia&b=b', + // ); + expect( + stringify( + { a: 'a', z: { zj: { zjb: 'zjb', zja: 'zja' }, zi: { zib: 'zib', zia: 'zia' } }, b: 'b' }, + { sort: sort, encode: false }, + ), + ).toBe('a=a&b=b&z[zi][zia]=zia&z[zi][zib]=zib&z[zj][zja]=zja&z[zj][zjb]=zjb'); + expect( + stringify( + { a: 'a', z: { zj: { zjb: 'zjb', zja: 'zja' }, zi: { zib: 'zib', zia: 'zia' } }, b: 'b' }, + { sort: null, encode: false }, + ), + ).toBe('a=a&z[zj][zjb]=zjb&z[zj][zja]=zja&z[zi][zib]=zib&z[zi][zia]=zia&b=b'); + }); + + test('can stringify with custom encoding', function () { + // st.equal( + // stringify( + // { 県: '大阪府', '': '' }, + // { + // encoder: function (str) { + // if (str.length === 0) { + // return ''; + // } + // var buf = iconv.encode(str, 'shiftjis'); + // var result = []; + // for (var i = 0; i < buf.length; ++i) { + // result.push(buf.readUInt8(i).toString(16)); + // } + // return '%' + result.join('%'); + // }, + // }, + // ), + // '%8c%a7=%91%e5%8d%e3%95%7b&=', + // ); + expect( + stringify( + { 県: '大阪府', '': '' }, + { + encoder: function (str) { + if (str.length === 0) { + return ''; + } + var buf = iconv.encode(str, 'shiftjis'); + var result = []; + for (var i = 0; i < buf.length; ++i) { + result.push(buf.readUInt8(i).toString(16)); + } + return '%' + result.join('%'); + }, + }, + ), + ).toBe('%8c%a7=%91%e5%8d%e3%95%7b&='); + }); + + test('receives the default encoder as a second argument', function () { + // stringify( + // { a: 1, b: new Date(), c: true, d: [1] }, + // { + // encoder: function (str) { + // st.match(typeof str, /^(?:string|number|boolean)$/); + // return ''; + // }, + // }, + // ); + + stringify( + { a: 1, b: new Date(), c: true, d: [1] }, + { + encoder: function (str) { + // st.match(typeof str, /^(?:string|number|boolean)$/); + assert.match(typeof str, /^(?:string|number|boolean)$/); + return ''; + }, + }, + ); + }); + + test('receives the default encoder as a second argument', function () { + // stringify( + // { a: 1 }, + // { + // encoder: function (str, defaultEncoder) { + // st.equal(defaultEncoder, utils.encode); + // }, + // }, + // ); + + stringify( + { a: 1 }, + { + // @ts-ignore + encoder: function (_str, defaultEncoder) { + expect(defaultEncoder).toBe(encode); + }, + }, + ); + }); + + test('throws error with wrong encoder', function () { + // st['throws'](function () { + // stringify({}, { encoder: 'string' }); + // }, new TypeError('Encoder has to be a function.')); + // st.end(); + expect(() => { + // @ts-expect-error + stringify({}, { encoder: 'string' }); + }).toThrow(TypeError); + }); + + (typeof Buffer === 'undefined' ? test.skip : test)( + 'can use custom encoder for a buffer object', + function () { + // st.equal( + // stringify( + // { a: Buffer.from([1]) }, + // { + // encoder: function (buffer) { + // if (typeof buffer === 'string') { + // return buffer; + // } + // return String.fromCharCode(buffer.readUInt8(0) + 97); + // }, + // }, + // ), + // 'a=b', + // ); + expect( + stringify( + { a: Buffer.from([1]) }, + { + encoder: function (buffer) { + if (typeof buffer === 'string') { + return buffer; + } + return String.fromCharCode(buffer.readUInt8(0) + 97); + }, + }, + ), + ).toBe('a=b'); + + // st.equal( + // stringify( + // { a: Buffer.from('a b') }, + // { + // encoder: function (buffer) { + // return buffer; + // }, + // }, + // ), + // 'a=a b', + // ); + expect( + stringify( + { a: Buffer.from('a b') }, + { + encoder: function (buffer) { + return buffer; + }, + }, + ), + ).toBe('a=a b'); + }, + ); + + test('serializeDate option', function () { + var date = new Date(); + // st.equal( + // stringify({ a: date }), + // 'a=' + date.toISOString().replace(/:/g, '%3A'), + // 'default is toISOString', + // ); + expect(stringify({ a: date })).toBe('a=' + date.toISOString().replace(/:/g, '%3A')); + + var mutatedDate = new Date(); + mutatedDate.toISOString = function () { + throw new SyntaxError(); + }; + // st['throws'](function () { + // mutatedDate.toISOString(); + // }, SyntaxError); + expect(() => { + mutatedDate.toISOString(); + }).toThrow(SyntaxError); + // st.equal( + // stringify({ a: mutatedDate }), + // 'a=' + Date.prototype.toISOString.call(mutatedDate).replace(/:/g, '%3A'), + // 'toISOString works even when method is not locally present', + // ); + expect(stringify({ a: mutatedDate })).toBe( + 'a=' + Date.prototype.toISOString.call(mutatedDate).replace(/:/g, '%3A'), + ); + + var specificDate = new Date(6); + // st.equal( + // stringify( + // { a: specificDate }, + // { + // serializeDate: function (d) { + // return d.getTime() * 7; + // }, + // }, + // ), + // 'a=42', + // 'custom serializeDate function called', + // ); + expect( + stringify( + { a: specificDate }, + { + // @ts-ignore + serializeDate: function (d) { + return d.getTime() * 7; + }, + }, + ), + ).toBe('a=42'); + + // st.equal( + // stringify( + // { a: [date] }, + // { + // serializeDate: function (d) { + // return d.getTime(); + // }, + // arrayFormat: 'comma', + // }, + // ), + // 'a=' + date.getTime(), + // 'works with arrayFormat comma', + // ); + // st.equal( + // stringify( + // { a: [date] }, + // { + // serializeDate: function (d) { + // return d.getTime(); + // }, + // arrayFormat: 'comma', + // commaRoundTrip: true, + // }, + // ), + // 'a%5B%5D=' + date.getTime(), + // 'works with arrayFormat comma', + // ); + expect( + stringify( + { a: [date] }, + { + // @ts-expect-error + serializeDate: function (d) { + return d.getTime(); + }, + arrayFormat: 'comma', + }, + ), + ).toBe('a=' + date.getTime()); + expect( + stringify( + { a: [date] }, + { + // @ts-expect-error + serializeDate: function (d) { + return d.getTime(); + }, + arrayFormat: 'comma', + commaRoundTrip: true, + }, + ), + ).toBe('a%5B%5D=' + date.getTime()); + }); + + test('RFC 1738 serialization', function () { + // st.equal(stringify({ a: 'b c' }, { format: formats.RFC1738 }), 'a=b+c'); + // st.equal(stringify({ 'a b': 'c d' }, { format: formats.RFC1738 }), 'a+b=c+d'); + // st.equal( + // stringify({ 'a b': Buffer.from('a b') }, { format: formats.RFC1738 }), + // 'a+b=a+b', + // ); + expect(stringify({ a: 'b c' }, { format: 'RFC1738' })).toBe('a=b+c'); + expect(stringify({ 'a b': 'c d' }, { format: 'RFC1738' })).toBe('a+b=c+d'); + expect(stringify({ 'a b': Buffer.from('a b') }, { format: 'RFC1738' })).toBe('a+b=a+b'); + + // st.equal(stringify({ 'foo(ref)': 'bar' }, { format: formats.RFC1738 }), 'foo(ref)=bar'); + expect(stringify({ 'foo(ref)': 'bar' }, { format: 'RFC1738' })).toBe('foo(ref)=bar'); + }); + + test('RFC 3986 spaces serialization', function () { + // st.equal(stringify({ a: 'b c' }, { format: formats.RFC3986 }), 'a=b%20c'); + // st.equal(stringify({ 'a b': 'c d' }, { format: formats.RFC3986 }), 'a%20b=c%20d'); + // st.equal( + // stringify({ 'a b': Buffer.from('a b') }, { format: formats.RFC3986 }), + // 'a%20b=a%20b', + // ); + expect(stringify({ a: 'b c' }, { format: 'RFC3986' })).toBe('a=b%20c'); + expect(stringify({ 'a b': 'c d' }, { format: 'RFC3986' })).toBe('a%20b=c%20d'); + expect(stringify({ 'a b': Buffer.from('a b') }, { format: 'RFC3986' })).toBe('a%20b=a%20b'); + }); + + test('Backward compatibility to RFC 3986', function () { + // st.equal(stringify({ a: 'b c' }), 'a=b%20c'); + // st.equal(stringify({ 'a b': Buffer.from('a b') }), 'a%20b=a%20b'); + expect(stringify({ a: 'b c' })).toBe('a=b%20c'); + expect(stringify({ 'a b': Buffer.from('a b') })).toBe('a%20b=a%20b'); + }); + + test('Edge cases and unknown formats', function () { + ['UFO1234', false, 1234, null, {}, []].forEach(function (format) { + // st['throws'](function () { + // stringify({ a: 'b c' }, { format: format }); + // }, new TypeError('Unknown format option provided.')); + expect(() => { + // @ts-expect-error + stringify({ a: 'b c' }, { format: format }); + }).toThrow(TypeError); + }); + }); + + test('encodeValuesOnly', function () { + // st.equal( + // stringify( + // { a: 'b', c: ['d', 'e=f'], f: [['g'], ['h']] }, + // { encodeValuesOnly: true, arrayFormat: 'indices' }, + // ), + // 'a=b&c[0]=d&c[1]=e%3Df&f[0][0]=g&f[1][0]=h', + // 'encodeValuesOnly + indices', + // ); + // st.equal( + // stringify( + // { a: 'b', c: ['d', 'e=f'], f: [['g'], ['h']] }, + // { encodeValuesOnly: true, arrayFormat: 'brackets' }, + // ), + // 'a=b&c[]=d&c[]=e%3Df&f[][]=g&f[][]=h', + // 'encodeValuesOnly + brackets', + // ); + // st.equal( + // stringify( + // { a: 'b', c: ['d', 'e=f'], f: [['g'], ['h']] }, + // { encodeValuesOnly: true, arrayFormat: 'repeat' }, + // ), + // 'a=b&c=d&c=e%3Df&f=g&f=h', + // 'encodeValuesOnly + repeat', + // ); + expect( + stringify( + { a: 'b', c: ['d', 'e=f'], f: [['g'], ['h']] }, + { encodeValuesOnly: true, arrayFormat: 'indices' }, + ), + ).toBe('a=b&c[0]=d&c[1]=e%3Df&f[0][0]=g&f[1][0]=h'); + expect( + stringify( + { a: 'b', c: ['d', 'e=f'], f: [['g'], ['h']] }, + { encodeValuesOnly: true, arrayFormat: 'brackets' }, + ), + ).toBe('a=b&c[]=d&c[]=e%3Df&f[][]=g&f[][]=h'); + expect( + stringify( + { a: 'b', c: ['d', 'e=f'], f: [['g'], ['h']] }, + { encodeValuesOnly: true, arrayFormat: 'repeat' }, + ), + ).toBe('a=b&c=d&c=e%3Df&f=g&f=h'); + + // st.equal( + // stringify({ a: 'b', c: ['d', 'e'], f: [['g'], ['h']] }, { arrayFormat: 'indices' }), + // 'a=b&c%5B0%5D=d&c%5B1%5D=e&f%5B0%5D%5B0%5D=g&f%5B1%5D%5B0%5D=h', + // 'no encodeValuesOnly + indices', + // ); + // st.equal( + // stringify({ a: 'b', c: ['d', 'e'], f: [['g'], ['h']] }, { arrayFormat: 'brackets' }), + // 'a=b&c%5B%5D=d&c%5B%5D=e&f%5B%5D%5B%5D=g&f%5B%5D%5B%5D=h', + // 'no encodeValuesOnly + brackets', + // ); + // st.equal( + // stringify({ a: 'b', c: ['d', 'e'], f: [['g'], ['h']] }, { arrayFormat: 'repeat' }), + // 'a=b&c=d&c=e&f=g&f=h', + // 'no encodeValuesOnly + repeat', + // ); + expect(stringify({ a: 'b', c: ['d', 'e'], f: [['g'], ['h']] }, { arrayFormat: 'indices' })).toBe( + 'a=b&c%5B0%5D=d&c%5B1%5D=e&f%5B0%5D%5B0%5D=g&f%5B1%5D%5B0%5D=h', + ); + expect(stringify({ a: 'b', c: ['d', 'e'], f: [['g'], ['h']] }, { arrayFormat: 'brackets' })).toBe( + 'a=b&c%5B%5D=d&c%5B%5D=e&f%5B%5D%5B%5D=g&f%5B%5D%5B%5D=h', + ); + expect(stringify({ a: 'b', c: ['d', 'e'], f: [['g'], ['h']] }, { arrayFormat: 'repeat' })).toBe( + 'a=b&c=d&c=e&f=g&f=h', + ); + }); + + test('encodeValuesOnly - strictNullHandling', function () { + // st.equal( + // stringify({ a: { b: null } }, { encodeValuesOnly: true, strictNullHandling: true }), + // 'a[b]', + // ); + expect(stringify({ a: { b: null } }, { encodeValuesOnly: true, strictNullHandling: true })).toBe('a[b]'); + }); + + test('throws if an invalid charset is specified', function () { + // st['throws'](function () { + // stringify({ a: 'b' }, { charset: 'foobar' }); + // }, new TypeError('The charset option must be either utf-8, iso-8859-1, or undefined')); + expect(() => { + // @ts-expect-error + stringify({ a: 'b' }, { charset: 'foobar' }); + }).toThrow(TypeError); + }); + + test('respects a charset of iso-8859-1', function () { + // st.equal(stringify({ æ: 'æ' }, { charset: 'iso-8859-1' }), '%E6=%E6'); + expect(stringify({ æ: 'æ' }, { charset: 'iso-8859-1' })).toBe('%E6=%E6'); + }); + + test('encodes unrepresentable chars as numeric entities in iso-8859-1 mode', function () { + // st.equal(stringify({ a: '☺' }, { charset: 'iso-8859-1' }), 'a=%26%239786%3B'); + expect(stringify({ a: '☺' }, { charset: 'iso-8859-1' })).toBe('a=%26%239786%3B'); + }); + + test('respects an explicit charset of utf-8 (the default)', function () { + // st.equal(stringify({ a: 'æ' }, { charset: 'utf-8' }), 'a=%C3%A6'); + expect(stringify({ a: 'æ' }, { charset: 'utf-8' })).toBe('a=%C3%A6'); + }); + + test('`charsetSentinel` option', function () { + // st.equal( + // stringify({ a: 'æ' }, { charsetSentinel: true, charset: 'utf-8' }), + // 'utf8=%E2%9C%93&a=%C3%A6', + // 'adds the right sentinel when instructed to and the charset is utf-8', + // ); + expect(stringify({ a: 'æ' }, { charsetSentinel: true, charset: 'utf-8' })).toBe( + 'utf8=%E2%9C%93&a=%C3%A6', + ); + + // st.equal( + // stringify({ a: 'æ' }, { charsetSentinel: true, charset: 'iso-8859-1' }), + // 'utf8=%26%2310003%3B&a=%E6', + // 'adds the right sentinel when instructed to and the charset is iso-8859-1', + // ); + expect(stringify({ a: 'æ' }, { charsetSentinel: true, charset: 'iso-8859-1' })).toBe( + 'utf8=%26%2310003%3B&a=%E6', + ); + }); + + test('does not mutate the options argument', function () { + var options = {}; + stringify({}, options); + // st.deepEqual(options, {}); + expect(options).toEqual({}); + }); + + test('strictNullHandling works with custom filter', function () { + // @ts-expect-error + var filter = function (_prefix, value) { + return value; + }; + + var options = { strictNullHandling: true, filter: filter }; + // st.equal(stringify({ key: null }, options), 'key'); + expect(stringify({ key: null }, options)).toBe('key'); + }); + + test('strictNullHandling works with null serializeDate', function () { + var serializeDate = function () { + return null; + }; + var options = { strictNullHandling: true, serializeDate: serializeDate }; + var date = new Date(); + // st.equal(stringify({ key: date }, options), 'key'); + // @ts-expect-error + expect(stringify({ key: date }, options)).toBe('key'); + }); + + test('allows for encoding keys and values differently', function () { + // @ts-expect-error + var encoder = function (str, defaultEncoder, charset, type) { + if (type === 'key') { + return defaultEncoder(str, defaultEncoder, charset, type).toLowerCase(); + } + if (type === 'value') { + return defaultEncoder(str, defaultEncoder, charset, type).toUpperCase(); + } + throw 'this should never happen! type: ' + type; + }; + + // st.deepEqual(stringify({ KeY: 'vAlUe' }, { encoder: encoder }), 'key=VALUE'); + expect(stringify({ KeY: 'vAlUe' }, { encoder: encoder })).toBe('key=VALUE'); + }); + + test('objects inside arrays', function () { + var obj = { a: { b: { c: 'd', e: 'f' } } }; + var withArray = { a: { b: [{ c: 'd', e: 'f' }] } }; + + // st.equal( + // stringify(obj, { encode: false }), + // 'a[b][c]=d&a[b][e]=f', + // 'no array, no arrayFormat', + // ); + // st.equal( + // stringify(obj, { encode: false, arrayFormat: 'brackets' }), + // 'a[b][c]=d&a[b][e]=f', + // 'no array, bracket', + // ); + // st.equal( + // stringify(obj, { encode: false, arrayFormat: 'indices' }), + // 'a[b][c]=d&a[b][e]=f', + // 'no array, indices', + // ); + // st.equal( + // stringify(obj, { encode: false, arrayFormat: 'repeat' }), + // 'a[b][c]=d&a[b][e]=f', + // 'no array, repeat', + // ); + // st.equal( + // stringify(obj, { encode: false, arrayFormat: 'comma' }), + // 'a[b][c]=d&a[b][e]=f', + // 'no array, comma', + // ); + expect(stringify(obj, { encode: false })).toBe('a[b][c]=d&a[b][e]=f'); + expect(stringify(obj, { encode: false, arrayFormat: 'brackets' })).toBe('a[b][c]=d&a[b][e]=f'); + expect(stringify(obj, { encode: false, arrayFormat: 'indices' })).toBe('a[b][c]=d&a[b][e]=f'); + expect(stringify(obj, { encode: false, arrayFormat: 'repeat' })).toBe('a[b][c]=d&a[b][e]=f'); + expect(stringify(obj, { encode: false, arrayFormat: 'comma' })).toBe('a[b][c]=d&a[b][e]=f'); + + // st.equal( + // stringify(withArray, { encode: false }), + // 'a[b][0][c]=d&a[b][0][e]=f', + // 'array, no arrayFormat', + // ); + // st.equal( + // stringify(withArray, { encode: false, arrayFormat: 'brackets' }), + // 'a[b][][c]=d&a[b][][e]=f', + // 'array, bracket', + // ); + // st.equal( + // stringify(withArray, { encode: false, arrayFormat: 'indices' }), + // 'a[b][0][c]=d&a[b][0][e]=f', + // 'array, indices', + // ); + // st.equal( + // stringify(withArray, { encode: false, arrayFormat: 'repeat' }), + // 'a[b][c]=d&a[b][e]=f', + // 'array, repeat', + // ); + // st.equal( + // stringify(withArray, { encode: false, arrayFormat: 'comma' }), + // '???', + // 'array, comma', + // { skip: 'TODO: figure out what this should do' }, + // ); + expect(stringify(withArray, { encode: false })).toBe('a[b][0][c]=d&a[b][0][e]=f'); + expect(stringify(withArray, { encode: false, arrayFormat: 'brackets' })).toBe('a[b][][c]=d&a[b][][e]=f'); + expect(stringify(withArray, { encode: false, arrayFormat: 'indices' })).toBe('a[b][0][c]=d&a[b][0][e]=f'); + expect(stringify(withArray, { encode: false, arrayFormat: 'repeat' })).toBe('a[b][c]=d&a[b][e]=f'); + // !TODo: Figure out what this should do + // expect(stringify(withArray, { encode: false, arrayFormat: 'comma' })).toBe( + // 'a[b][c]=d&a[b][e]=f', + // ); + }); + + test('stringifies sparse arrays', function () { + // st.equal( + // stringify({ a: [, '2', , , '1'] }, { encodeValuesOnly: true, arrayFormat: 'indices' }), + // 'a[1]=2&a[4]=1', + // ); + // st.equal( + // stringify({ a: [, '2', , , '1'] }, { encodeValuesOnly: true, arrayFormat: 'brackets' }), + // 'a[]=2&a[]=1', + // ); + // st.equal( + // stringify({ a: [, '2', , , '1'] }, { encodeValuesOnly: true, arrayFormat: 'repeat' }), + // 'a=2&a=1', + // ); + expect(stringify({ a: [, '2', , , '1'] }, { encodeValuesOnly: true, arrayFormat: 'indices' })).toBe( + 'a[1]=2&a[4]=1', + ); + expect(stringify({ a: [, '2', , , '1'] }, { encodeValuesOnly: true, arrayFormat: 'brackets' })).toBe( + 'a[]=2&a[]=1', + ); + expect(stringify({ a: [, '2', , , '1'] }, { encodeValuesOnly: true, arrayFormat: 'repeat' })).toBe( + 'a=2&a=1', + ); + + // st.equal( + // stringify( + // { a: [, { b: [, , { c: '1' }] }] }, + // { encodeValuesOnly: true, arrayFormat: 'indices' }, + // ), + // 'a[1][b][2][c]=1', + // ); + // st.equal( + // stringify( + // { a: [, { b: [, , { c: '1' }] }] }, + // { encodeValuesOnly: true, arrayFormat: 'brackets' }, + // ), + // 'a[][b][][c]=1', + // ); + // st.equal( + // stringify( + // { a: [, { b: [, , { c: '1' }] }] }, + // { encodeValuesOnly: true, arrayFormat: 'repeat' }, + // ), + // 'a[b][c]=1', + // ); + expect( + stringify({ a: [, { b: [, , { c: '1' }] }] }, { encodeValuesOnly: true, arrayFormat: 'indices' }), + ).toBe('a[1][b][2][c]=1'); + expect( + stringify({ a: [, { b: [, , { c: '1' }] }] }, { encodeValuesOnly: true, arrayFormat: 'brackets' }), + ).toBe('a[][b][][c]=1'); + expect( + stringify({ a: [, { b: [, , { c: '1' }] }] }, { encodeValuesOnly: true, arrayFormat: 'repeat' }), + ).toBe('a[b][c]=1'); + + // st.equal( + // stringify( + // { a: [, [, , [, , , { c: '1' }]]] }, + // { encodeValuesOnly: true, arrayFormat: 'indices' }, + // ), + // 'a[1][2][3][c]=1', + // ); + // st.equal( + // stringify( + // { a: [, [, , [, , , { c: '1' }]]] }, + // { encodeValuesOnly: true, arrayFormat: 'brackets' }, + // ), + // 'a[][][][c]=1', + // ); + // st.equal( + // stringify( + // { a: [, [, , [, , , { c: '1' }]]] }, + // { encodeValuesOnly: true, arrayFormat: 'repeat' }, + // ), + // 'a[c]=1', + // ); + expect( + stringify({ a: [, [, , [, , , { c: '1' }]]] }, { encodeValuesOnly: true, arrayFormat: 'indices' }), + ).toBe('a[1][2][3][c]=1'); + expect( + stringify({ a: [, [, , [, , , { c: '1' }]]] }, { encodeValuesOnly: true, arrayFormat: 'brackets' }), + ).toBe('a[][][][c]=1'); + expect( + stringify({ a: [, [, , [, , , { c: '1' }]]] }, { encodeValuesOnly: true, arrayFormat: 'repeat' }), + ).toBe('a[c]=1'); + + // st.equal( + // stringify( + // { a: [, [, , [, , , { c: [, '1'] }]]] }, + // { encodeValuesOnly: true, arrayFormat: 'indices' }, + // ), + // 'a[1][2][3][c][1]=1', + // ); + // st.equal( + // stringify( + // { a: [, [, , [, , , { c: [, '1'] }]]] }, + // { encodeValuesOnly: true, arrayFormat: 'brackets' }, + // ), + // 'a[][][][c][]=1', + // ); + // st.equal( + // stringify( + // { a: [, [, , [, , , { c: [, '1'] }]]] }, + // { encodeValuesOnly: true, arrayFormat: 'repeat' }, + // ), + // 'a[c]=1', + // ); + expect( + stringify({ a: [, [, , [, , , { c: [, '1'] }]]] }, { encodeValuesOnly: true, arrayFormat: 'indices' }), + ).toBe('a[1][2][3][c][1]=1'); + expect( + stringify({ a: [, [, , [, , , { c: [, '1'] }]]] }, { encodeValuesOnly: true, arrayFormat: 'brackets' }), + ).toBe('a[][][][c][]=1'); + expect( + stringify({ a: [, [, , [, , , { c: [, '1'] }]]] }, { encodeValuesOnly: true, arrayFormat: 'repeat' }), + ).toBe('a[c]=1'); + }); + + test('encodes a very long string', function () { + var chars = []; + var expected = []; + for (var i = 0; i < 5e3; i++) { + chars.push(' ' + i); + + expected.push('%20' + i); + } + + var obj = { + foo: chars.join(''), + }; + + // st.equal( + // stringify(obj, { arrayFormat: 'bracket', charset: 'utf-8' }), + // 'foo=' + expected.join(''), + // ); + // @ts-expect-error + expect(stringify(obj, { arrayFormat: 'bracket', charset: 'utf-8' })).toBe('foo=' + expected.join('')); + }); +}); + +describe('stringifies empty keys', function () { + empty_test_cases.forEach(function (testCase) { + test('stringifies an object with empty string key with ' + testCase.input, function () { + // st.deepEqual( + // stringify(testCase.withEmptyKeys, { encode: false, arrayFormat: 'indices' }), + // testCase.stringifyOutput.indices, + // 'test case: ' + testCase.input + ', indices', + // ); + // st.deepEqual( + // stringify(testCase.withEmptyKeys, { encode: false, arrayFormat: 'brackets' }), + // testCase.stringifyOutput.brackets, + // 'test case: ' + testCase.input + ', brackets', + // ); + // st.deepEqual( + // stringify(testCase.withEmptyKeys, { encode: false, arrayFormat: 'repeat' }), + // testCase.stringifyOutput.repeat, + // 'test case: ' + testCase.input + ', repeat', + // ); + expect(stringify(testCase.with_empty_keys, { encode: false, arrayFormat: 'indices' })).toBe( + testCase.stringify_output.indices, + ); + expect(stringify(testCase.with_empty_keys, { encode: false, arrayFormat: 'brackets' })).toBe( + testCase.stringify_output.brackets, + ); + expect(stringify(testCase.with_empty_keys, { encode: false, arrayFormat: 'repeat' })).toBe( + testCase.stringify_output.repeat, + ); + }); + }); + + test('edge case with object/arrays', function () { + // st.deepEqual(stringify({ '': { '': [2, 3] } }, { encode: false }), '[][0]=2&[][1]=3'); + // st.deepEqual( + // stringify({ '': { '': [2, 3], a: 2 } }, { encode: false }), + // '[][0]=2&[][1]=3&[a]=2', + // ); + // st.deepEqual( + // stringify({ '': { '': [2, 3] } }, { encode: false, arrayFormat: 'indices' }), + // '[][0]=2&[][1]=3', + // ); + // st.deepEqual( + // stringify({ '': { '': [2, 3], a: 2 } }, { encode: false, arrayFormat: 'indices' }), + // '[][0]=2&[][1]=3&[a]=2', + // ); + expect(stringify({ '': { '': [2, 3] } }, { encode: false })).toBe('[][0]=2&[][1]=3'); + expect(stringify({ '': { '': [2, 3], a: 2 } }, { encode: false })).toBe('[][0]=2&[][1]=3&[a]=2'); + expect(stringify({ '': { '': [2, 3] } }, { encode: false, arrayFormat: 'indices' })).toBe( + '[][0]=2&[][1]=3', + ); + expect(stringify({ '': { '': [2, 3], a: 2 } }, { encode: false, arrayFormat: 'indices' })).toBe( + '[][0]=2&[][1]=3&[a]=2', + ); + }); +}); diff --git a/tests/qs/utils.test.ts b/tests/qs/utils.test.ts new file mode 100644 index 00000000..0b8bd4cd --- /dev/null +++ b/tests/qs/utils.test.ts @@ -0,0 +1,169 @@ +import { combine, merge, is_buffer, assign_single_source } from '@onkernel/sdk/internal/qs/utils'; + +describe('merge()', function () { + // t.deepEqual(merge(null, true), [null, true], 'merges true into null'); + expect(merge(null, true)).toEqual([null, true]); + + // t.deepEqual(merge(null, [42]), [null, 42], 'merges null into an array'); + expect(merge(null, [42])).toEqual([null, 42]); + + // t.deepEqual( + // merge({ a: 'b' }, { a: 'c' }), + // { a: ['b', 'c'] }, + // 'merges two objects with the same key', + // ); + expect(merge({ a: 'b' }, { a: 'c' })).toEqual({ a: ['b', 'c'] }); + + var oneMerged = merge({ foo: 'bar' }, { foo: { first: '123' } }); + // t.deepEqual( + // oneMerged, + // { foo: ['bar', { first: '123' }] }, + // 'merges a standalone and an object into an array', + // ); + expect(oneMerged).toEqual({ foo: ['bar', { first: '123' }] }); + + var twoMerged = merge({ foo: ['bar', { first: '123' }] }, { foo: { second: '456' } }); + // t.deepEqual( + // twoMerged, + // { foo: { 0: 'bar', 1: { first: '123' }, second: '456' } }, + // 'merges a standalone and two objects into an array', + // ); + expect(twoMerged).toEqual({ foo: { 0: 'bar', 1: { first: '123' }, second: '456' } }); + + var sandwiched = merge({ foo: ['bar', { first: '123', second: '456' }] }, { foo: 'baz' }); + // t.deepEqual( + // sandwiched, + // { foo: ['bar', { first: '123', second: '456' }, 'baz'] }, + // 'merges an object sandwiched by two standalones into an array', + // ); + expect(sandwiched).toEqual({ foo: ['bar', { first: '123', second: '456' }, 'baz'] }); + + var nestedArrays = merge({ foo: ['baz'] }, { foo: ['bar', 'xyzzy'] }); + // t.deepEqual(nestedArrays, { foo: ['baz', 'bar', 'xyzzy'] }); + expect(nestedArrays).toEqual({ foo: ['baz', 'bar', 'xyzzy'] }); + + var noOptionsNonObjectSource = merge({ foo: 'baz' }, 'bar'); + // t.deepEqual(noOptionsNonObjectSource, { foo: 'baz', bar: true }); + expect(noOptionsNonObjectSource).toEqual({ foo: 'baz', bar: true }); + + (typeof Object.defineProperty !== 'function' ? test.skip : test)( + 'avoids invoking array setters unnecessarily', + function () { + var setCount = 0; + var getCount = 0; + var observed: any[] = []; + Object.defineProperty(observed, 0, { + get: function () { + getCount += 1; + return { bar: 'baz' }; + }, + set: function () { + setCount += 1; + }, + }); + merge(observed, [null]); + // st.equal(setCount, 0); + // st.equal(getCount, 1); + expect(setCount).toEqual(0); + expect(getCount).toEqual(1); + observed[0] = observed[0]; + // st.equal(setCount, 1); + // st.equal(getCount, 2); + expect(setCount).toEqual(1); + expect(getCount).toEqual(2); + }, + ); +}); + +test('assign()', function () { + var target = { a: 1, b: 2 }; + var source = { b: 3, c: 4 }; + var result = assign_single_source(target, source); + + expect(result).toEqual(target); + expect(target).toEqual({ a: 1, b: 3, c: 4 }); + expect(source).toEqual({ b: 3, c: 4 }); +}); + +describe('combine()', function () { + test('both arrays', function () { + var a = [1]; + var b = [2]; + var combined = combine(a, b); + + // st.deepEqual(a, [1], 'a is not mutated'); + // st.deepEqual(b, [2], 'b is not mutated'); + // st.notEqual(a, combined, 'a !== combined'); + // st.notEqual(b, combined, 'b !== combined'); + // st.deepEqual(combined, [1, 2], 'combined is a + b'); + expect(a).toEqual([1]); + expect(b).toEqual([2]); + expect(combined).toEqual([1, 2]); + expect(a).not.toEqual(combined); + expect(b).not.toEqual(combined); + }); + + test('one array, one non-array', function () { + var aN = 1; + var a = [aN]; + var bN = 2; + var b = [bN]; + + var combinedAnB = combine(aN, b); + // st.deepEqual(b, [bN], 'b is not mutated'); + // st.notEqual(aN, combinedAnB, 'aN + b !== aN'); + // st.notEqual(a, combinedAnB, 'aN + b !== a'); + // st.notEqual(bN, combinedAnB, 'aN + b !== bN'); + // st.notEqual(b, combinedAnB, 'aN + b !== b'); + // st.deepEqual([1, 2], combinedAnB, 'first argument is array-wrapped when not an array'); + expect(b).toEqual([bN]); + expect(combinedAnB).not.toEqual(aN); + expect(combinedAnB).not.toEqual(a); + expect(combinedAnB).not.toEqual(bN); + expect(combinedAnB).not.toEqual(b); + expect(combinedAnB).toEqual([1, 2]); + + var combinedABn = combine(a, bN); + // st.deepEqual(a, [aN], 'a is not mutated'); + // st.notEqual(aN, combinedABn, 'a + bN !== aN'); + // st.notEqual(a, combinedABn, 'a + bN !== a'); + // st.notEqual(bN, combinedABn, 'a + bN !== bN'); + // st.notEqual(b, combinedABn, 'a + bN !== b'); + // st.deepEqual([1, 2], combinedABn, 'second argument is array-wrapped when not an array'); + expect(a).toEqual([aN]); + expect(combinedABn).not.toEqual(aN); + expect(combinedABn).not.toEqual(a); + expect(combinedABn).not.toEqual(bN); + expect(combinedABn).not.toEqual(b); + expect(combinedABn).toEqual([1, 2]); + }); + + test('neither is an array', function () { + var combined = combine(1, 2); + // st.notEqual(1, combined, '1 + 2 !== 1'); + // st.notEqual(2, combined, '1 + 2 !== 2'); + // st.deepEqual([1, 2], combined, 'both arguments are array-wrapped when not an array'); + expect(combined).not.toEqual(1); + expect(combined).not.toEqual(2); + expect(combined).toEqual([1, 2]); + }); +}); + +test('is_buffer()', function () { + for (const x of [null, undefined, true, false, '', 'abc', 42, 0, NaN, {}, [], function () {}, /a/g]) { + // t.equal(is_buffer(x), false, inspect(x) + ' is not a buffer'); + expect(is_buffer(x)).toEqual(false); + } + + var fakeBuffer = { constructor: Buffer }; + // t.equal(is_buffer(fakeBuffer), false, 'fake buffer is not a buffer'); + expect(is_buffer(fakeBuffer)).toEqual(false); + + var saferBuffer = Buffer.from('abc'); + // t.equal(is_buffer(saferBuffer), true, 'SaferBuffer instance is a buffer'); + expect(is_buffer(saferBuffer)).toEqual(true); + + var buffer = Buffer.from('abc'); + // t.equal(is_buffer(buffer), true, 'real Buffer instance is a buffer'); + expect(is_buffer(buffer)).toEqual(true); +}); diff --git a/tests/stringifyQuery.test.ts b/tests/stringifyQuery.test.ts index dedd39a7..8696cdfa 100644 --- a/tests/stringifyQuery.test.ts +++ b/tests/stringifyQuery.test.ts @@ -18,10 +18,4 @@ describe(stringifyQuery, () => { expect(stringifyQuery(input)).toEqual(expected); }); } - - for (const value of [[], {}, new Date()]) { - it(`${JSON.stringify(value)} -> `, () => { - expect(() => stringifyQuery({ value })).toThrow(`Cannot stringify type ${typeof value}`); - }); - } }); From 3bc43093a03f598d294fe9ff9f5ee40c8ddbfeee Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 5 Jun 2026 17:24:41 +0000 Subject: [PATCH 429/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 4f40d13b..12bb1a5c 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.62.0" + ".": "0.63.0" } diff --git a/package.json b/package.json index 29db9412..b0191e22 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.62.0", + "version": "0.63.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 59e6a166..3abb4d11 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.62.0'; // x-release-please-version +export const VERSION = '0.63.0'; // x-release-please-version From e073610445c1d6b716ed149773c6a235f065c62a Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 5 Jun 2026 18:06:25 +0000 Subject: [PATCH 430/551] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index b53121ed..8991baf8 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 117 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-8f84f4214a8024d8ea62ee639eeaf2fa26900fabe23c8b87accb41d529a0bf4f.yml -openapi_spec_hash: db14f415438b3d338d9376bddc83a5cf +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-53de38ec04ee49846c89946b2fe72641c5ee005956d1fff4e8a50de9ba22e874.yml +openapi_spec_hash: 96162b6a1e4a2521be1b6c4fb9b0e5ce config_hash: 590bf8cb85948cf1e63b7b5ef60686c8 From 297153288e749073e3f3d1edfcf41947a683084d Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 5 Jun 2026 21:36:50 +0000 Subject: [PATCH 431/551] feat: Telemetry: expose opt-in categories + full event taxonomy (public API) --- .stats.yml | 6 +- api.md | 8 + src/resources/browsers/browsers.ts | 46 +- src/resources/browsers/index.ts | 8 + src/resources/browsers/telemetry.ts | 526 +++++++++++++++++- tests/api-resources/browsers/browsers.test.ts | 5 + 6 files changed, 563 insertions(+), 36 deletions(-) diff --git a/.stats.yml b/.stats.yml index 8991baf8..d9e97532 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 117 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-53de38ec04ee49846c89946b2fe72641c5ee005956d1fff4e8a50de9ba22e874.yml -openapi_spec_hash: 96162b6a1e4a2521be1b6c4fb9b0e5ce -config_hash: 590bf8cb85948cf1e63b7b5ef60686c8 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-9d489e3e43edfa64a754d4281241718e01c85d9a82ef3687df12bbd3c4ff5b42.yml +openapi_spec_hash: a953cafb7f40ec8495dbd7df8bab8bad +config_hash: bb7acce8576a50dd449b0c8f58ef0f1d diff --git a/api.md b/api.md index 337b12a3..4625155d 100644 --- a/api.md +++ b/api.md @@ -90,7 +90,11 @@ Methods: Types: +- BrowserAPICallEvent - BrowserCallStack +- BrowserCaptchaSolveResultEvent +- BrowserCdpConnectEvent +- BrowserCdpDisconnectEvent - BrowserConsoleErrorEvent - BrowserConsoleLogEvent - BrowserEventContext @@ -99,6 +103,8 @@ Types: - BrowserInteractionClickEvent - BrowserInteractionKeyEvent - BrowserInteractionScrollSettledEvent +- BrowserLiveViewConnectEvent +- BrowserLiveViewDisconnectEvent - BrowserMonitorDisconnectedEvent - BrowserMonitorInitFailedEvent - BrowserMonitorReconnectFailedEvent @@ -116,6 +122,8 @@ Types: - BrowserPageNavigationEvent - BrowserPageNavigationSettledEvent - BrowserPageTabOpenedEvent +- BrowserServiceCrashedEvent +- BrowserSystemOomKillEvent - BrowserTelemetryCategoriesConfig - BrowserTelemetryCategoryConfig - BrowserTelemetryConfig diff --git a/src/resources/browsers/browsers.ts b/src/resources/browsers/browsers.ts index d3d61374..39c317b8 100644 --- a/src/resources/browsers/browsers.ts +++ b/src/resources/browsers/browsers.ts @@ -52,7 +52,11 @@ import { } from './replays'; import * as TelemetryAPI from './telemetry'; import { + BrowserAPICallEvent, BrowserCallStack, + BrowserCaptchaSolveResultEvent, + BrowserCdpConnectEvent, + BrowserCdpDisconnectEvent, BrowserConsoleErrorEvent, BrowserConsoleLogEvent, BrowserEventContext, @@ -61,6 +65,8 @@ import { BrowserInteractionClickEvent, BrowserInteractionKeyEvent, BrowserInteractionScrollSettledEvent, + BrowserLiveViewConnectEvent, + BrowserLiveViewDisconnectEvent, BrowserMonitorDisconnectedEvent, BrowserMonitorInitFailedEvent, BrowserMonitorReconnectFailedEvent, @@ -78,6 +84,8 @@ import { BrowserPageNavigationEvent, BrowserPageNavigationSettledEvent, BrowserPageTabOpenedEvent, + BrowserServiceCrashedEvent, + BrowserSystemOomKillEvent, BrowserTelemetryCategoriesConfig, BrowserTelemetryCategoryConfig, BrowserTelemetryConfig, @@ -988,17 +996,18 @@ export namespace BrowserCreateParams { */ export interface Telemetry { /** - * Per-category enable/disable flags. If enabled is true and browser is omitted or - * empty, the VM default category set is used. Explicitly disabling all four - * categories stops capture on update and starts no capture on create. + * Per-category capture flags. Selection is opt-in: only the categories set to + * enabled=true are captured; anything omitted is off. If enabled is true and + * browser is omitted or empty, the default category set is used. A browser config + * that enables nothing stops capture on update and starts no capture on create. */ browser?: TelemetryAPI.BrowserTelemetryCategoriesConfig; /** - * Request shortcut for browser telemetry capture. True enables capture using VM - * defaults unless browser category settings are provided. False stops capture on - * update and starts no capture on create. enabled=false cannot be combined with - * browser category settings. + * Request shortcut for browser telemetry capture. True enables capture using the + * default category set unless browser category settings are provided. False stops + * capture on update and starts no capture on create. enabled=false cannot be + * combined with browser category settings. */ enabled?: boolean; } @@ -1055,17 +1064,18 @@ export namespace BrowserUpdateParams { */ export interface Telemetry { /** - * Per-category enable/disable flags. If enabled is true and browser is omitted or - * empty, the VM default category set is used. Explicitly disabling all four - * categories stops capture on update and starts no capture on create. + * Per-category capture flags. Selection is opt-in: only the categories set to + * enabled=true are captured; anything omitted is off. If enabled is true and + * browser is omitted or empty, the default category set is used. A browser config + * that enables nothing stops capture on update and starts no capture on create. */ browser?: TelemetryAPI.BrowserTelemetryCategoriesConfig; /** - * Request shortcut for browser telemetry capture. True enables capture using VM - * defaults unless browser category settings are provided. False stops capture on - * update and starts no capture on create. enabled=false cannot be combined with - * browser category settings. + * Request shortcut for browser telemetry capture. True enables capture using the + * default category set unless browser category settings are provided. False stops + * capture on update and starts no capture on create. enabled=false cannot be + * combined with browser category settings. */ enabled?: boolean; } @@ -1194,7 +1204,11 @@ export declare namespace Browsers { export { TelemetryAPITelemetry as Telemetry, + type BrowserAPICallEvent as BrowserAPICallEvent, type BrowserCallStack as BrowserCallStack, + type BrowserCaptchaSolveResultEvent as BrowserCaptchaSolveResultEvent, + type BrowserCdpConnectEvent as BrowserCdpConnectEvent, + type BrowserCdpDisconnectEvent as BrowserCdpDisconnectEvent, type BrowserConsoleErrorEvent as BrowserConsoleErrorEvent, type BrowserConsoleLogEvent as BrowserConsoleLogEvent, type BrowserEventContext as BrowserEventContext, @@ -1203,6 +1217,8 @@ export declare namespace Browsers { type BrowserInteractionClickEvent as BrowserInteractionClickEvent, type BrowserInteractionKeyEvent as BrowserInteractionKeyEvent, type BrowserInteractionScrollSettledEvent as BrowserInteractionScrollSettledEvent, + type BrowserLiveViewConnectEvent as BrowserLiveViewConnectEvent, + type BrowserLiveViewDisconnectEvent as BrowserLiveViewDisconnectEvent, type BrowserMonitorDisconnectedEvent as BrowserMonitorDisconnectedEvent, type BrowserMonitorInitFailedEvent as BrowserMonitorInitFailedEvent, type BrowserMonitorReconnectFailedEvent as BrowserMonitorReconnectFailedEvent, @@ -1220,6 +1236,8 @@ export declare namespace Browsers { type BrowserPageNavigationEvent as BrowserPageNavigationEvent, type BrowserPageNavigationSettledEvent as BrowserPageNavigationSettledEvent, type BrowserPageTabOpenedEvent as BrowserPageTabOpenedEvent, + type BrowserServiceCrashedEvent as BrowserServiceCrashedEvent, + type BrowserSystemOomKillEvent as BrowserSystemOomKillEvent, type BrowserTelemetryCategoriesConfig as BrowserTelemetryCategoriesConfig, type BrowserTelemetryCategoryConfig as BrowserTelemetryCategoryConfig, type BrowserTelemetryConfig as BrowserTelemetryConfig, diff --git a/src/resources/browsers/index.ts b/src/resources/browsers/index.ts index 08e2fdec..a95c02b6 100644 --- a/src/resources/browsers/index.ts +++ b/src/resources/browsers/index.ts @@ -82,7 +82,11 @@ export { } from './replays'; export { Telemetry, + type BrowserAPICallEvent, type BrowserCallStack, + type BrowserCaptchaSolveResultEvent, + type BrowserCdpConnectEvent, + type BrowserCdpDisconnectEvent, type BrowserConsoleErrorEvent, type BrowserConsoleLogEvent, type BrowserEventContext, @@ -91,6 +95,8 @@ export { type BrowserInteractionClickEvent, type BrowserInteractionKeyEvent, type BrowserInteractionScrollSettledEvent, + type BrowserLiveViewConnectEvent, + type BrowserLiveViewDisconnectEvent, type BrowserMonitorDisconnectedEvent, type BrowserMonitorInitFailedEvent, type BrowserMonitorReconnectFailedEvent, @@ -108,6 +114,8 @@ export { type BrowserPageNavigationEvent, type BrowserPageNavigationSettledEvent, type BrowserPageTabOpenedEvent, + type BrowserServiceCrashedEvent, + type BrowserSystemOomKillEvent, type BrowserTelemetryCategoriesConfig, type BrowserTelemetryCategoryConfig, type BrowserTelemetryConfig, diff --git a/src/resources/browsers/telemetry.ts b/src/resources/browsers/telemetry.ts index 74e83d07..50909b02 100644 --- a/src/resources/browsers/telemetry.ts +++ b/src/resources/browsers/telemetry.ts @@ -49,6 +49,56 @@ export class Telemetry extends APIResource { } } +/** + * An agent-driven HTTP call handled by the in-VM API server. + */ +export interface BrowserAPICallEvent { + category: 'control'; + + /** + * Provenance metadata identifying which producer emitted the event. + */ + source: BrowserEventSource; + + /** + * Event timestamp in Unix microseconds. + */ + ts: number; + + type: 'api_call'; + + data?: BrowserAPICallEvent.Data; + + /** + * True if the data field was truncated due to size limits. + */ + truncated?: boolean; +} + +export namespace BrowserAPICallEvent { + export interface Data { + /** + * Wall-clock duration of the handler in milliseconds. + */ + duration_ms: number; + + /** + * OpenAPI operationId of the matched route (e.g. processExec, takeScreenshot). + */ + operation_id: string; + + /** + * Per-request identifier from the in-VM API request middleware. + */ + request_id: string; + + /** + * HTTP response status code. + */ + status: number; + } +} + /** * CDP Runtime.StackTrace representing the JavaScript call stack at the time of an * event. Fields use CDP naming conventions rather than snake_case to match the @@ -100,6 +150,151 @@ export namespace BrowserCallStack { } } +/** + * A captcha solve attempt reached a terminal outcome. + */ +export interface BrowserCaptchaSolveResultEvent { + category: 'captcha'; + + /** + * Provenance metadata identifying which producer emitted the event. + */ + source: BrowserEventSource; + + /** + * Event timestamp in Unix microseconds. + */ + ts: number; + + type: 'captcha_solve_result'; + + data?: BrowserCaptchaSolveResultEvent.Data; + + /** + * True if the data field was truncated due to size limits. + */ + truncated?: boolean; +} + +export namespace BrowserCaptchaSolveResultEvent { + export interface Data { + /** + * Captcha vendor family. Provider-specific task names are normalized into this + * set; anything not covered is reported as other. + */ + captcha_type: 'hcaptcha' | 'recaptcha_v2' | 'recaptcha_v3' | 'turnstile' | 'geetest' | 'other'; + + /** + * Wall-clock duration from solve start to terminal outcome. + */ + duration_ms: number; + + /** + * Terminal outcome. success: solver returned a usable solution. failure: solver + * returned an error (see error_code). timeout: solver did not return within the + * caller's wait budget. abandoned: caller cancelled or the page navigated away + * mid-solve. + */ + status: 'success' | 'failure' | 'timeout' | 'abandoned'; + + /** + * Solver-specific error code on failure (e.g. ERROR_CAPTCHA_UNSOLVABLE). Absent on + * success. + */ + error_code?: string; + + /** + * Solver-assigned identifier. Opaque, useful for support cross-references. + */ + task_id?: string; + + /** + * Host of the page where the captcha was solved. + */ + website_host?: string; + + /** + * Path of the page where the captcha was solved. Query string excluded. + */ + website_path?: string; + } +} + +/** + * An external client (e.g. customer SDK, Playwright, Puppeteer) connected to the + * CDP WebSocket proxy on this VM. + */ +export interface BrowserCdpConnectEvent { + category: 'connection'; + + /** + * Provenance metadata identifying which producer emitted the event. + */ + source: BrowserEventSource; + + /** + * Event timestamp in Unix microseconds. + */ + ts: number; + + type: 'cdp_connect'; + + /** + * True if the data field was truncated due to size limits. + */ + truncated?: boolean; +} + +/** + * An external client disconnected from the CDP WebSocket proxy on this VM. Pair + * with the immediately preceding cdp_connect on the same stream. + */ +export interface BrowserCdpDisconnectEvent { + category: 'connection'; + + /** + * Provenance metadata identifying which producer emitted the event. + */ + source: BrowserEventSource; + + /** + * Event timestamp in Unix microseconds. + */ + ts: number; + + type: 'cdp_disconnect'; + + data?: BrowserCdpDisconnectEvent.Data; + + /** + * True if the data field was truncated due to size limits. + */ + truncated?: boolean; +} + +export namespace BrowserCdpDisconnectEvent { + export interface Data { + /** + * Wall-clock duration of the connection in milliseconds. + */ + duration_ms: number; + + /** + * Number of CDP messages relayed across the connection in either direction. + */ + message_count: number; + + /** + * Why the connection ended. client_close: the client initiated the close. + * upstream_changed: Chromium restarted mid-session and the proxy tore down so the + * client could reconnect against the new upstream. upstream_error: upstream dial + * or message pump errored. context_cancelled: the request context was cancelled + * (typically server shutdown). + */ + reason: 'client_close' | 'upstream_changed' | 'upstream_error' | 'context_cancelled'; + } +} + /** * A browser console error or uncaught JavaScript exception event. Emitted from two * distinct CDP sources with different data shapes. Runtime.consoleAPICalled @@ -509,13 +704,91 @@ export namespace BrowserInteractionScrollSettledEvent { } } +/** + * A live view client connected to the headful browser's WebRTC server. Headful + * only; not emitted for headless images. + */ +export interface BrowserLiveViewConnectEvent { + category: 'connection'; + + /** + * Provenance metadata identifying which producer emitted the event. + */ + source: BrowserEventSource; + + /** + * Event timestamp in Unix microseconds. + */ + ts: number; + + type: 'live_view_connect'; + + data?: BrowserLiveViewConnectEvent.Data; + + /** + * True if the data field was truncated due to size limits. + */ + truncated?: boolean; +} + +export namespace BrowserLiveViewConnectEvent { + export interface Data { + /** + * Live view session identifier. Stable across reconnects, so a transient network + * blip can emit two events with the same session_id. + */ + session_id: string; + } +} + +/** + * A live view client disconnected from the headful browser's WebRTC server. Pair + * with live_view_connect by session_id. + */ +export interface BrowserLiveViewDisconnectEvent { + category: 'connection'; + + /** + * Provenance metadata identifying which producer emitted the event. + */ + source: BrowserEventSource; + + /** + * Event timestamp in Unix microseconds. + */ + ts: number; + + type: 'live_view_disconnect'; + + data?: BrowserLiveViewDisconnectEvent.Data; + + /** + * True if the data field was truncated due to size limits. + */ + truncated?: boolean; +} + +export namespace BrowserLiveViewDisconnectEvent { + export interface Data { + /** + * Wall-clock duration of the connection in milliseconds. + */ + duration_ms: number; + + /** + * Live view session identifier; matches the corresponding live_view_connect event. + */ + session_id: string; + } +} + /** * The CDP connection to Chrome was lost. Telemetry events may be dropped until * monitor_reconnected arrives. Treat any in-progress computed state (network_idle, * page_layout_settled) as unreliable until then. */ export interface BrowserMonitorDisconnectedEvent { - category: 'system'; + category: 'monitor'; /** * Provenance metadata identifying which producer emitted the event. @@ -550,7 +823,7 @@ export namespace BrowserMonitorDisconnectedEvent { * The CDP session could not be initialized. */ export interface BrowserMonitorInitFailedEvent { - category: 'system'; + category: 'monitor'; /** * Provenance metadata identifying which producer emitted the event. @@ -586,7 +859,7 @@ export namespace BrowserMonitorInitFailedEvent { * reconnection attempts. No further telemetry events will arrive on this session. */ export interface BrowserMonitorReconnectFailedEvent { - category: 'system'; + category: 'monitor'; /** * Provenance metadata identifying which producer emitted the event. @@ -624,7 +897,7 @@ export namespace BrowserMonitorReconnectFailedEvent { * so navigation and network tracking restart fresh from this point. */ export interface BrowserMonitorReconnectedEvent { - category: 'system'; + category: 'monitor'; /** * Provenance metadata identifying which producer emitted the event. @@ -659,7 +932,7 @@ export namespace BrowserMonitorReconnectedEvent { * A periodic screenshot of the browser viewport. */ export interface BrowserMonitorScreenshotEvent { - category: 'system'; + category: 'screenshot'; /** * Provenance metadata identifying which producer emitted the event. @@ -1417,16 +1690,195 @@ export namespace BrowserPageTabOpenedEvent { } /** - * Per-category telemetry capture settings. + * A managed service exited unexpectedly. Intentional stops do not produce this + * event; only unexpected exits and terminal restart-give-up transitions do. + */ +export interface BrowserServiceCrashedEvent { + category: 'system'; + + /** + * Provenance metadata identifying which producer emitted the event. + */ + source: BrowserEventSource; + + /** + * Event timestamp in Unix microseconds. + */ + ts: number; + + type: 'service_crashed'; + + data?: BrowserServiceCrashedEvent.Data; + + /** + * True if the data field was truncated due to size limits. + */ + truncated?: boolean; +} + +export namespace BrowserServiceCrashedEvent { + export interface Data { + /** + * Lifecycle phase the crash occurred in. startup: the process died before reaching + * a healthy running state. running: a previously healthy process died + * unexpectedly. gave_up: the process manager exhausted its restart attempts and + * stopped trying. + */ + phase: 'startup' | 'running' | 'gave_up'; + + /** + * Program name of the crashed service (e.g. chromium, mutter, kernel-images-api). + */ + service_name: string; + + /** + * PID of the crashed process. Absent when the process manager gave up after + * exhausting restart attempts. + */ + pid?: number; + } +} + +/** + * The Linux kernel OOM-killer terminated a process inside the VM. Fires for any + * process killed by the kernel due to memory exhaustion, including Chrome renderer + * subprocesses that are not supervised. + */ +export interface BrowserSystemOomKillEvent { + category: 'system'; + + /** + * Provenance metadata identifying which producer emitted the event. + */ + source: BrowserEventSource; + + /** + * Event timestamp in Unix microseconds. + */ + ts: number; + + type: 'system_oom_kill'; + + data?: BrowserSystemOomKillEvent.Data; + + /** + * True if the data field was truncated due to size limits. + */ + truncated?: boolean; +} + +export namespace BrowserSystemOomKillEvent { + export interface Data { + /** + * PID of the killed process. + */ + pid: number; + + /** + * Comm of the killed process as reported by the kernel (max 15 chars, truncated by + * the kernel). + */ + process_name: string; + + /** + * Resident set size of the killed process in KiB (sum of anon-rss, file-rss, and + * shmem-rss). + */ + rss_kb: number; + + /** + * Why the kernel decided to OOM-kill. none means global memory exhaustion; memcg + * means a cgroup memory limit was hit; cpuset / memory_policy are + * NUMA/policy-driven kills. Absent on kernels older than 5.0. + */ + constraint?: 'none' | 'memcg' | 'cpuset' | 'memory_policy'; + + /** + * Free system memory in KiB at the time of the kill. Assumes a 4 KiB page size. + * Does not include reclaimable caches. Absent if the kernel did not emit a + * parseable Mem-Info section. + */ + mem_free_kb?: number; + + /** + * Total system memory in KiB at the time of the kill. Assumes a 4 KiB page size. + * Absent if the kernel did not emit a parseable Mem-Info section. + */ + mem_total_kb?: number; + + /** + * Top processes by resident-set-size at the moment of the kill, sorted descending. + * Empty if the kernel did not emit the Tasks state table. Capped at 5 entries. + */ + top_tasks?: Array; + + /** + * PID of the triggering process. Absent if the kernel did not emit the standard + * header line. + */ + trigger_pid?: number; + + /** + * Comm of the process whose allocation request caused the kernel to invoke the + * OOM-killer. Often the same as process_name but can differ. Max 15 chars. + */ + trigger_process_name?: string; + } + + export namespace Data { + export interface TopTask { + /** + * Comm of the process (max 15 chars, truncated by the kernel). + */ + name: string; + + /** + * PID of the process. + */ + pid: number; + + /** + * Resident set size in KiB at the moment of the kill. + */ + rss_kb: number; + } + } +} + +/** + * Per-category telemetry capture settings. Selection is opt-in: set a category to + * enabled=true to capture it; anything omitted is off. The default set (used by + * enabled=true with no per-category settings) is the lightweight operational + * signals: control, connection, system, captcha. The CDP categories (console, + * network, page, interaction) and screenshot are off by default and must be opted + * into. */ export interface BrowserTelemetryCategoriesConfig { /** - * Console output (log, warn, error) and uncaught exceptions. + * Captcha solve attempt outcomes. On by default. + */ + captcha?: BrowserTelemetryCategoryConfig; + + /** + * Client attach/detach lifecycle for the CDP proxy and live view. On by default. + */ + connection?: BrowserTelemetryCategoryConfig; + + /** + * Console output (log, warn, error) and uncaught exceptions. CDP category; off by + * default. */ console?: BrowserTelemetryCategoryConfig; + /** + * Agent-driven actions against the browser, such as inbound calls to the in-VM + * API. On by default. + */ + control?: BrowserTelemetryCategoryConfig; + /** * User interaction events including clicks, keydowns, and scroll-settled events. + * CDP category; off by default. */ interaction?: BrowserTelemetryCategoryConfig; @@ -1434,15 +1886,28 @@ export interface BrowserTelemetryCategoriesConfig { * HTTP request and response metadata including URL, method, status code, and * timing. Request post data is forwarded as-is from CDP. Text response bodies are * truncated at 8 KB for structured types (JSON, XML, form data) and 4 KB for other - * text types. Binary responses (images, fonts, media) are excluded. + * text types. Binary responses (images, fonts, media) are excluded. CDP category; + * off by default. */ network?: BrowserTelemetryCategoryConfig; /** * Page lifecycle events including navigation, DOMContentLoaded, load, layout - * shifts, and LCP. + * shifts, and LCP. CDP category; off by default. */ page?: BrowserTelemetryCategoryConfig; + + /** + * Periodic base64-encoded viewport screenshots. High volume; off by default and + * must be opted into. + */ + screenshot?: BrowserTelemetryCategoryConfig; + + /** + * Browser VM health, such as out-of-memory kills and managed-service crashes. On + * by default. + */ + system?: BrowserTelemetryCategoryConfig; } /** @@ -1450,7 +1915,8 @@ export interface BrowserTelemetryCategoriesConfig { */ export interface BrowserTelemetryCategoryConfig { /** - * Whether this category is captured. Defaults to true if omitted. + * Whether this category is captured. Selection is opt-in, so an omitted category + * is not captured. */ enabled?: boolean; } @@ -1467,10 +1933,13 @@ export interface BrowserTelemetryConfig { /** * Union type representing any browser telemetry event. Discriminated on `type`. - * Events with a `monitor_` prefix (monitor_screenshot, monitor_disconnected, - * monitor_reconnected, monitor_reconnect_failed, monitor_init_failed) are always - * emitted regardless of the category configuration in BrowserTelemetryConfig. All - * other event types are controlled by the per-category enable/disable flags. + * Each event's `category` determines when it is captured. The CDP collector-health + * events (monitor_disconnected, monitor_reconnected, monitor_reconnect_failed, + * monitor_init_failed) use the `monitor` category, which is not user-configurable: + * it flows automatically whenever any CDP category (console, network, page, + * interaction) is captured, and is silent otherwise. monitor_screenshot uses the + * opt-in `screenshot` category. All other event types are controlled by their + * per-category enable/disable flags. */ export type BrowserTelemetryEvent = | BrowserConsoleLogEvent @@ -1494,7 +1963,15 @@ export type BrowserTelemetryEvent = | BrowserMonitorDisconnectedEvent | BrowserMonitorReconnectedEvent | BrowserMonitorReconnectFailedEvent - | BrowserMonitorInitFailedEvent; + | BrowserMonitorInitFailedEvent + | BrowserAPICallEvent + | BrowserCdpConnectEvent + | BrowserCdpDisconnectEvent + | BrowserLiveViewConnectEvent + | BrowserLiveViewDisconnectEvent + | BrowserCaptchaSolveResultEvent + | BrowserSystemOomKillEvent + | BrowserServiceCrashedEvent; /** * Envelope wrapping a browser telemetry event with its monotonic sequence number. @@ -1504,10 +1981,13 @@ export type BrowserTelemetryEvent = export interface TelemetryStreamResponse { /** * Union type representing any browser telemetry event. Discriminated on `type`. - * Events with a `monitor_` prefix (monitor_screenshot, monitor_disconnected, - * monitor_reconnected, monitor_reconnect_failed, monitor_init_failed) are always - * emitted regardless of the category configuration in BrowserTelemetryConfig. All - * other event types are controlled by the per-category enable/disable flags. + * Each event's `category` determines when it is captured. The CDP collector-health + * events (monitor_disconnected, monitor_reconnected, monitor_reconnect_failed, + * monitor_init_failed) use the `monitor` category, which is not user-configurable: + * it flows automatically whenever any CDP category (console, network, page, + * interaction) is captured, and is silent otherwise. monitor_screenshot uses the + * opt-in `screenshot` category. All other event types are controlled by their + * per-category enable/disable flags. */ event: BrowserTelemetryEvent; @@ -1529,7 +2009,11 @@ export interface TelemetryStreamParams { export declare namespace Telemetry { export { + type BrowserAPICallEvent as BrowserAPICallEvent, type BrowserCallStack as BrowserCallStack, + type BrowserCaptchaSolveResultEvent as BrowserCaptchaSolveResultEvent, + type BrowserCdpConnectEvent as BrowserCdpConnectEvent, + type BrowserCdpDisconnectEvent as BrowserCdpDisconnectEvent, type BrowserConsoleErrorEvent as BrowserConsoleErrorEvent, type BrowserConsoleLogEvent as BrowserConsoleLogEvent, type BrowserEventContext as BrowserEventContext, @@ -1538,6 +2022,8 @@ export declare namespace Telemetry { type BrowserInteractionClickEvent as BrowserInteractionClickEvent, type BrowserInteractionKeyEvent as BrowserInteractionKeyEvent, type BrowserInteractionScrollSettledEvent as BrowserInteractionScrollSettledEvent, + type BrowserLiveViewConnectEvent as BrowserLiveViewConnectEvent, + type BrowserLiveViewDisconnectEvent as BrowserLiveViewDisconnectEvent, type BrowserMonitorDisconnectedEvent as BrowserMonitorDisconnectedEvent, type BrowserMonitorInitFailedEvent as BrowserMonitorInitFailedEvent, type BrowserMonitorReconnectFailedEvent as BrowserMonitorReconnectFailedEvent, @@ -1555,6 +2041,8 @@ export declare namespace Telemetry { type BrowserPageNavigationEvent as BrowserPageNavigationEvent, type BrowserPageNavigationSettledEvent as BrowserPageNavigationSettledEvent, type BrowserPageTabOpenedEvent as BrowserPageTabOpenedEvent, + type BrowserServiceCrashedEvent as BrowserServiceCrashedEvent, + type BrowserSystemOomKillEvent as BrowserSystemOomKillEvent, type BrowserTelemetryCategoriesConfig as BrowserTelemetryCategoriesConfig, type BrowserTelemetryCategoryConfig as BrowserTelemetryCategoryConfig, type BrowserTelemetryConfig as BrowserTelemetryConfig, diff --git a/tests/api-resources/browsers/browsers.test.ts b/tests/api-resources/browsers/browsers.test.ts index 0d2e506e..689bf85b 100644 --- a/tests/api-resources/browsers/browsers.test.ts +++ b/tests/api-resources/browsers/browsers.test.ts @@ -44,10 +44,15 @@ describe('resource browsers', () => { tags: { team: 'backend', env: 'staging' }, telemetry: { browser: { + captcha: { enabled: true }, + connection: { enabled: true }, console: { enabled: true }, + control: { enabled: true }, interaction: { enabled: true }, network: { enabled: true }, page: { enabled: true }, + screenshot: { enabled: true }, + system: { enabled: true }, }, enabled: true, }, From 76f7aa56f91bfd39a717e50287fcfe00a9a77ea0 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 8 Jun 2026 16:28:06 +0000 Subject: [PATCH 432/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 12bb1a5c..b611d1b5 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.63.0" + ".": "0.64.0" } diff --git a/package.json b/package.json index b0191e22..bf1cdb0e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.63.0", + "version": "0.64.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 3abb4d11..40872bf3 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.63.0'; // x-release-please-version +export const VERSION = '0.64.0'; // x-release-please-version From 23fa224367fba7e5306f5e4f798487260451c111 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 8 Jun 2026 19:03:37 +0000 Subject: [PATCH 433/551] feat(api): allow setting a name and tags on a pool-acquired browser session --- .stats.yml | 4 ++-- src/resources/browser-pools.ts | 15 +++++++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index d9e97532..cd599894 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 117 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-9d489e3e43edfa64a754d4281241718e01c85d9a82ef3687df12bbd3c4ff5b42.yml -openapi_spec_hash: a953cafb7f40ec8495dbd7df8bab8bad +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-662a9d6352d842f37e06e0197a61fe10850483302650713345d45780b3128343.yml +openapi_spec_hash: e65977d16d95d48c75d02a1133131149 config_hash: bb7acce8576a50dd449b0c8f58ef0f1d diff --git a/src/resources/browser-pools.ts b/src/resources/browser-pools.ts index 06e6832b..4b8ba393 100644 --- a/src/resources/browser-pools.ts +++ b/src/resources/browser-pools.ts @@ -626,6 +626,21 @@ export interface BrowserPoolAcquireParams { * rate. */ acquire_timeout_seconds?: number; + + /** + * Optional human-readable name for the acquired browser session, used to find it + * later in the dashboard. Must be unique among active sessions within the pool's + * project. Applies to this lease only and is cleared when the browser is released + * back to the pool. + */ + name?: string; + + /** + * Optional user-defined key-value tags for the acquired browser session, used to + * find and group sessions later. Applies to this lease only and are cleared when + * the browser is released back to the pool. Up to 50 pairs. + */ + tags?: BrowsersAPI.Tags; } export interface BrowserPoolReleaseParams { From f2f421662e1da1c9700b03dd3fd2534e99f5c5fe Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 8 Jun 2026 20:24:59 +0000 Subject: [PATCH 434/551] feat(api): support id-or-name lookup on browser session get/patch/delete --- .stats.yml | 6 +++--- api.md | 6 +++--- src/resources/browsers/browsers.ts | 18 +++++++++++------- 3 files changed, 17 insertions(+), 13 deletions(-) diff --git a/.stats.yml b/.stats.yml index cd599894..dcde96de 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 117 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-662a9d6352d842f37e06e0197a61fe10850483302650713345d45780b3128343.yml -openapi_spec_hash: e65977d16d95d48c75d02a1133131149 -config_hash: bb7acce8576a50dd449b0c8f58ef0f1d +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-08c2d6a44f4cdcbfb6803a3043fdc1a3e33911dec4652cb3a870f01bc584421f.yml +openapi_spec_hash: c816491451347eb93b793cddf6a78648 +config_hash: 9e45c27425021d49b5391f5cc980b046 diff --git a/api.md b/api.md index 4625155d..1568486e 100644 --- a/api.md +++ b/api.md @@ -79,11 +79,11 @@ Types: Methods: - client.browsers.create({ ...params }) -> BrowserCreateResponse -- client.browsers.retrieve(id, { ...params }) -> BrowserRetrieveResponse -- client.browsers.update(id, { ...params }) -> BrowserUpdateResponse +- client.browsers.retrieve(idOrName, { ...params }) -> BrowserRetrieveResponse +- client.browsers.update(idOrName, { ...params }) -> BrowserUpdateResponse - client.browsers.list({ ...params }) -> BrowserListResponsesOffsetPagination - client.browsers.curl(id, { ...params }) -> BrowserCurlResponse -- client.browsers.deleteByID(id) -> void +- client.browsers.deleteByID(idOrName) -> void - client.browsers.loadExtensions(id, { ...params }) -> void ## Telemetry diff --git a/src/resources/browsers/browsers.ts b/src/resources/browsers/browsers.ts index 39c317b8..ad888b75 100644 --- a/src/resources/browsers/browsers.ts +++ b/src/resources/browsers/browsers.ts @@ -158,11 +158,11 @@ export class Browsers extends APIResource { * ``` */ retrieve( - id: string, + idOrName: string, query: BrowserRetrieveParams | null | undefined = {}, options?: RequestOptions, ): APIPromise { - return this._client.get(path`/browsers/${id}`, { query, ...options }); + return this._client.get(path`/browsers/${idOrName}`, { query, ...options }); } /** @@ -175,8 +175,12 @@ export class Browsers extends APIResource { * ); * ``` */ - update(id: string, body: BrowserUpdateParams, options?: RequestOptions): APIPromise { - return this._client.patch(path`/browsers/${id}`, { body, ...options }); + update( + idOrName: string, + body: BrowserUpdateParams, + options?: RequestOptions, + ): APIPromise { + return this._client.patch(path`/browsers/${idOrName}`, { body, ...options }); } /** @@ -215,7 +219,7 @@ export class Browsers extends APIResource { } /** - * Delete a browser session by ID + * Delete a browser session by ID or name * * @example * ```ts @@ -224,8 +228,8 @@ export class Browsers extends APIResource { * ); * ``` */ - deleteByID(id: string, options?: RequestOptions): APIPromise { - return this._client.delete(path`/browsers/${id}`, { + deleteByID(idOrName: string, options?: RequestOptions): APIPromise { + return this._client.delete(path`/browsers/${idOrName}`, { ...options, headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), }); From 55c3497bee5f9b4b33fd0f8f2a085b2d79376fac Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 8 Jun 2026 23:29:25 +0000 Subject: [PATCH 435/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index b611d1b5..59cbd40d 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.64.0" + ".": "0.65.0" } diff --git a/package.json b/package.json index bf1cdb0e..ea0fdfe7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.64.0", + "version": "0.65.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 40872bf3..7ebe654f 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.64.0'; // x-release-please-version +export const VERSION = '0.65.0'; // x-release-please-version From 17bb2aa6d10194ac247765bf2027da1aabf72e6c Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 9 Jun 2026 18:59:17 +0000 Subject: [PATCH 436/551] feat: Add org-level default per-project concurrency cap --- .stats.yml | 8 +-- api.md | 14 ++++ src/client.ts | 5 ++ src/resources/index.ts | 1 + src/resources/organization.ts | 3 + src/resources/organization/index.ts | 4 ++ src/resources/organization/limits.ts | 71 +++++++++++++++++++ src/resources/organization/organization.ts | 20 ++++++ .../api-resources/organization/limits.test.ts | 34 +++++++++ 9 files changed, 156 insertions(+), 4 deletions(-) create mode 100644 src/resources/organization.ts create mode 100644 src/resources/organization/index.ts create mode 100644 src/resources/organization/limits.ts create mode 100644 src/resources/organization/organization.ts create mode 100644 tests/api-resources/organization/limits.test.ts diff --git a/.stats.yml b/.stats.yml index dcde96de..fc334e13 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 117 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-08c2d6a44f4cdcbfb6803a3043fdc1a3e33911dec4652cb3a870f01bc584421f.yml -openapi_spec_hash: c816491451347eb93b793cddf6a78648 -config_hash: 9e45c27425021d49b5391f5cc980b046 +configured_endpoints: 119 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-76f6c461ca9fd01958f3315a4f5d558ef80896c8aa0496e38caef55d4bd51dbd.yml +openapi_spec_hash: bb8124b6016b73022c52e6ef5b7220a4 +config_hash: 80eef1b592110714ea55cd26c470fabb diff --git a/api.md b/api.md index 1568486e..79b92058 100644 --- a/api.md +++ b/api.md @@ -375,6 +375,20 @@ Methods: - client.projects.limits.retrieve(id) -> ProjectLimits - client.projects.limits.update(id, { ...params }) -> ProjectLimits +# Organization + +## Limits + +Types: + +- OrgLimits +- UpdateOrgLimitsRequest + +Methods: + +- client.organization.limits.retrieve() -> OrgLimits +- client.organization.limits.update({ ...params }) -> OrgLimits + # APIKeys Types: diff --git a/src/client.ts b/src/client.ts index 9a215e06..43446350 100644 --- a/src/client.ts +++ b/src/client.ts @@ -133,6 +133,7 @@ import { Profile, Tags, } from './resources/browsers/browsers'; +import { Organization } from './resources/organization/organization'; import { CreateProjectRequest, Project, @@ -941,6 +942,7 @@ export class Kernel { * Create and manage projects for resource isolation within an organization. */ projects: API.Projects = new API.Projects(this); + organization: API.Organization = new API.Organization(this); /** * Create and manage API keys for organization and project-scoped access. */ @@ -962,6 +964,7 @@ Kernel.Extensions = Extensions; Kernel.BrowserPools = BrowserPools; Kernel.Credentials = Credentials; Kernel.Projects = Projects; +Kernel.Organization = Organization; Kernel.APIKeys = APIKeys; Kernel.CredentialProviders = CredentialProviders; @@ -1096,6 +1099,8 @@ export declare namespace Kernel { type ProjectListParams as ProjectListParams, }; + export { Organization as Organization }; + export { APIKeys as APIKeys, type APIKey as APIKey, diff --git a/src/resources/index.ts b/src/resources/index.ts index d92fde23..491319db 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -109,6 +109,7 @@ export { type InvocationFollowParams, type InvocationListResponsesOffsetPagination, } from './invocations'; +export { Organization } from './organization/organization'; export { Profiles, type ProfileCreateParams, type ProfileListParams } from './profiles'; export { Projects, diff --git a/src/resources/organization.ts b/src/resources/organization.ts new file mode 100644 index 00000000..4e74c0d4 --- /dev/null +++ b/src/resources/organization.ts @@ -0,0 +1,3 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export * from './organization/index'; diff --git a/src/resources/organization/index.ts b/src/resources/organization/index.ts new file mode 100644 index 00000000..48c5622b --- /dev/null +++ b/src/resources/organization/index.ts @@ -0,0 +1,4 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export { Limits, type OrgLimits, type UpdateOrgLimitsRequest, type LimitUpdateParams } from './limits'; +export { Organization } from './organization'; diff --git a/src/resources/organization/limits.ts b/src/resources/organization/limits.ts new file mode 100644 index 00000000..53f2f5c0 --- /dev/null +++ b/src/resources/organization/limits.ts @@ -0,0 +1,71 @@ +// 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 { RequestOptions } from '../../internal/request-options'; + +/** + * Read and manage organization-level limits. + */ +export class Limits extends APIResource { + /** + * Get the organization's concurrent session ceiling and the default per-project + * concurrency cap applied to projects without an explicit override. + */ + retrieve(options?: RequestOptions): APIPromise { + return this._client.get('/org/limits', options); + } + + /** + * Set the default per-project concurrency cap applied to projects without an + * explicit override. Set the value to 0 to remove the default; omit to leave it + * unchanged. The default cannot exceed the organization's concurrent session + * ceiling. + */ + update(body: LimitUpdateParams, options?: RequestOptions): APIPromise { + return this._client.patch('/org/limits', { body, ...options }); + } +} + +export interface OrgLimits { + /** + * Default maximum concurrent browser sessions applied to every project that has no + * explicit per-project override. Null means no org-level default, so such projects + * are uncapped (only the org-wide limit applies). Applies to existing and newly + * created projects. + */ + default_project_max_concurrent_sessions?: number | null; + + /** + * The organization's effective concurrent browser session ceiling, from its plan + * or an override. Read-only and shared across all projects in the org; a + * per-project default cannot exceed it. + */ + max_concurrent_sessions?: number; +} + +export interface UpdateOrgLimitsRequest { + /** + * Default maximum concurrent browser sessions for projects without an explicit + * override. Set to 0 to remove the default; omit to leave unchanged. Cannot exceed + * the organization's concurrent session ceiling. + */ + default_project_max_concurrent_sessions?: number | null; +} + +export interface LimitUpdateParams { + /** + * Default maximum concurrent browser sessions for projects without an explicit + * override. Set to 0 to remove the default; omit to leave unchanged. Cannot exceed + * the organization's concurrent session ceiling. + */ + default_project_max_concurrent_sessions?: number | null; +} + +export declare namespace Limits { + export { + type OrgLimits as OrgLimits, + type UpdateOrgLimitsRequest as UpdateOrgLimitsRequest, + type LimitUpdateParams as LimitUpdateParams, + }; +} diff --git a/src/resources/organization/organization.ts b/src/resources/organization/organization.ts new file mode 100644 index 00000000..4f29b5b7 --- /dev/null +++ b/src/resources/organization/organization.ts @@ -0,0 +1,20 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../core/resource'; +import * as LimitsAPI from './limits'; +import { LimitUpdateParams, Limits, OrgLimits, UpdateOrgLimitsRequest } from './limits'; + +export class Organization extends APIResource { + limits: LimitsAPI.Limits = new LimitsAPI.Limits(this._client); +} + +Organization.Limits = Limits; + +export declare namespace Organization { + export { + Limits as Limits, + type OrgLimits as OrgLimits, + type UpdateOrgLimitsRequest as UpdateOrgLimitsRequest, + type LimitUpdateParams as LimitUpdateParams, + }; +} diff --git a/tests/api-resources/organization/limits.test.ts b/tests/api-resources/organization/limits.test.ts new file mode 100644 index 00000000..9fe090a4 --- /dev/null +++ b/tests/api-resources/organization/limits.test.ts @@ -0,0 +1,34 @@ +// 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 limits', () => { + // Mock server tests are disabled + test.skip('retrieve', async () => { + const responsePromise = client.organization.limits.retrieve(); + 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); + }); + + // Mock server tests are disabled + test.skip('update', async () => { + const responsePromise = client.organization.limits.update({}); + 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); + }); +}); From 09a15b419e60f86f1f68c3be390b64798a6d447c Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 9 Jun 2026 21:31:42 +0000 Subject: [PATCH 437/551] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index fc334e13..17293bfb 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 119 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-76f6c461ca9fd01958f3315a4f5d558ef80896c8aa0496e38caef55d4bd51dbd.yml -openapi_spec_hash: bb8124b6016b73022c52e6ef5b7220a4 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-f9a96fe14f0b3c93230a26f9b64827a35a19a28d4e7cd2719315c4d76cce78fc.yml +openapi_spec_hash: 852e2a64b850f759ccbcf81b1579497a config_hash: 80eef1b592110714ea55cd26c470fabb From 64897b95dd3c737f10cb041b68bc2a232137943e Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 10 Jun 2026 20:41:49 +0000 Subject: [PATCH 438/551] feat: Support updating browser session name and tags via PATCH --- .stats.yml | 4 ++-- src/resources/browsers/browsers.ts | 21 ++++++++++++++++++--- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/.stats.yml b/.stats.yml index 17293bfb..5ad69241 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 119 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-f9a96fe14f0b3c93230a26f9b64827a35a19a28d4e7cd2719315c4d76cce78fc.yml -openapi_spec_hash: 852e2a64b850f759ccbcf81b1579497a +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-e66c3f8aedccc39104386a3ec619f3fdcef7e8b00d9e5aa82e414a1b387351c2.yml +openapi_spec_hash: afeddf18ebc3da1521b3e6f6739411fa config_hash: 80eef1b592110714ea55cd26c470fabb diff --git a/src/resources/browsers/browsers.ts b/src/resources/browsers/browsers.ts index ad888b75..708a1e15 100644 --- a/src/resources/browsers/browsers.ts +++ b/src/resources/browsers/browsers.ts @@ -918,8 +918,8 @@ export interface BrowserCreateParams { /** * Optional human-readable name for the browser session, used to find it later in - * the dashboard. Must be unique among active sessions within the project. Set at - * creation time only. + * the dashboard. Must be unique among active sessions within the project. Can be + * changed later via PATCH /browsers/{id_or_name}. */ name?: string; @@ -951,7 +951,8 @@ export interface BrowserCreateParams { /** * Optional user-defined key-value tags for the browser session, used to find and - * group sessions later. Set at creation time only. Up to 50 pairs. + * group sessions later. Can be changed later via PATCH /browsers/{id_or_name}. Up + * to 50 pairs. */ tags?: Tags; @@ -1031,6 +1032,13 @@ export interface BrowserUpdateParams { */ disable_default_proxy?: boolean; + /** + * Human-readable name for the browser session. Omit to leave unchanged, set to an + * empty string to clear the name. When set, must be unique among active sessions + * within the project. + */ + name?: string | null; + /** * Profile to load into the browser session. Only allowed if the session does not * already have a profile loaded. @@ -1043,6 +1051,13 @@ export interface BrowserUpdateParams { */ proxy_id?: string | null; + /** + * User-defined key-value tags for the browser session. Omit to leave unchanged. + * Provide a map to replace the entire tag set (full replace, not a merge). Set to + * an empty object ({}) to clear all tags. Up to 50 pairs. + */ + tags?: Tags | null; + /** * Telemetry configuration. Omit, set to null, or set to an empty object ({}) to * leave the existing configuration unchanged. Set enabled to true to enable From c1b518e57aaf834d55a5ae88581ee7997e3449cc Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 10 Jun 2026 21:14:40 +0000 Subject: [PATCH 439/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 59cbd40d..7b24d85b 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.65.0" + ".": "0.66.0" } diff --git a/package.json b/package.json index ea0fdfe7..722c6b89 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.65.0", + "version": "0.66.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 7ebe654f..98269868 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.65.0'; // x-release-please-version +export const VERSION = '0.66.0'; // x-release-please-version From a50f58153eb86107a94b52ec864c397ad9c93b6e Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 11 Jun 2026 19:08:24 +0000 Subject: [PATCH 440/551] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 5ad69241..f6e3d871 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 119 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-e66c3f8aedccc39104386a3ec619f3fdcef7e8b00d9e5aa82e414a1b387351c2.yml -openapi_spec_hash: afeddf18ebc3da1521b3e6f6739411fa +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-663f08b43eda6383b99ab0f3b1cd049d62f22c81daf149d8e84ff18f53c84c89.yml +openapi_spec_hash: 29ea250251cc14d70e3f8f737ebc1466 config_hash: 80eef1b592110714ea55cd26c470fabb From b32ff8e14c5971b46109ae13941598c08da47cb3 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 11 Jun 2026 19:42:21 +0000 Subject: [PATCH 441/551] docs(api): correct project-scoping descriptions in OpenAPI spec --- .stats.yml | 4 +-- src/resources/auth/connections.ts | 40 +++++++++++++++--------------- src/resources/browser-pools.ts | 14 +++++------ src/resources/browsers/browsers.ts | 4 +-- src/resources/credentials.ts | 3 +-- src/resources/extensions.ts | 2 +- src/resources/proxies.ts | 6 ++--- 7 files changed, 36 insertions(+), 37 deletions(-) diff --git a/.stats.yml b/.stats.yml index f6e3d871..1d17b2b3 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 119 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-663f08b43eda6383b99ab0f3b1cd049d62f22c81daf149d8e84ff18f53c84c89.yml -openapi_spec_hash: 29ea250251cc14d70e3f8f737ebc1466 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-c6458d9c6cb5d7e3d8309c79b69eba3a22269e0ecc0bdafbaee00fde4b302e99.yml +openapi_spec_hash: ee77b293c4bda91c1a32cfdd12b8739e config_hash: 80eef1b592110714ea55cd26c470fabb diff --git a/src/resources/auth/connections.ts b/src/resources/auth/connections.ts index 1c338deb..3ddd5080 100644 --- a/src/resources/auth/connections.ts +++ b/src/resources/auth/connections.ts @@ -699,8 +699,8 @@ export interface ManagedAuthCreateRequest { login_url?: string; /** - * Proxy selection. Provide either id or name. The proxy must belong to the - * caller's org. + * Proxy selection. Provide either id or name. The proxy must be in the same + * project as the resource referencing it. */ proxy?: ManagedAuthCreateRequest.Proxy; @@ -748,8 +748,8 @@ export namespace ManagedAuthCreateRequest { } /** - * Proxy selection. Provide either id or name. The proxy must belong to the - * caller's org. + * Proxy selection. Provide either id or name. The proxy must be in the same + * project as the resource referencing it. */ export interface Proxy { /** @@ -812,8 +812,8 @@ export interface ManagedAuthUpdateRequest { login_url?: string; /** - * Proxy selection. Provide either id or name. The proxy must belong to the - * caller's org. + * Proxy selection. Provide either id or name. The proxy must be in the same + * project as the resource referencing it. */ proxy?: ManagedAuthUpdateRequest.Proxy; @@ -859,8 +859,8 @@ export namespace ManagedAuthUpdateRequest { } /** - * Proxy selection. Provide either id or name. The proxy must belong to the - * caller's org. + * Proxy selection. Provide either id or name. The proxy must be in the same + * project as the resource referencing it. */ export interface Proxy { /** @@ -1215,8 +1215,8 @@ export interface ConnectionCreateParams { login_url?: string; /** - * Proxy selection. Provide either id or name. The proxy must belong to the - * caller's org. + * Proxy selection. Provide either id or name. The proxy must be in the same + * project as the resource referencing it. */ proxy?: ConnectionCreateParams.Proxy; @@ -1264,8 +1264,8 @@ export namespace ConnectionCreateParams { } /** - * Proxy selection. Provide either id or name. The proxy must belong to the - * caller's org. + * Proxy selection. Provide either id or name. The proxy must be in the same + * project as the resource referencing it. */ export interface Proxy { /** @@ -1325,8 +1325,8 @@ export interface ConnectionUpdateParams { login_url?: string; /** - * Proxy selection. Provide either id or name. The proxy must belong to the - * caller's org. + * Proxy selection. Provide either id or name. The proxy must be in the same + * project as the resource referencing it. */ proxy?: ConnectionUpdateParams.Proxy; @@ -1372,8 +1372,8 @@ export namespace ConnectionUpdateParams { } /** - * Proxy selection. Provide either id or name. The proxy must belong to the - * caller's org. + * Proxy selection. Provide either id or name. The proxy must be in the same + * project as the resource referencing it. */ export interface Proxy { /** @@ -1402,8 +1402,8 @@ export interface ConnectionListParams extends OffsetPaginationParams { export interface ConnectionLoginParams { /** - * Proxy selection. Provide either id or name. The proxy must belong to the - * caller's org. + * Proxy selection. Provide either id or name. The proxy must be in the same + * project as the resource referencing it. */ proxy?: ConnectionLoginParams.Proxy; @@ -1416,8 +1416,8 @@ export interface ConnectionLoginParams { export namespace ConnectionLoginParams { /** - * Proxy selection. Provide either id or name. The proxy must belong to the - * caller's org. + * Proxy selection. Provide either id or name. The proxy must be in the same + * project as the resource referencing it. */ export interface Proxy { /** diff --git a/src/resources/browser-pools.ts b/src/resources/browser-pools.ts index 4b8ba393..a22174da 100644 --- a/src/resources/browser-pools.ts +++ b/src/resources/browser-pools.ts @@ -57,7 +57,7 @@ export class BrowserPools extends APIResource { } /** - * List browser pools owned by the caller's organization. + * List browser pools in the resolved project. * * @example * ```ts @@ -241,8 +241,8 @@ export namespace BrowserPool { profile?: Shared.BrowserProfile; /** - * Optional proxy to associate to the browser session. Must reference a proxy - * belonging to the caller's org. + * Optional proxy to associate to the browser session. Must reference a proxy in + * the same project as the browser session. */ proxy_id?: string; @@ -467,8 +467,8 @@ export interface BrowserPoolCreateParams { profile?: Shared.BrowserProfile; /** - * Optional proxy to associate to the browser session. Must reference a proxy - * belonging to the caller's org. + * Optional proxy to associate to the browser session. Must reference a proxy in + * the same project as the browser session. */ proxy_id?: string; @@ -559,8 +559,8 @@ export interface BrowserPoolUpdateParams { profile?: Shared.BrowserProfile; /** - * Optional proxy to associate to the browser session. Must reference a proxy - * belonging to the caller's org. + * Optional proxy to associate to the browser session. Must reference a proxy in + * the same project as the browser session. */ proxy_id?: string; diff --git a/src/resources/browsers/browsers.ts b/src/resources/browsers/browsers.ts index 708a1e15..3a395dea 100644 --- a/src/resources/browsers/browsers.ts +++ b/src/resources/browsers/browsers.ts @@ -931,8 +931,8 @@ export interface BrowserCreateParams { profile?: Shared.BrowserProfile; /** - * Optional proxy to associate to the browser session. Must reference a proxy - * belonging to the caller's org. + * Optional proxy to associate to the browser session. Must reference a proxy in + * the same project as the browser session. */ proxy_id?: string; diff --git a/src/resources/credentials.ts b/src/resources/credentials.ts index ef80c0dc..cd64d5e6 100644 --- a/src/resources/credentials.ts +++ b/src/resources/credentials.ts @@ -60,8 +60,7 @@ export class Credentials extends APIResource { } /** - * List credentials owned by the caller's organization. Credential values are not - * returned. + * List credentials in the resolved project. Credential values are not returned. * * @example * ```ts diff --git a/src/resources/extensions.ts b/src/resources/extensions.ts index e12233ed..0afbdd59 100644 --- a/src/resources/extensions.ts +++ b/src/resources/extensions.ts @@ -14,7 +14,7 @@ import { path } from '../internal/utils/path'; */ export class Extensions extends APIResource { /** - * List extensions owned by the caller's organization. + * List extensions in the resolved project. * * @example * ```ts diff --git a/src/resources/proxies.ts b/src/resources/proxies.ts index 833ae00a..274a0501 100644 --- a/src/resources/proxies.ts +++ b/src/resources/proxies.ts @@ -12,21 +12,21 @@ import { path } from '../internal/utils/path'; */ export class Proxies extends APIResource { /** - * Create a new proxy configuration for the caller's organization. + * Create a new proxy configuration in the resolved project. */ create(body: ProxyCreateParams, options?: RequestOptions): APIPromise { return this._client.post('/proxies', { body, ...options }); } /** - * Retrieve a proxy belonging to the caller's organization by ID. + * Retrieve a proxy in the resolved project by ID. */ retrieve(id: string, options?: RequestOptions): APIPromise { return this._client.get(path`/proxies/${id}`, options); } /** - * List proxies owned by the caller's organization. + * List proxies in the resolved project. */ list( query: ProxyListParams | null | undefined = {}, From fd7db54b43824ef9d120285d4aeb51551f79a03c Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 11 Jun 2026 21:01:05 +0000 Subject: [PATCH 442/551] feat: Add project_id SDK client option mapped to X-Kernel-Project-Id --- .stats.yml | 4 ++-- src/client.ts | 9 +++++++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 1d17b2b3..a1640098 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 119 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-c6458d9c6cb5d7e3d8309c79b69eba3a22269e0ecc0bdafbaee00fde4b302e99.yml +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-51549f813f3002e18c6ca8d850cc0c7932828d511c151e0412c73b6798d19e30.yml openapi_spec_hash: ee77b293c4bda91c1a32cfdd12b8739e -config_hash: 80eef1b592110714ea55cd26c470fabb +config_hash: 57567e00b41af47cef1b78e51b747aa0 diff --git a/src/client.ts b/src/client.ts index 43446350..de83f629 100644 --- a/src/client.ts +++ b/src/client.ts @@ -169,6 +169,8 @@ export interface ClientOptions { */ apiKey?: string | undefined; + projectID?: string | null | undefined; + /** * Specifies the environment to use for the API. * @@ -252,6 +254,7 @@ export interface ClientOptions { */ export class Kernel { apiKey: string; + projectID: string | null; baseURL: string; maxRetries: number; @@ -269,6 +272,7 @@ export class Kernel { * API Client for interfacing with the Kernel API. * * @param {string | undefined} [opts.apiKey=process.env['KERNEL_API_KEY'] ?? undefined] + * @param {string | null | undefined} [opts.projectID] * @param {Environment} [opts.environment=production] - Specifies the environment URL to use for the API. * @param {string} [opts.baseURL=process.env['KERNEL_BASE_URL'] ?? https://api.onkernel.com/] - Override the default base URL for the API. * @param {number} [opts.timeout=1 minute] - The maximum amount of time (in milliseconds) the client will wait for a response before timing out. @@ -281,6 +285,7 @@ export class Kernel { constructor({ baseURL = readEnv('KERNEL_BASE_URL'), apiKey = readEnv('KERNEL_API_KEY'), + projectID = null, ...opts }: ClientOptions = {}) { if (apiKey === undefined) { @@ -291,6 +296,7 @@ export class Kernel { const options: ClientOptions = { apiKey, + projectID, ...opts, baseURL, environment: opts.environment ?? 'production', @@ -332,6 +338,7 @@ export class Kernel { this._options = options; this.apiKey = apiKey; + this.projectID = projectID; } /** @@ -349,6 +356,7 @@ export class Kernel { fetch: this.fetch, fetchOptions: this.fetchOptions, apiKey: this.apiKey, + projectID: this.projectID, ...options, }); return client; @@ -819,6 +827,7 @@ export class Kernel { 'X-Stainless-Retry-Count': String(retryCount), ...(options.timeout ? { 'X-Stainless-Timeout': String(Math.trunc(options.timeout / 1000)) } : {}), ...getPlatformHeaders(), + 'X-Kernel-Project-Id': this.projectID, }, await this.authHeaders(options), this._options.defaultHeaders, From 5b57714b655504540686db60e0f8a3d52549132e Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 12 Jun 2026 14:38:35 +0000 Subject: [PATCH 443/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 7b24d85b..94994d4f 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.66.0" + ".": "0.67.0" } diff --git a/package.json b/package.json index 722c6b89..459f9eb3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.66.0", + "version": "0.67.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 98269868..ed32717a 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.66.0'; // x-release-please-version +export const VERSION = '0.67.0'; // x-release-please-version From 3a5ad0d4d4ce998a55193218be76b2cf406cf89c Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 12 Jun 2026 16:08:43 +0000 Subject: [PATCH 444/551] feat(api): surface deleted/expired API keys for audit trail (KERNEL-1350) --- .stats.yml | 4 ++-- api.md | 2 +- src/client.ts | 2 ++ src/resources/api-keys.ts | 36 ++++++++++++++++++++++++++-- src/resources/index.ts | 1 + tests/api-resources/api-keys.test.ts | 9 +++++++ 6 files changed, 49 insertions(+), 5 deletions(-) diff --git a/.stats.yml b/.stats.yml index a1640098..3ff52d98 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 119 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-51549f813f3002e18c6ca8d850cc0c7932828d511c151e0412c73b6798d19e30.yml -openapi_spec_hash: ee77b293c4bda91c1a32cfdd12b8739e +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-42074f2b600b0dc805377d6793e4bb30c959738b0f9cc44c409d094517e5e0ab.yml +openapi_spec_hash: 81c27a833d6d9637787634180dec2abd config_hash: 57567e00b41af47cef1b78e51b747aa0 diff --git a/api.md b/api.md index 79b92058..5c2fb0c5 100644 --- a/api.md +++ b/api.md @@ -399,7 +399,7 @@ Types: Methods: - client.apiKeys.create({ ...params }) -> CreatedAPIKey -- client.apiKeys.retrieve(id) -> APIKey +- client.apiKeys.retrieve(id, { ...params }) -> APIKey - client.apiKeys.update(id, { ...params }) -> APIKey - client.apiKeys.list({ ...params }) -> APIKeysOffsetPagination - client.apiKeys.delete(id) -> void diff --git a/src/client.ts b/src/client.ts index de83f629..316f4339 100644 --- a/src/client.ts +++ b/src/client.ts @@ -23,6 +23,7 @@ import { APIKey, APIKeyCreateParams, APIKeyListParams, + APIKeyRetrieveParams, APIKeyUpdateParams, APIKeys, APIKeysOffsetPagination, @@ -1116,6 +1117,7 @@ export declare namespace Kernel { type CreatedAPIKey as CreatedAPIKey, type APIKeysOffsetPagination as APIKeysOffsetPagination, type APIKeyCreateParams as APIKeyCreateParams, + type APIKeyRetrieveParams as APIKeyRetrieveParams, type APIKeyUpdateParams as APIKeyUpdateParams, type APIKeyListParams as APIKeyListParams, }; diff --git a/src/resources/api-keys.ts b/src/resources/api-keys.ts index a855c962..49c172bb 100644 --- a/src/resources/api-keys.ts +++ b/src/resources/api-keys.ts @@ -34,8 +34,12 @@ export class APIKeys extends APIResource { * const apiKey = await client.apiKeys.retrieve('id'); * ``` */ - retrieve(id: string, options?: RequestOptions): APIPromise { - return this._client.get(path`/org/api_keys/${id}`, options); + retrieve( + id: string, + query: APIKeyRetrieveParams | null | undefined = {}, + options?: RequestOptions, + ): APIPromise { + return this._client.get(path`/org/api_keys/${id}`, { query, ...options }); } /** @@ -101,6 +105,12 @@ export interface APIKey { created_by: APIKey.CreatedBy; + /** + * When the API key was deleted (soft-deleted). Null for keys that have not been + * deleted. + */ + deleted_at: string | null; + /** * When the API key expires */ @@ -126,6 +136,13 @@ export interface APIKey { * project name is unavailable. */ project_name: string | null; + + /** + * Derived lifecycle status of the API key. `active` means usable. `expired` means + * past its expires_at. `deleted` means it was deleted (soft-deleted) and can no + * longer authenticate. Deleted takes precedence over expired. + */ + status: 'active' | 'expired' | 'deleted'; } export namespace APIKey { @@ -174,6 +191,14 @@ export interface APIKeyCreateParams { project_id?: string | null; } +export interface APIKeyRetrieveParams { + /** + * When true, return the API key even if it has been deleted (soft-deleted), for + * audit purposes. Defaults to false, which returns 404 for a deleted key. + */ + include_deleted?: boolean; +} + export interface APIKeyUpdateParams { /** * New API key name @@ -182,6 +207,12 @@ export interface APIKeyUpdateParams { } export interface APIKeyListParams extends OffsetPaginationParams { + /** + * When true, include deleted (soft-deleted) API keys in the results for audit + * purposes. Defaults to false, which returns only live keys. + */ + include_deleted?: boolean; + /** * Case-insensitive substring match against API key name, creator, and project. API * key identifiers and masked keys match by exact value or prefix. @@ -205,6 +236,7 @@ export declare namespace APIKeys { type CreatedAPIKey as CreatedAPIKey, type APIKeysOffsetPagination as APIKeysOffsetPagination, type APIKeyCreateParams as APIKeyCreateParams, + type APIKeyRetrieveParams as APIKeyRetrieveParams, type APIKeyUpdateParams as APIKeyUpdateParams, type APIKeyListParams as APIKeyListParams, }; diff --git a/src/resources/index.ts b/src/resources/index.ts index 491319db..b73f26f3 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -6,6 +6,7 @@ export { type APIKey, type CreatedAPIKey, type APIKeyCreateParams, + type APIKeyRetrieveParams, type APIKeyUpdateParams, type APIKeyListParams, type APIKeysOffsetPagination, diff --git a/tests/api-resources/api-keys.test.ts b/tests/api-resources/api-keys.test.ts index 14a45a0d..1dbeb3e7 100644 --- a/tests/api-resources/api-keys.test.ts +++ b/tests/api-resources/api-keys.test.ts @@ -41,6 +41,14 @@ describe('resource apiKeys', () => { expect(dataAndResponse.response).toBe(rawResponse); }); + // Mock server tests are disabled + test.skip('retrieve: 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.apiKeys.retrieve('id', { include_deleted: true }, { path: '/_stainless_unknown_path' }), + ).rejects.toThrow(Kernel.NotFoundError); + }); + // Mock server tests are disabled test.skip('update: only required params', async () => { const responsePromise = client.apiKeys.update('id', { name: 'new-api-name' }); @@ -76,6 +84,7 @@ describe('resource apiKeys', () => { await expect( client.apiKeys.list( { + include_deleted: true, limit: 100, offset: 0, query: 'query', From 8001581e8433f1b22a3813ca4129682c74eebb53 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 12 Jun 2026 19:04:31 +0000 Subject: [PATCH 445/551] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 3ff52d98..ab902c2f 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 119 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-42074f2b600b0dc805377d6793e4bb30c959738b0f9cc44c409d094517e5e0ab.yml -openapi_spec_hash: 81c27a833d6d9637787634180dec2abd +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-c98841235b0ece0591f28f7dd424339b6ef2f3e8f539b95b670ae0da2ef43df4.yml +openapi_spec_hash: c1e9456765f0743a333af297d135d5cf config_hash: 57567e00b41af47cef1b78e51b747aa0 From 949509203e6102c86665443a43f8fe55f28b67d3 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sun, 14 Jun 2026 19:09:00 +0000 Subject: [PATCH 446/551] feat: Add API key rotate endpoint --- .stats.yml | 8 +++---- api.md | 1 + src/client.ts | 2 ++ src/resources/api-keys.ts | 33 ++++++++++++++++++++++++++++ src/resources/index.ts | 1 + tests/api-resources/api-keys.test.ts | 24 ++++++++++++++++++++ 6 files changed, 65 insertions(+), 4 deletions(-) diff --git a/.stats.yml b/.stats.yml index ab902c2f..8d8fe88a 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 119 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-c98841235b0ece0591f28f7dd424339b6ef2f3e8f539b95b670ae0da2ef43df4.yml -openapi_spec_hash: c1e9456765f0743a333af297d135d5cf -config_hash: 57567e00b41af47cef1b78e51b747aa0 +configured_endpoints: 120 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-1f10598afa01d76d22b0ed63685248f482f74c9353cffe1d3e4a3d38da7716cf.yml +openapi_spec_hash: 8936f458bfa681b709e459ca1cc76fb5 +config_hash: 03c7e57f268c750e2415831662e95969 diff --git a/api.md b/api.md index 5c2fb0c5..7a48707d 100644 --- a/api.md +++ b/api.md @@ -403,6 +403,7 @@ Methods: - client.apiKeys.update(id, { ...params }) -> APIKey - client.apiKeys.list({ ...params }) -> APIKeysOffsetPagination - client.apiKeys.delete(id) -> void +- client.apiKeys.rotate(id, { ...params }) -> CreatedAPIKey # CredentialProviders diff --git a/src/client.ts b/src/client.ts index 316f4339..50d419a5 100644 --- a/src/client.ts +++ b/src/client.ts @@ -24,6 +24,7 @@ import { APIKeyCreateParams, APIKeyListParams, APIKeyRetrieveParams, + APIKeyRotateParams, APIKeyUpdateParams, APIKeys, APIKeysOffsetPagination, @@ -1120,6 +1121,7 @@ export declare namespace Kernel { type APIKeyRetrieveParams as APIKeyRetrieveParams, type APIKeyUpdateParams as APIKeyUpdateParams, type APIKeyListParams as APIKeyListParams, + type APIKeyRotateParams as APIKeyRotateParams, }; export { diff --git a/src/resources/api-keys.ts b/src/resources/api-keys.ts index 49c172bb..7dc62e6d 100644 --- a/src/resources/api-keys.ts +++ b/src/resources/api-keys.ts @@ -88,6 +88,24 @@ export class APIKeys extends APIResource { headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), }); } + + /** + * Rotate an API key. Issues a new key that copies the name and project of the + * rotated key, and schedules the rotated key to expire after a grace period so + * in-flight callers can swap over. The new plaintext key is returned once. + * + * @example + * ```ts + * const createdAPIKey = await client.apiKeys.rotate('id'); + * ``` + */ + rotate( + id: string, + body: APIKeyRotateParams | null | undefined = {}, + options?: RequestOptions, + ): APIPromise { + return this._client.post(path`/org/api_keys/${id}/rotate`, { body, ...options }); + } } export type APIKeysOffsetPagination = OffsetPagination; @@ -230,6 +248,20 @@ export interface APIKeyListParams extends OffsetPaginationParams { sort_direction?: 'asc' | 'desc'; } +export interface APIKeyRotateParams { + /** + * Lifetime in days for the new key, up to 3650. Omit to reuse the rotated key's + * original lifetime, or never-expires if it had none. + */ + days_to_expire?: number | null; + + /** + * Grace period in days before the rotated key expires. Use 0 to expire it + * immediately. Omit for the default grace period of 7 days. + */ + expire_in_days?: number | null; +} + export declare namespace APIKeys { export { type APIKey as APIKey, @@ -239,5 +271,6 @@ export declare namespace APIKeys { type APIKeyRetrieveParams as APIKeyRetrieveParams, type APIKeyUpdateParams as APIKeyUpdateParams, type APIKeyListParams as APIKeyListParams, + type APIKeyRotateParams as APIKeyRotateParams, }; } diff --git a/src/resources/index.ts b/src/resources/index.ts index b73f26f3..bc3f9ffa 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -9,6 +9,7 @@ export { type APIKeyRetrieveParams, type APIKeyUpdateParams, type APIKeyListParams, + type APIKeyRotateParams, type APIKeysOffsetPagination, } from './api-keys'; export { diff --git a/tests/api-resources/api-keys.test.ts b/tests/api-resources/api-keys.test.ts index 1dbeb3e7..3c1497bb 100644 --- a/tests/api-resources/api-keys.test.ts +++ b/tests/api-resources/api-keys.test.ts @@ -107,4 +107,28 @@ describe('resource apiKeys', () => { expect(dataAndResponse.data).toBe(response); expect(dataAndResponse.response).toBe(rawResponse); }); + + // Mock server tests are disabled + test.skip('rotate', async () => { + const responsePromise = client.apiKeys.rotate('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); + }); + + // Mock server tests are disabled + test.skip('rotate: 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.apiKeys.rotate( + 'id', + { days_to_expire: 30, expire_in_days: 7 }, + { path: '/_stainless_unknown_path' }, + ), + ).rejects.toThrow(Kernel.NotFoundError); + }); }); From b81d9d8ef719ff9cbced865d0a6dc760db3a0ffa Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sun, 14 Jun 2026 20:21:25 +0000 Subject: [PATCH 447/551] refactor(api): align API key audit surface with browser sibling (KERNEL-1350) --- .stats.yml | 4 ++-- src/resources/api-keys.ts | 18 +++++++++--------- tests/api-resources/api-keys.test.ts | 1 + 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/.stats.yml b/.stats.yml index 8d8fe88a..4127b5f2 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 120 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-1f10598afa01d76d22b0ed63685248f482f74c9353cffe1d3e4a3d38da7716cf.yml -openapi_spec_hash: 8936f458bfa681b709e459ca1cc76fb5 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-e8afdbeac9332cf79200c2eb873e532104fd0a7472b08e63cde6c857a87cf0c3.yml +openapi_spec_hash: 2525caf30dffbdd83c83948201f11a52 config_hash: 03c7e57f268c750e2415831662e95969 diff --git a/src/resources/api-keys.ts b/src/resources/api-keys.ts index 7dc62e6d..60b41f54 100644 --- a/src/resources/api-keys.ts +++ b/src/resources/api-keys.ts @@ -154,13 +154,6 @@ export interface APIKey { * project name is unavailable. */ project_name: string | null; - - /** - * Derived lifecycle status of the API key. `active` means usable. `expired` means - * past its expires_at. `deleted` means it was deleted (soft-deleted) and can no - * longer authenticate. Deleted takes precedence over expired. - */ - status: 'active' | 'expired' | 'deleted'; } export namespace APIKey { @@ -226,8 +219,8 @@ export interface APIKeyUpdateParams { export interface APIKeyListParams extends OffsetPaginationParams { /** - * When true, include deleted (soft-deleted) API keys in the results for audit - * purposes. Defaults to false, which returns only live keys. + * Deprecated: use status=all instead. When true, include deleted (soft-deleted) + * API keys in the results for audit purposes. */ include_deleted?: boolean; @@ -246,6 +239,13 @@ export interface APIKeyListParams extends OffsetPaginationParams { * Sort direction for API keys. */ sort_direction?: 'asc' | 'desc'; + + /** + * Filter API keys by status. "active" returns keys that are not deleted (default; + * expired-but-not-deleted keys are still included), "deleted" returns only + * soft-deleted keys, "all" returns both. + */ + status?: 'active' | 'deleted' | 'all'; } export interface APIKeyRotateParams { diff --git a/tests/api-resources/api-keys.test.ts b/tests/api-resources/api-keys.test.ts index 3c1497bb..b179ccfb 100644 --- a/tests/api-resources/api-keys.test.ts +++ b/tests/api-resources/api-keys.test.ts @@ -90,6 +90,7 @@ describe('resource apiKeys', () => { query: 'query', sort_by: 'created_at', sort_direction: 'asc', + status: 'active', }, { path: '/_stainless_unknown_path' }, ), From 55e6d92c6d1a0b2e02a86ce339a3f1587594ee8e Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 15 Jun 2026 18:41:40 +0000 Subject: [PATCH 448/551] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 4127b5f2..29192087 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 120 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-e8afdbeac9332cf79200c2eb873e532104fd0a7472b08e63cde6c857a87cf0c3.yml -openapi_spec_hash: 2525caf30dffbdd83c83948201f11a52 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-d26459bd3514237e8d757be3cbdc76ca62f6083504b85601e57db830888964f7.yml +openapi_spec_hash: 5dd151a8099398819a97692c1c60c3c6 config_hash: 03c7e57f268c750e2415831662e95969 From 66090dcd4316765acca00d6fcd7fb754cab5d2d9 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 15 Jun 2026 18:58:26 +0000 Subject: [PATCH 449/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 94994d4f..e5a17c22 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.67.0" + ".": "0.68.0" } diff --git a/package.json b/package.json index 459f9eb3..afc80acb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.67.0", + "version": "0.68.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index ed32717a..71e73403 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.67.0'; // x-release-please-version +export const VERSION = '0.68.0'; // x-release-please-version From a7b43e49c7acc860f246d7f3364469931e8aa0fd Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 17 Jun 2026 02:09:37 +0000 Subject: [PATCH 450/551] fix(client): send content-type header for requests with an omitted optional body --- src/client.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/client.ts b/src/client.ts index 50d419a5..9b834ce7 100644 --- a/src/client.ts +++ b/src/client.ts @@ -848,11 +848,19 @@ export class Kernel { return () => controller.abort(); } - private buildBody({ options: { body, headers: rawHeaders } }: { options: FinalRequestOptions }): { + private buildBody({ options }: { options: FinalRequestOptions }): { bodyHeaders: HeadersLike; body: BodyInit | undefined; } { + const { body, headers: rawHeaders } = options; if (!body) { + // A resource method always passes a `body` key when its operation defines a + // request body, even if the caller omitted an optional body param. Keep the + // content-type for those, and only elide it for operations with no body at + // all (e.g. GET/DELETE). + if (body == null && 'body' in options) { + return this.#encoder({ body, headers: buildHeaders([rawHeaders]) }); + } return { bodyHeaders: undefined, body: undefined }; } const headers = buildHeaders([rawHeaders]); From 738fc025d9462b0e11cb0cc6fcc193b598941818 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 18 Jun 2026 18:55:39 +0000 Subject: [PATCH 451/551] feat: Add free-text search to remaining paginated list endpoints --- .stats.yml | 4 ++-- src/resources/auth/connections.ts | 5 +++++ src/resources/browser-pools.ts | 7 ++++++- src/resources/credential-providers.ts | 7 ++++++- src/resources/credentials.ts | 5 +++++ src/resources/deployments.ts | 5 +++++ src/resources/extensions.ts | 7 ++++++- src/resources/invocations.ts | 5 +++++ src/resources/proxies.ts | 7 ++++++- tests/api-resources/auth/connections.test.ts | 1 + tests/api-resources/browser-pools.test.ts | 9 ++++++++- tests/api-resources/credential-providers.test.ts | 9 ++++++++- tests/api-resources/credentials.test.ts | 1 + tests/api-resources/deployments.test.ts | 1 + tests/api-resources/extensions.test.ts | 9 ++++++++- tests/api-resources/invocations.test.ts | 1 + tests/api-resources/proxies.test.ts | 9 ++++++++- 17 files changed, 82 insertions(+), 10 deletions(-) diff --git a/.stats.yml b/.stats.yml index 29192087..4424fe73 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 120 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-d26459bd3514237e8d757be3cbdc76ca62f6083504b85601e57db830888964f7.yml -openapi_spec_hash: 5dd151a8099398819a97692c1c60c3c6 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-cde481b2f320ce48f83db84ae96226b0e7568146c9387c4fefebf286ecb0dd0a.yml +openapi_spec_hash: 6bd86d767290fcd7e2a6aae26dff5417 config_hash: 03c7e57f268c750e2415831662e95969 diff --git a/src/resources/auth/connections.ts b/src/resources/auth/connections.ts index 3ddd5080..1fd1422f 100644 --- a/src/resources/auth/connections.ts +++ b/src/resources/auth/connections.ts @@ -1398,6 +1398,11 @@ export interface ConnectionListParams extends OffsetPaginationParams { * Filter by profile name */ profile_name?: string; + + /** + * Search auth connections by ID, domain, or profile name. + */ + query?: string; } export interface ConnectionLoginParams { diff --git a/src/resources/browser-pools.ts b/src/resources/browser-pools.ts index a22174da..d4035643 100644 --- a/src/resources/browser-pools.ts +++ b/src/resources/browser-pools.ts @@ -609,7 +609,12 @@ export interface BrowserPoolUpdateParams { viewport?: Shared.BrowserViewport; } -export interface BrowserPoolListParams extends OffsetPaginationParams {} +export interface BrowserPoolListParams extends OffsetPaginationParams { + /** + * Search browser pools by name or ID. + */ + query?: string; +} export interface BrowserPoolDeleteParams { /** diff --git a/src/resources/credential-providers.ts b/src/resources/credential-providers.ts index 5386ac06..601cf269 100644 --- a/src/resources/credential-providers.ts +++ b/src/resources/credential-providers.ts @@ -344,7 +344,12 @@ export interface CredentialProviderUpdateParams { priority?: number; } -export interface CredentialProviderListParams extends OffsetPaginationParams {} +export interface CredentialProviderListParams extends OffsetPaginationParams { + /** + * Search credential providers by name or ID. + */ + query?: string; +} export declare namespace CredentialProviders { export { diff --git a/src/resources/credentials.ts b/src/resources/credentials.ts index cd64d5e6..19842027 100644 --- a/src/resources/credentials.ts +++ b/src/resources/credentials.ts @@ -305,6 +305,11 @@ export interface CredentialListParams extends OffsetPaginationParams { * Filter by domain */ domain?: string; + + /** + * Search credentials by name, domain, or ID. + */ + query?: string; } export declare namespace Credentials { diff --git a/src/resources/deployments.ts b/src/resources/deployments.ts index 8ea9843e..a389f8bd 100644 --- a/src/resources/deployments.ts +++ b/src/resources/deployments.ts @@ -469,6 +469,11 @@ export interface DeploymentListParams extends OffsetPaginationParams { * Filter results by application version. Requires app_name to be set. */ app_version?: string; + + /** + * Search deployments by ID or app name. + */ + query?: string; } export interface DeploymentFollowParams { diff --git a/src/resources/extensions.ts b/src/resources/extensions.ts index 0afbdd59..c1fff540 100644 --- a/src/resources/extensions.ts +++ b/src/resources/extensions.ts @@ -177,7 +177,12 @@ export interface ExtensionUploadResponse { name?: string | null; } -export interface ExtensionListParams extends OffsetPaginationParams {} +export interface ExtensionListParams extends OffsetPaginationParams { + /** + * Search extensions by name or ID. + */ + query?: string; +} export interface ExtensionDownloadFromChromeStoreParams { /** diff --git a/src/resources/invocations.ts b/src/resources/invocations.ts index ce731966..381ff1bc 100644 --- a/src/resources/invocations.ts +++ b/src/resources/invocations.ts @@ -613,6 +613,11 @@ export interface InvocationListParams extends OffsetPaginationParams { */ deployment_id?: string; + /** + * Search invocations by ID, app name, or action name. + */ + query?: string; + /** * Show invocations that have started since the given time (RFC timestamps or * durations like 5m). diff --git a/src/resources/proxies.ts b/src/resources/proxies.ts index 274a0501..3dda98f5 100644 --- a/src/resources/proxies.ts +++ b/src/resources/proxies.ts @@ -824,7 +824,12 @@ export namespace ProxyCreateParams { } } -export interface ProxyListParams extends OffsetPaginationParams {} +export interface ProxyListParams extends OffsetPaginationParams { + /** + * Search proxies by name, host, IP address, or ID. + */ + query?: string; +} export interface ProxyCheckParams { /** diff --git a/tests/api-resources/auth/connections.test.ts b/tests/api-resources/auth/connections.test.ts index c03afb3a..ff94370a 100644 --- a/tests/api-resources/auth/connections.test.ts +++ b/tests/api-resources/auth/connections.test.ts @@ -91,6 +91,7 @@ describe('resource connections', () => { limit: 100, offset: 0, profile_name: 'profile_name', + query: 'query', }, { path: '/_stainless_unknown_path' }, ), diff --git a/tests/api-resources/browser-pools.test.ts b/tests/api-resources/browser-pools.test.ts index a7c39c3e..3d8e3ebd 100644 --- a/tests/api-resources/browser-pools.test.ts +++ b/tests/api-resources/browser-pools.test.ts @@ -87,7 +87,14 @@ describe('resource browserPools', () => { test.skip('list: 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.browserPools.list({ limit: 1, offset: 0 }, { path: '/_stainless_unknown_path' }), + client.browserPools.list( + { + limit: 1, + offset: 0, + query: 'query', + }, + { path: '/_stainless_unknown_path' }, + ), ).rejects.toThrow(Kernel.NotFoundError); }); diff --git a/tests/api-resources/credential-providers.test.ts b/tests/api-resources/credential-providers.test.ts index ae64be3e..d5356327 100644 --- a/tests/api-resources/credential-providers.test.ts +++ b/tests/api-resources/credential-providers.test.ts @@ -74,7 +74,14 @@ describe('resource credentialProviders', () => { test.skip('list: 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.credentialProviders.list({ limit: 1, offset: 0 }, { path: '/_stainless_unknown_path' }), + client.credentialProviders.list( + { + limit: 1, + offset: 0, + query: 'query', + }, + { path: '/_stainless_unknown_path' }, + ), ).rejects.toThrow(Kernel.NotFoundError); }); diff --git a/tests/api-resources/credentials.test.ts b/tests/api-resources/credentials.test.ts index 11ab0da6..5bd00bbc 100644 --- a/tests/api-resources/credentials.test.ts +++ b/tests/api-resources/credentials.test.ts @@ -80,6 +80,7 @@ describe('resource credentials', () => { domain: 'domain', limit: 100, offset: 0, + query: 'query', }, { path: '/_stainless_unknown_path' }, ), diff --git a/tests/api-resources/deployments.test.ts b/tests/api-resources/deployments.test.ts index 3405cc89..8d7901e1 100644 --- a/tests/api-resources/deployments.test.ts +++ b/tests/api-resources/deployments.test.ts @@ -54,6 +54,7 @@ describe('resource deployments', () => { app_version: 'app_version', limit: 1, offset: 0, + query: 'query', }, { path: '/_stainless_unknown_path' }, ), diff --git a/tests/api-resources/extensions.test.ts b/tests/api-resources/extensions.test.ts index 8f03039f..431d43d3 100644 --- a/tests/api-resources/extensions.test.ts +++ b/tests/api-resources/extensions.test.ts @@ -24,7 +24,14 @@ describe('resource extensions', () => { test.skip('list: 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.extensions.list({ limit: 1, offset: 0 }, { path: '/_stainless_unknown_path' }), + client.extensions.list( + { + limit: 1, + offset: 0, + query: 'query', + }, + { path: '/_stainless_unknown_path' }, + ), ).rejects.toThrow(Kernel.NotFoundError); }); diff --git a/tests/api-resources/invocations.test.ts b/tests/api-resources/invocations.test.ts index d1915b2e..5feab271 100644 --- a/tests/api-resources/invocations.test.ts +++ b/tests/api-resources/invocations.test.ts @@ -88,6 +88,7 @@ describe('resource invocations', () => { deployment_id: 'deployment_id', limit: 1, offset: 0, + query: 'query', since: '2025-06-20T12:00:00Z', status: 'queued', version: 'version', diff --git a/tests/api-resources/proxies.test.ts b/tests/api-resources/proxies.test.ts index f4e09d94..e64b2747 100644 --- a/tests/api-resources/proxies.test.ts +++ b/tests/api-resources/proxies.test.ts @@ -59,7 +59,14 @@ describe('resource proxies', () => { test.skip('list: 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.proxies.list({ limit: 1, offset: 0 }, { path: '/_stainless_unknown_path' }), + client.proxies.list( + { + limit: 1, + offset: 0, + query: 'query', + }, + { path: '/_stainless_unknown_path' }, + ), ).rejects.toThrow(Kernel.NotFoundError); }); From 1c6cf3cc99c18a15f2fe1412e46b7f79bd8e68d3 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 18 Jun 2026 19:04:14 +0000 Subject: [PATCH 452/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index e5a17c22..93e2be7f 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.68.0" + ".": "0.69.0" } diff --git a/package.json b/package.json index afc80acb..40249fbc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.68.0", + "version": "0.69.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 71e73403..f88b6d2e 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.68.0'; // x-release-please-version +export const VERSION = '0.69.0'; // x-release-please-version From 8c532b540b05b9bae55a82463b8d99ad4e5307e4 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 20 Jun 2026 20:02:38 +0000 Subject: [PATCH 453/551] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 4424fe73..ed276ab4 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 120 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-cde481b2f320ce48f83db84ae96226b0e7568146c9387c4fefebf286ecb0dd0a.yml -openapi_spec_hash: 6bd86d767290fcd7e2a6aae26dff5417 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-d70be5e703da22000f3f7e76b19d5fa3e3bf8c33be2e9570bfafb5cf9d956a17.yml +openapi_spec_hash: deaa8926543116d1f81d34d1e01e0c0a config_hash: 03c7e57f268c750e2415831662e95969 From e64790b0f1166bfb1c5211d399784bb9d96d5c91 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 22 Jun 2026 17:41:40 +0000 Subject: [PATCH 454/551] feat: Align browser-pool timeout/viewport/fill-rate contract with implementation; reject save_changes on update --- .stats.yml | 4 ++-- src/resources/browser-pools.ts | 18 ++++++++++++------ src/resources/shared.ts | 8 ++++---- tests/api-resources/browser-pools.test.ts | 2 +- 4 files changed, 19 insertions(+), 13 deletions(-) diff --git a/.stats.yml b/.stats.yml index ed276ab4..316f1e84 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 120 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-d70be5e703da22000f3f7e76b19d5fa3e3bf8c33be2e9570bfafb5cf9d956a17.yml -openapi_spec_hash: deaa8926543116d1f81d34d1e01e0c0a +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-ab4e7c50c41fefd891648fa84ba0258986f192ba1bde9f42cbdf487f64c4cc27.yml +openapi_spec_hash: b4bcd6557f7045ecff30b01e02d28ac5 config_hash: 03c7e57f268c750e2415831662e95969 diff --git a/src/resources/browser-pools.ts b/src/resources/browser-pools.ts index d4035643..e4c06190 100644 --- a/src/resources/browser-pools.ts +++ b/src/resources/browser-pools.ts @@ -213,7 +213,9 @@ export namespace BrowserPool { extensions?: Array; /** - * Percentage of the pool to fill per minute. Defaults to 10%. + * Percentage of the pool to fill per minute. Defaults to 10. The cap is 25 for + * most organizations but can be raised per-organization, so only the lower bound + * is enforced here. */ fill_rate_per_minute?: number; @@ -263,7 +265,7 @@ export namespace BrowserPool { /** * Default idle timeout in seconds for browsers acquired from this pool before they - * are destroyed. Defaults to 600 seconds if not specified + * are destroyed. Defaults to 600 seconds. Minimum 10, maximum 259200 (72 hours). */ timeout_seconds?: number; @@ -439,7 +441,9 @@ export interface BrowserPoolCreateParams { extensions?: Array; /** - * Percentage of the pool to fill per minute. Defaults to 10%. + * Percentage of the pool to fill per minute. Defaults to 10. The cap is 25 for + * most organizations but can be raised per-organization, so only the lower bound + * is enforced here. */ fill_rate_per_minute?: number; @@ -489,7 +493,7 @@ export interface BrowserPoolCreateParams { /** * Default idle timeout in seconds for browsers acquired from this pool before they - * are destroyed. Defaults to 600 seconds if not specified + * are destroyed. Defaults to 600 seconds. Minimum 10, maximum 259200 (72 hours). */ timeout_seconds?: number; @@ -531,7 +535,9 @@ export interface BrowserPoolUpdateParams { extensions?: Array; /** - * Percentage of the pool to fill per minute. Defaults to 10%. + * Percentage of the pool to fill per minute. Defaults to 10. The cap is 25 for + * most organizations but can be raised per-organization, so only the lower bound + * is enforced here. */ fill_rate_per_minute?: number; @@ -588,7 +594,7 @@ export interface BrowserPoolUpdateParams { /** * Default idle timeout in seconds for browsers acquired from this pool before they - * are destroyed. Defaults to 600 seconds if not specified + * are destroyed. Defaults to 600 seconds. Minimum 10, maximum 259200 (72 hours). */ timeout_seconds?: number; diff --git a/src/resources/shared.ts b/src/resources/shared.ts index 8666f8a7..e18de324 100644 --- a/src/resources/shared.ts +++ b/src/resources/shared.ts @@ -79,18 +79,18 @@ export interface BrowserProfile { */ export interface BrowserViewport { /** - * Browser window height in pixels. + * Browser window height in pixels. Any positive integer is accepted. */ height: number; /** - * Browser window width in pixels. + * Browser window width in pixels. Any positive integer is accepted. */ width: number; /** - * Display refresh rate in Hz. If omitted, automatically determined from width and - * height. + * Display refresh rate in Hz. Any positive integer is accepted; if omitted, + * automatically determined from width and height. */ refresh_rate?: number; } diff --git a/tests/api-resources/browser-pools.test.ts b/tests/api-resources/browser-pools.test.ts index 3d8e3ebd..ff870709 100644 --- a/tests/api-resources/browser-pools.test.ts +++ b/tests/api-resources/browser-pools.test.ts @@ -38,7 +38,7 @@ describe('resource browserPools', () => { proxy_id: 'proxy_id', start_url: 'https://example.com', stealth: true, - timeout_seconds: 60, + timeout_seconds: 10, viewport: { height: 800, width: 1280, From 69f2ff867d318a335017c03048b9f1dfe136d6eb Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 23 Jun 2026 14:13:58 +0000 Subject: [PATCH 455/551] feat(api): add GET /extensions/{id_or_name}/metadata --- .stats.yml | 8 ++--- api.md | 2 ++ src/client.ts | 2 ++ src/resources/extensions.ts | 45 ++++++++++++++++++++++++++ src/resources/index.ts | 1 + tests/api-resources/extensions.test.ts | 12 +++++++ 6 files changed, 66 insertions(+), 4 deletions(-) diff --git a/.stats.yml b/.stats.yml index 316f1e84..db9991cb 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 120 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-ab4e7c50c41fefd891648fa84ba0258986f192ba1bde9f42cbdf487f64c4cc27.yml -openapi_spec_hash: b4bcd6557f7045ecff30b01e02d28ac5 -config_hash: 03c7e57f268c750e2415831662e95969 +configured_endpoints: 121 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-bccc42bb10d1afe703f0374d11f33e775522069d69a13bb2345cc566a49ba4f3.yml +openapi_spec_hash: 9f00975c0e741ed84011413674313be0 +config_hash: 3a50aee540dce69a53bb8942f5086f5e diff --git a/api.md b/api.md index 7a48707d..8658b7ec 100644 --- a/api.md +++ b/api.md @@ -301,6 +301,7 @@ Methods: Types: - ExtensionListResponse +- ExtensionGetResponse - ExtensionUploadResponse Methods: @@ -309,6 +310,7 @@ Methods: - client.extensions.delete(idOrName) -> void - client.extensions.download(idOrName) -> Response - client.extensions.downloadFromChromeStore({ ...params }) -> Response +- client.extensions.get(idOrName) -> ExtensionGetResponse - client.extensions.upload({ ...params }) -> ExtensionUploadResponse # BrowserPools diff --git a/src/client.ts b/src/client.ts index 9b834ce7..b0557644 100644 --- a/src/client.ts +++ b/src/client.ts @@ -81,6 +81,7 @@ import { } from './resources/deployments'; import { ExtensionDownloadFromChromeStoreParams, + ExtensionGetResponse, ExtensionListParams, ExtensionListResponse, ExtensionListResponsesOffsetPagination, @@ -1075,6 +1076,7 @@ export declare namespace Kernel { export { Extensions as Extensions, type ExtensionListResponse as ExtensionListResponse, + type ExtensionGetResponse as ExtensionGetResponse, type ExtensionUploadResponse as ExtensionUploadResponse, type ExtensionListResponsesOffsetPagination as ExtensionListResponsesOffsetPagination, type ExtensionListParams as ExtensionListParams, diff --git a/src/resources/extensions.ts b/src/resources/extensions.ts index c1fff540..79e98e12 100644 --- a/src/resources/extensions.ts +++ b/src/resources/extensions.ts @@ -97,6 +97,19 @@ export class Extensions extends APIResource { }); } + /** + * Get an extension's metadata (name, size, timestamps) by ID or name, without + * downloading the archive. + * + * @example + * ```ts + * const extension = await client.extensions.get('id_or_name'); + * ``` + */ + get(idOrName: string, options?: RequestOptions): APIPromise { + return this._client.get(path`/extensions/${idOrName}/metadata`, options); + } + /** * Upload a zip file containing an unpacked browser extension. Optionally provide a * unique name for later reference. @@ -146,6 +159,37 @@ export interface ExtensionListResponse { name?: string | null; } +/** + * A browser extension uploaded to Kernel. + */ +export interface ExtensionGetResponse { + /** + * Unique identifier for the extension + */ + id: string; + + /** + * Timestamp when the extension was created + */ + created_at: string; + + /** + * Size of the extension archive in bytes + */ + size_bytes: number; + + /** + * Timestamp when the extension was last used + */ + last_used_at?: string | null; + + /** + * Optional, easier-to-reference name for the extension. Must be unique within the + * project. + */ + name?: string | null; +} + /** * A browser extension uploaded to Kernel. */ @@ -211,6 +255,7 @@ export interface ExtensionUploadParams { export declare namespace Extensions { export { type ExtensionListResponse as ExtensionListResponse, + type ExtensionGetResponse as ExtensionGetResponse, type ExtensionUploadResponse as ExtensionUploadResponse, type ExtensionListResponsesOffsetPagination as ExtensionListResponsesOffsetPagination, type ExtensionListParams as ExtensionListParams, diff --git a/src/resources/index.ts b/src/resources/index.ts index bc3f9ffa..edbee058 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -90,6 +90,7 @@ export { export { Extensions, type ExtensionListResponse, + type ExtensionGetResponse, type ExtensionUploadResponse, type ExtensionListParams, type ExtensionDownloadFromChromeStoreParams, diff --git a/tests/api-resources/extensions.test.ts b/tests/api-resources/extensions.test.ts index 431d43d3..8d196d93 100644 --- a/tests/api-resources/extensions.test.ts +++ b/tests/api-resources/extensions.test.ts @@ -52,6 +52,18 @@ describe('resource extensions', () => { const response = await client.extensions.downloadFromChromeStore({ url: 'url', os: 'win' }); }); + // Mock server tests are disabled + test.skip('get', async () => { + const responsePromise = client.extensions.get('id_or_name'); + 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); + }); + // Mock server tests are disabled test.skip('upload: only required params', async () => { const responsePromise = client.extensions.upload({ From 00cdc05d3e1340f68c78e5a9b88ffa84c4a47550 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 23 Jun 2026 14:43:52 +0000 Subject: [PATCH 456/551] feat(api): resolve GET /org/projects/{id} by ID or name --- .stats.yml | 4 ++-- src/resources/projects/projects.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.stats.yml b/.stats.yml index db9991cb..734935c5 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 121 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-bccc42bb10d1afe703f0374d11f33e775522069d69a13bb2345cc566a49ba4f3.yml -openapi_spec_hash: 9f00975c0e741ed84011413674313be0 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-7d6d64b3998b55057f21aa5e33096cd5468f2bb2c4fda65190e9f299b50e5908.yml +openapi_spec_hash: aa7d3971d38b16eff41b08cc3cbb549d config_hash: 3a50aee540dce69a53bb8942f5086f5e diff --git a/src/resources/projects/projects.ts b/src/resources/projects/projects.ts index 520b1afb..e20a1c2e 100644 --- a/src/resources/projects/projects.ts +++ b/src/resources/projects/projects.ts @@ -30,7 +30,7 @@ export class Projects extends APIResource { } /** - * Get a project by ID. + * Get a project by its ID or by its name. Names are unique within an organization. * * @example * ```ts From 5763a449806f4c9db5e05693e5caaa3dd34bb0de Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 23 Jun 2026 16:18:01 +0000 Subject: [PATCH 457/551] feat: Forward replay param through telemetry stream passthrough --- .stats.yml | 4 ++-- src/resources/browsers/telemetry.ts | 18 ++++++++++++++---- tests/api-resources/browsers/telemetry.test.ts | 2 +- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/.stats.yml b/.stats.yml index 734935c5..c487e555 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 121 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-7d6d64b3998b55057f21aa5e33096cd5468f2bb2c4fda65190e9f299b50e5908.yml -openapi_spec_hash: aa7d3971d38b16eff41b08cc3cbb549d +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-01f7f21a2fc892da284edf6b7cfd340d2ce5d0a9eb7ad2b39a8daec27b093134.yml +openapi_spec_hash: 21972930082b23d985faf285fd656c31 config_hash: 3a50aee540dce69a53bb8942f5086f5e diff --git a/src/resources/browsers/telemetry.ts b/src/resources/browsers/telemetry.ts index 50909b02..91295f42 100644 --- a/src/resources/browsers/telemetry.ts +++ b/src/resources/browsers/telemetry.ts @@ -20,7 +20,8 @@ export class Telemetry extends APIResource { * set; all frames carry JSON in the data: field. A keepalive comment frame is sent * every 15 seconds when no events arrive. Returns 404 if the browser session does * not exist. If telemetry was not enabled on the session, the stream opens but no - * events are delivered. + * events are delivered. Fresh connections only see new events; pass replay=all to + * start from the oldest retained event instead. * * @example * ```ts @@ -34,8 +35,9 @@ export class Telemetry extends APIResource { params: TelemetryStreamParams | undefined = {}, options?: RequestOptions, ): APIPromise> { - const { 'Last-Event-ID': lastEventID } = params ?? {}; + const { 'Last-Event-ID': lastEventID, ...query } = params ?? {}; return this._client.get(path`/browsers/${id}/telemetry/stream`, { + query, ...options, headers: buildHeaders([ { @@ -2001,8 +2003,16 @@ export interface TelemetryStreamResponse { export interface TelemetryStreamParams { /** - * Last event sequence number for SSE reconnection (sent by SSE clients on - * reconnect) + * Query param: Pass `all` to start from the oldest retained event instead of only + * new events; any other value is treated as from-now. The buffer is bounded, so + * the first event id may be greater than 1 if older events were evicted. + */ + replay?: string; + + /** + * Header param: Last event sequence number for SSE reconnection (sent by SSE + * clients on reconnect). Takes precedence over replay when both are present, so + * reconnect resumes instead of re-replaying. */ 'Last-Event-ID'?: string; } diff --git a/tests/api-resources/browsers/telemetry.test.ts b/tests/api-resources/browsers/telemetry.test.ts index e1986560..b0e52695 100644 --- a/tests/api-resources/browsers/telemetry.test.ts +++ b/tests/api-resources/browsers/telemetry.test.ts @@ -26,7 +26,7 @@ describe('resource telemetry', () => { await expect( client.browsers.telemetry.stream( 'id', - { 'Last-Event-ID': 'Last-Event-ID' }, + { replay: 'replay', 'Last-Event-ID': 'Last-Event-ID' }, { path: '/_stainless_unknown_path' }, ), ).rejects.toThrow(Kernel.NotFoundError); From 4b587c216339824da733c39e4713759beb833c9c Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 23 Jun 2026 16:36:09 +0000 Subject: [PATCH 458/551] feat: Add GET /browsers/{id}/telemetry/events (read from S2) --- .stats.yml | 8 +- api.md | 2 + src/resources/browsers/browsers.ts | 6 ++ src/resources/browsers/index.ts | 3 + src/resources/browsers/telemetry.ts | 91 +++++++++++++++++++ .../api-resources/browsers/telemetry.test.ts | 30 ++++++ 6 files changed, 136 insertions(+), 4 deletions(-) diff --git a/.stats.yml b/.stats.yml index c487e555..310bb248 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 121 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-01f7f21a2fc892da284edf6b7cfd340d2ce5d0a9eb7ad2b39a8daec27b093134.yml -openapi_spec_hash: 21972930082b23d985faf285fd656c31 -config_hash: 3a50aee540dce69a53bb8942f5086f5e +configured_endpoints: 122 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-7cde13c82c71b7a5fd64b592f853a7c999c0e0c02dce161e6126d0e99df3412b.yml +openapi_spec_hash: 52cda226c70a248cbea3af6c52822b44 +config_hash: 99b2b2a25e8067ad9c9214e38e01d64c diff --git a/api.md b/api.md index 8658b7ec..45d69699 100644 --- a/api.md +++ b/api.md @@ -128,10 +128,12 @@ Types: - BrowserTelemetryCategoryConfig - BrowserTelemetryConfig - BrowserTelemetryEvent +- TelemetryEventsResponse - TelemetryStreamResponse Methods: +- client.browsers.telemetry.events(id, { ...params }) -> TelemetryEventsResponsesOffsetPagination - client.browsers.telemetry.stream(id, { ...params }) -> TelemetryStreamResponse ## Replays diff --git a/src/resources/browsers/browsers.ts b/src/resources/browsers/browsers.ts index 3a395dea..a14e05a8 100644 --- a/src/resources/browsers/browsers.ts +++ b/src/resources/browsers/browsers.ts @@ -91,6 +91,9 @@ import { BrowserTelemetryConfig, BrowserTelemetryEvent, Telemetry as TelemetryAPITelemetry, + TelemetryEventsParams, + TelemetryEventsResponse, + TelemetryEventsResponsesOffsetPagination, TelemetryStreamParams, TelemetryStreamResponse, } from './telemetry'; @@ -1261,7 +1264,10 @@ export declare namespace Browsers { type BrowserTelemetryCategoryConfig as BrowserTelemetryCategoryConfig, type BrowserTelemetryConfig as BrowserTelemetryConfig, type BrowserTelemetryEvent as BrowserTelemetryEvent, + type TelemetryEventsResponse as TelemetryEventsResponse, type TelemetryStreamResponse as TelemetryStreamResponse, + type TelemetryEventsResponsesOffsetPagination as TelemetryEventsResponsesOffsetPagination, + type TelemetryEventsParams as TelemetryEventsParams, type TelemetryStreamParams as TelemetryStreamParams, }; diff --git a/src/resources/browsers/index.ts b/src/resources/browsers/index.ts index a95c02b6..dc9aed87 100644 --- a/src/resources/browsers/index.ts +++ b/src/resources/browsers/index.ts @@ -120,6 +120,9 @@ export { type BrowserTelemetryCategoryConfig, type BrowserTelemetryConfig, type BrowserTelemetryEvent, + type TelemetryEventsResponse, type TelemetryStreamResponse, + type TelemetryEventsParams, type TelemetryStreamParams, + type TelemetryEventsResponsesOffsetPagination, } from './telemetry'; diff --git a/src/resources/browsers/telemetry.ts b/src/resources/browsers/telemetry.ts index 91295f42..59bed198 100644 --- a/src/resources/browsers/telemetry.ts +++ b/src/resources/browsers/telemetry.ts @@ -3,6 +3,7 @@ import { APIResource } from '../../core/resource'; import * as TelemetryAPI from './telemetry'; import { APIPromise } from '../../core/api-promise'; +import { OffsetPagination, type OffsetPaginationParams, PagePromise } from '../../core/pagination'; import { Stream } from '../../core/streaming'; import { buildHeaders } from '../../internal/headers'; import { RequestOptions } from '../../internal/request-options'; @@ -12,6 +13,34 @@ import { path } from '../../internal/utils/path'; * Stream live telemetry events from a browser session. */ export class Telemetry extends APIResource { + /** + * Reads a page of telemetry events for the browser session in ascending sequence + * order. To page through results, pass the X-Next-Offset value from the previous + * response as offset and repeat while X-Has-More is true. Returns an empty list + * when telemetry data is unavailable. + * + * @example + * ```ts + * // Automatically fetches more pages as needed. + * for await (const telemetryEventsResponse of client.browsers.telemetry.events( + * 'id', + * )) { + * // ... + * } + * ``` + */ + events( + id: string, + query: TelemetryEventsParams | null | undefined = {}, + options?: RequestOptions, + ): PagePromise { + return this._client.getAPIList( + path`/browsers/${id}/telemetry/events`, + OffsetPagination, + { query, ...options }, + ); + } + /** * Streams browser telemetry events as a server-sent events (SSE) stream. The * stream closes when the browser session terminates. Each event frame includes an @@ -51,6 +80,8 @@ export class Telemetry extends APIResource { } } +export type TelemetryEventsResponsesOffsetPagination = OffsetPagination; + /** * An agent-driven HTTP call handled by the in-VM API server. */ @@ -1975,6 +2006,32 @@ export type BrowserTelemetryEvent = | BrowserSystemOomKillEvent | BrowserServiceCrashedEvent; +/** + * Envelope wrapping a browser telemetry event with its monotonic sequence number. + * Each SSE data: frame carries one envelope as JSON. The seq value is also emitted + * as the SSE id: field so clients can pass it as Last-Event-ID on reconnect. + */ +export interface TelemetryEventsResponse { + /** + * Union type representing any browser telemetry event. Discriminated on `type`. + * Each event's `category` determines when it is captured. The CDP collector-health + * events (monitor_disconnected, monitor_reconnected, monitor_reconnect_failed, + * monitor_init_failed) use the `monitor` category, which is not user-configurable: + * it flows automatically whenever any CDP category (console, network, page, + * interaction) is captured, and is silent otherwise. monitor_screenshot uses the + * opt-in `screenshot` category. All other event types are controlled by their + * per-category enable/disable flags. + */ + event: BrowserTelemetryEvent; + + /** + * Process-monotonic sequence number assigned by the browser VM. Pass as + * Last-Event-ID on reconnect to resume without gaps. Gaps in received seq values + * indicate dropped events. + */ + seq: number; +} + /** * Envelope wrapping a browser telemetry event with its monotonic sequence number. * Each SSE data: frame carries one envelope as JSON. The seq value is also emitted @@ -2001,6 +2058,37 @@ export interface TelemetryStreamResponse { seq: number; } +export interface TelemetryEventsParams extends OffsetPaginationParams { + /** + * Restrict results to these event categories. Repeat the parameter for multiple + * values. + */ + category?: Array< + | 'console' + | 'network' + | 'page' + | 'interaction' + | 'control' + | 'connection' + | 'system' + | 'screenshot' + | 'captcha' + | 'monitor' + >; + + /** + * Start of the window: an RFC-3339 timestamp, or a duration like 5m meaning that + * long ago. Defaults to 5m. Ignored when offset is set. + */ + since?: string; + + /** + * End of the window (exclusive): an RFC-3339 timestamp, or a duration like 5m + * meaning that long ago. + */ + until?: string; +} + export interface TelemetryStreamParams { /** * Query param: Pass `all` to start from the oldest retained event instead of only @@ -2057,7 +2145,10 @@ export declare namespace Telemetry { type BrowserTelemetryCategoryConfig as BrowserTelemetryCategoryConfig, type BrowserTelemetryConfig as BrowserTelemetryConfig, type BrowserTelemetryEvent as BrowserTelemetryEvent, + type TelemetryEventsResponse as TelemetryEventsResponse, type TelemetryStreamResponse as TelemetryStreamResponse, + type TelemetryEventsResponsesOffsetPagination as TelemetryEventsResponsesOffsetPagination, + type TelemetryEventsParams as TelemetryEventsParams, type TelemetryStreamParams as TelemetryStreamParams, }; } diff --git a/tests/api-resources/browsers/telemetry.test.ts b/tests/api-resources/browsers/telemetry.test.ts index b0e52695..a36ff8c5 100644 --- a/tests/api-resources/browsers/telemetry.test.ts +++ b/tests/api-resources/browsers/telemetry.test.ts @@ -8,6 +8,36 @@ const client = new Kernel({ }); describe('resource telemetry', () => { + // Mock server tests are disabled + test.skip('events', async () => { + const responsePromise = client.browsers.telemetry.events('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); + }); + + // Mock server tests are disabled + test.skip('events: 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.telemetry.events( + 'id', + { + category: ['console'], + limit: 1, + offset: 0, + since: 'since', + until: 'until', + }, + { path: '/_stainless_unknown_path' }, + ), + ).rejects.toThrow(Kernel.NotFoundError); + }); + // Mock server tests are disabled test.skip('stream', async () => { const responsePromise = client.browsers.telemetry.stream('id'); From beb3227df8bb45b0f5da6da0b8dc50ec8cdcefeb Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 23 Jun 2026 20:45:26 +0000 Subject: [PATCH 459/551] feat: api: support per-acquire start_url override on browser pool acquire --- .stats.yml | 4 ++-- src/resources/browser-pools.ts | 7 +++++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 310bb248..2018924b 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 122 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-7cde13c82c71b7a5fd64b592f853a7c999c0e0c02dce161e6126d0e99df3412b.yml -openapi_spec_hash: 52cda226c70a248cbea3af6c52822b44 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-d9b82fc5346c9be1bf9c2b18792fdcdec6a80a86153ca765c9e93e597b46fa24.yml +openapi_spec_hash: 9cbaab975acfa421b795d11aa635c57e config_hash: 99b2b2a25e8067ad9c9214e38e01d64c diff --git a/src/resources/browser-pools.ts b/src/resources/browser-pools.ts index e4c06190..d37f04ff 100644 --- a/src/resources/browser-pools.ts +++ b/src/resources/browser-pools.ts @@ -646,6 +646,13 @@ export interface BrowserPoolAcquireParams { */ name?: string; + /** + * Optional URL to navigate the acquired browser to. Overrides the pool's start_url + * for this acquire only. Best-effort: failures to navigate do not fail the + * acquire. + */ + start_url?: string; + /** * Optional user-defined key-value tags for the acquired browser session, used to * find and group sessions later. Applies to this lease only and are cleared when From 9c2aac7a330379b4c69ea037b9db50545857d0b9 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 24 Jun 2026 18:31:03 +0000 Subject: [PATCH 460/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 93e2be7f..f61d46cf 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.69.0" + ".": "0.70.0" } diff --git a/package.json b/package.json index 40249fbc..b1fd98e7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.69.0", + "version": "0.70.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index f88b6d2e..9d083b8f 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.69.0'; // x-release-please-version +export const VERSION = '0.70.0'; // x-release-please-version From 1cb3b65b2cfa9c37f03613ec25ba74ca14f969c4 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 24 Jun 2026 18:41:52 +0000 Subject: [PATCH 461/551] feat: Expose audit logs in public SDK --- .stats.yml | 8 +- api.md | 10 ++ src/client.ts | 32 +++++- src/core/pagination.ts | 56 ++++++++++ src/resources/audit-logs.ts | 135 +++++++++++++++++++++++++ src/resources/index.ts | 6 ++ tests/api-resources/audit-logs.test.ts | 41 ++++++++ 7 files changed, 283 insertions(+), 5 deletions(-) create mode 100644 src/resources/audit-logs.ts create mode 100644 tests/api-resources/audit-logs.test.ts diff --git a/.stats.yml b/.stats.yml index 2018924b..04bb94ae 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 122 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-d9b82fc5346c9be1bf9c2b18792fdcdec6a80a86153ca765c9e93e597b46fa24.yml -openapi_spec_hash: 9cbaab975acfa421b795d11aa635c57e -config_hash: 99b2b2a25e8067ad9c9214e38e01d64c +configured_endpoints: 123 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-784ee80ab17dd58e4b44292a4732d1669263d9928df5685e2683c59398e7a043.yml +openapi_spec_hash: d34b07cf9549aef3469c82379f526f95 +config_hash: d52b040438a187c46050e0e8395b2f47 diff --git a/api.md b/api.md index 45d69699..d9a2d969 100644 --- a/api.md +++ b/api.md @@ -393,6 +393,16 @@ Methods: - client.organization.limits.retrieve() -> OrgLimits - client.organization.limits.update({ ...params }) -> OrgLimits +# AuditLogs + +Types: + +- AuditLogEntry + +Methods: + +- client.auditLogs.list({ ...params }) -> AuditLogEntriesPageTokenPagination + # APIKeys Types: diff --git a/src/client.ts b/src/client.ts index b0557644..80e8aae4 100644 --- a/src/client.ts +++ b/src/client.ts @@ -15,7 +15,13 @@ import { stringifyQuery } from './internal/utils/query'; import { VERSION } from './version'; import * as Errors from './core/error'; import * as Pagination from './core/pagination'; -import { AbstractPage, type OffsetPaginationParams, OffsetPaginationResponse } from './core/pagination'; +import { + AbstractPage, + type OffsetPaginationParams, + OffsetPaginationResponse, + type PageTokenPaginationParams, + PageTokenPaginationResponse, +} from './core/pagination'; import * as Uploads from './core/uploads'; import * as API from './resources/index'; import { APIPromise } from './core/api-promise'; @@ -31,6 +37,12 @@ import { CreatedAPIKey, } from './resources/api-keys'; import { AppListParams, AppListResponse, AppListResponsesOffsetPagination, Apps } from './resources/apps'; +import { + AuditLogEntriesPageTokenPagination, + AuditLogEntry, + AuditLogListParams, + AuditLogs, +} from './resources/audit-logs'; import { BrowserPool, BrowserPoolAcquireParams, @@ -963,6 +975,10 @@ export class Kernel { */ projects: API.Projects = new API.Projects(this); organization: API.Organization = new API.Organization(this); + /** + * Read audit log records for the authenticated organization. + */ + auditLogs: API.AuditLogs = new API.AuditLogs(this); /** * Create and manage API keys for organization and project-scoped access. */ @@ -985,12 +1001,19 @@ Kernel.BrowserPools = BrowserPools; Kernel.Credentials = Credentials; Kernel.Projects = Projects; Kernel.Organization = Organization; +Kernel.AuditLogs = AuditLogs; Kernel.APIKeys = APIKeys; Kernel.CredentialProviders = CredentialProviders; export declare namespace Kernel { export type RequestOptions = Opts.RequestOptions; + export import PageTokenPagination = Pagination.PageTokenPagination; + export { + type PageTokenPaginationParams as PageTokenPaginationParams, + type PageTokenPaginationResponse as PageTokenPaginationResponse, + }; + export import OffsetPagination = Pagination.OffsetPagination; export { type OffsetPaginationParams as OffsetPaginationParams, @@ -1122,6 +1145,13 @@ export declare namespace Kernel { export { Organization as Organization }; + export { + AuditLogs as AuditLogs, + type AuditLogEntry as AuditLogEntry, + type AuditLogEntriesPageTokenPagination as AuditLogEntriesPageTokenPagination, + type AuditLogListParams as AuditLogListParams, + }; + export { APIKeys as APIKeys, type APIKey as APIKey, diff --git a/src/core/pagination.ts b/src/core/pagination.ts index 9a507f0e..d4b039dc 100644 --- a/src/core/pagination.ts +++ b/src/core/pagination.ts @@ -107,6 +107,62 @@ export class PagePromise< } } +export type PageTokenPaginationResponse = Item[]; + +export interface PageTokenPaginationParams { + page_token?: string; + + limit?: number; +} + +export class PageTokenPagination extends AbstractPage { + items: Array; + + next_page_token: string | null; + + has_more: boolean | null; + + constructor( + client: Kernel, + response: Response, + body: PageTokenPaginationResponse, + options: FinalRequestOptions, + ) { + super(client, response, body, options); + + this.items = body || []; + this.next_page_token = this.response.headers.get('x-next-page-token') ?? null; + this.has_more = maybeCoerceBoolean(this.response.headers.get('x-has-more')) ?? null; + } + + getPaginatedItems(): Item[] { + return this.items ?? []; + } + + override hasNextPage(): boolean { + if (this.has_more === false) { + return false; + } + + return super.hasNextPage(); + } + + nextPageRequestOptions(): PageRequestOptions | null { + const cursor = this.next_page_token; + if (!cursor) { + return null; + } + + return { + ...this.options, + query: { + ...maybeObj(this.options.query), + page_token: cursor, + }, + }; + } +} + export type OffsetPaginationResponse = Item[]; export interface OffsetPaginationParams { diff --git a/src/resources/audit-logs.ts b/src/resources/audit-logs.ts new file mode 100644 index 00000000..69366c57 --- /dev/null +++ b/src/resources/audit-logs.ts @@ -0,0 +1,135 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../core/resource'; +import { PagePromise, PageTokenPagination, type PageTokenPaginationParams } from '../core/pagination'; +import { RequestOptions } from '../internal/request-options'; + +/** + * Read audit log records for the authenticated organization. + */ +export class AuditLogs extends APIResource { + /** + * API for searching audit logs. Limited to at most 30 day search, returns up to + * 100 records per page. Not recommended for bulk export. + */ + list( + query: AuditLogListParams, + options?: RequestOptions, + ): PagePromise { + return this._client.getAPIList('/audit-logs', PageTokenPagination, { query, ...options }); + } +} + +export type AuditLogEntriesPageTokenPagination = PageTokenPagination; + +export interface AuditLogEntry { + /** + * Authentication strategy used for the request. + */ + auth_strategy: string; + + /** + * Client IP address. + */ + client_ip: string; + + /** + * Request host. + */ + domain: string; + + /** + * Request duration in milliseconds. + */ + duration_ms: number; + + /** + * Email of the authenticated user at request time, if any. + */ + email: string; + + /** + * HTTP method. + */ + method: string; + + /** + * Request path. + */ + path: string; + + /** + * Matched API route pattern, if available. + */ + route: string; + + /** + * HTTP response status code. + */ + status: number; + + /** + * UTC time when the request was received. + */ + timestamp: string; + + /** + * User agent header. + */ + user_agent: string; + + /** + * ID of the authenticated user, if any. + */ + user_id: string; +} + +export interface AuditLogListParams extends PageTokenPaginationParams { + /** + * Upper bound (exclusive) for the audit record timestamp. + */ + end: string; + + /** + * Lower bound (inclusive) for the audit record timestamp. + */ + start: string; + + /** + * Filter by authentication strategy. + */ + auth_strategy?: string; + + /** + * Filter out results by HTTP method. + */ + exclude_method?: string; + + /** + * Filter by HTTP method. + */ + method?: string; + + /** + * Free-text search over path, user ID, email, client IP, and status. + */ + search?: string; + + /** + * Additional user IDs to OR into free-text search. + */ + search_user_id?: Array; + + /** + * Filter by service name. + */ + service?: string; +} + +export declare namespace AuditLogs { + export { + type AuditLogEntry as AuditLogEntry, + type AuditLogEntriesPageTokenPagination as AuditLogEntriesPageTokenPagination, + type AuditLogListParams as AuditLogListParams, + }; +} diff --git a/src/resources/index.ts b/src/resources/index.ts index edbee058..4704f6a5 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -18,6 +18,12 @@ export { type AppListParams, type AppListResponsesOffsetPagination, } from './apps'; +export { + AuditLogs, + type AuditLogEntry, + type AuditLogListParams, + type AuditLogEntriesPageTokenPagination, +} from './audit-logs'; export { Auth } from './auth/auth'; export { BrowserPools, diff --git a/tests/api-resources/audit-logs.test.ts b/tests/api-resources/audit-logs.test.ts new file mode 100644 index 00000000..833cbe15 --- /dev/null +++ b/tests/api-resources/audit-logs.test.ts @@ -0,0 +1,41 @@ +// 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 auditLogs', () => { + // Mock server tests are disabled + test.skip('list: only required params', async () => { + const responsePromise = client.auditLogs.list({ + end: '2026-01-02T00:00:00Z', + start: '2026-01-01T00:00:00Z', + }); + 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); + }); + + // Mock server tests are disabled + test.skip('list: required and optional params', async () => { + const response = await client.auditLogs.list({ + end: '2026-01-02T00:00:00Z', + start: '2026-01-01T00:00:00Z', + auth_strategy: 'auth_strategy', + exclude_method: 'exclude_method', + limit: 1, + method: 'method', + page_token: 'page_token', + search: 'search', + search_user_id: ['string'], + service: 'service', + }); + }); +}); From 149e62d313ceef1ff8d121d07a6a66dbf0f77c9b Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 25 Jun 2026 13:13:15 +0000 Subject: [PATCH 462/551] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 04bb94ae..397b820e 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 123 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-784ee80ab17dd58e4b44292a4732d1669263d9928df5685e2683c59398e7a043.yml -openapi_spec_hash: d34b07cf9549aef3469c82379f526f95 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-ac06dd66a7a0da0dd6dd6cd98127652891b914e880dbaed90d7ab666b13af8a9.yml +openapi_spec_hash: 1d35ae59d6570497f8b379ded59f0434 config_hash: d52b040438a187c46050e0e8395b2f47 From e7c8137a7da14e8aaf66e165de003c1acd3afe1a Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 26 Jun 2026 17:24:45 +0000 Subject: [PATCH 463/551] feat: Add auth connection event timeline endpoint --- .stats.yml | 8 +- api.md | 2 + src/resources/auth/auth.ts | 6 + src/resources/auth/connections.ts | 114 +++++++++++++++++++ src/resources/auth/index.ts | 3 + tests/api-resources/auth/connections.test.ts | 28 +++++ 6 files changed, 157 insertions(+), 4 deletions(-) diff --git a/.stats.yml b/.stats.yml index 397b820e..ef32d38d 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 123 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-ac06dd66a7a0da0dd6dd6cd98127652891b914e880dbaed90d7ab666b13af8a9.yml -openapi_spec_hash: 1d35ae59d6570497f8b379ded59f0434 -config_hash: d52b040438a187c46050e0e8395b2f47 +configured_endpoints: 124 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-4fb45d71a99648425c84bdc8e5780920105cede4ee2d4eac67276d0609ac1e94.yml +openapi_spec_hash: 1f04cb5b36e92db81dfa264c2a59c32a +config_hash: fb167e754ebb3a14649463725891c9d0 diff --git a/api.md b/api.md index d9a2d969..f91b4e8f 100644 --- a/api.md +++ b/api.md @@ -265,6 +265,7 @@ Types: - LoginResponse - ManagedAuth - ManagedAuthCreateRequest +- ManagedAuthTimelineEvent - ManagedAuthUpdateRequest - SubmitFieldsRequest - SubmitFieldsResponse @@ -280,6 +281,7 @@ Methods: - client.auth.connections.follow(id) -> ConnectionFollowResponse - client.auth.connections.login(id, { ...params }) -> LoginResponse - client.auth.connections.submit(id, { ...params }) -> SubmitFieldsResponse +- client.auth.connections.timeline(id, { ...params }) -> ManagedAuthTimelineEventsOffsetPagination # Proxies diff --git a/src/resources/auth/auth.ts b/src/resources/auth/auth.ts index ad3d8de0..b950b004 100644 --- a/src/resources/auth/auth.ts +++ b/src/resources/auth/auth.ts @@ -8,11 +8,14 @@ import { ConnectionListParams, ConnectionLoginParams, ConnectionSubmitParams, + ConnectionTimelineParams, ConnectionUpdateParams, Connections, LoginResponse, ManagedAuth, ManagedAuthCreateRequest, + ManagedAuthTimelineEvent, + ManagedAuthTimelineEventsOffsetPagination, ManagedAuthUpdateRequest, ManagedAuthsOffsetPagination, SubmitFieldsRequest, @@ -31,15 +34,18 @@ export declare namespace Auth { type LoginResponse as LoginResponse, type ManagedAuth as ManagedAuth, type ManagedAuthCreateRequest as ManagedAuthCreateRequest, + type ManagedAuthTimelineEvent as ManagedAuthTimelineEvent, type ManagedAuthUpdateRequest as ManagedAuthUpdateRequest, type SubmitFieldsRequest as SubmitFieldsRequest, type SubmitFieldsResponse as SubmitFieldsResponse, type ConnectionFollowResponse as ConnectionFollowResponse, type ManagedAuthsOffsetPagination as ManagedAuthsOffsetPagination, + type ManagedAuthTimelineEventsOffsetPagination as ManagedAuthTimelineEventsOffsetPagination, type ConnectionCreateParams as ConnectionCreateParams, type ConnectionUpdateParams as ConnectionUpdateParams, type ConnectionListParams as ConnectionListParams, type ConnectionLoginParams as ConnectionLoginParams, type ConnectionSubmitParams as ConnectionSubmitParams, + type ConnectionTimelineParams as ConnectionTimelineParams, }; } diff --git a/src/resources/auth/connections.ts b/src/resources/auth/connections.ts index 1fd1422f..67d067b7 100644 --- a/src/resources/auth/connections.ts +++ b/src/resources/auth/connections.ts @@ -152,10 +152,39 @@ export class Connections extends APIResource { ): APIPromise { return this._client.post(path`/auth/connections/${id}/submit`, { body, ...options }); } + + /** + * Returns a chronological timeline of events for an auth connection — login + * attempts, automatic re-auth attempts, and health checks. Events are returned + * newest-first. + * + * @example + * ```ts + * // Automatically fetches more pages as needed. + * for await (const managedAuthTimelineEvent of client.auth.connections.timeline( + * 'id', + * )) { + * // ... + * } + * ``` + */ + timeline( + id: string, + query: ConnectionTimelineParams | null | undefined = {}, + options?: RequestOptions, + ): PagePromise { + return this._client.getAPIList( + path`/auth/connections/${id}/timeline`, + OffsetPagination, + { query, ...options }, + ); + } } export type ManagedAuthsOffsetPagination = OffsetPagination; +export type ManagedAuthTimelineEventsOffsetPagination = OffsetPagination; + /** * Response from starting a login flow */ @@ -764,6 +793,81 @@ export namespace ManagedAuthCreateRequest { } } +/** + * A single event in an auth connection's history — a login attempt, an automatic + * re-auth attempt, or a health check. + */ +export interface ManagedAuthTimelineEvent { + /** + * Identifier of the underlying login/reauth session or health check. + */ + id: string; + + /** + * Outcome of the event. For login/reauth events this is the flow status + * (IN_PROGRESS, SUCCESS, EXPIRED, CANCELED, FAILED). For health_check events it is + * the observed session state (AUTHENTICATED, NEEDS_AUTH). + */ + status: 'IN_PROGRESS' | 'SUCCESS' | 'EXPIRED' | 'CANCELED' | 'FAILED' | 'AUTHENTICATED' | 'NEEDS_AUTH'; + + /** + * When the event occurred. + */ + timestamp: string; + + /** + * The kind of event. "login" and "reauth" are authentication attempts; + * "health_check" is a periodic session-validity check. + */ + type: 'login' | 'reauth' | 'health_check'; + + /** + * Machine-readable error code. Present when a login/reauth event failed. + */ + error_code?: string; + + /** + * Human-readable error message. Present when a login/reauth event failed. + */ + error_message?: string; + + /** + * The session state observed before this event. Present for health_check events + * that recorded a prior state. + */ + previous_status?: 'AUTHENTICATED' | 'NEEDS_AUTH'; + + /** + * Replay recording ID for the event's browser session, if session recording was + * enabled. + */ + replay_id?: string; + + /** + * The step the flow reached. Present for login/reauth events. + */ + step?: + | 'INITIALIZED' + | 'DISCOVERING' + | 'AWAITING_INPUT' + | 'AWAITING_EXTERNAL_ACTION' + | 'AWAITING_HUMAN_INTERVENTION' + | 'SUBMITTING' + | 'COMPLETED' + | 'EXPIRED'; + + /** + * When the event was last updated. Present for login/reauth events. + */ + updated_at?: string; + + /** + * Visible error message from the website (e.g., 'Incorrect password'). Present + * when the website displayed an error during the attempt. + */ + website_error?: string; +} + /** * Request to update an auth connection's configuration */ @@ -1466,20 +1570,30 @@ export interface ConnectionSubmitParams { sso_provider?: string; } +export interface ConnectionTimelineParams extends OffsetPaginationParams { + /** + * Filter the timeline to a single event type. + */ + type?: 'login' | 'reauth' | 'health_check'; +} + export declare namespace Connections { export { type LoginResponse as LoginResponse, type ManagedAuth as ManagedAuth, type ManagedAuthCreateRequest as ManagedAuthCreateRequest, + type ManagedAuthTimelineEvent as ManagedAuthTimelineEvent, type ManagedAuthUpdateRequest as ManagedAuthUpdateRequest, type SubmitFieldsRequest as SubmitFieldsRequest, type SubmitFieldsResponse as SubmitFieldsResponse, type ConnectionFollowResponse as ConnectionFollowResponse, type ManagedAuthsOffsetPagination as ManagedAuthsOffsetPagination, + type ManagedAuthTimelineEventsOffsetPagination as ManagedAuthTimelineEventsOffsetPagination, type ConnectionCreateParams as ConnectionCreateParams, type ConnectionUpdateParams as ConnectionUpdateParams, type ConnectionListParams as ConnectionListParams, type ConnectionLoginParams as ConnectionLoginParams, type ConnectionSubmitParams as ConnectionSubmitParams, + type ConnectionTimelineParams as ConnectionTimelineParams, }; } diff --git a/src/resources/auth/index.ts b/src/resources/auth/index.ts index a8a6bfef..7d82d6ec 100644 --- a/src/resources/auth/index.ts +++ b/src/resources/auth/index.ts @@ -6,6 +6,7 @@ export { type LoginResponse, type ManagedAuth, type ManagedAuthCreateRequest, + type ManagedAuthTimelineEvent, type ManagedAuthUpdateRequest, type SubmitFieldsRequest, type SubmitFieldsResponse, @@ -15,5 +16,7 @@ export { type ConnectionListParams, type ConnectionLoginParams, type ConnectionSubmitParams, + type ConnectionTimelineParams, type ManagedAuthsOffsetPagination, + type ManagedAuthTimelineEventsOffsetPagination, } from './connections'; diff --git a/tests/api-resources/auth/connections.test.ts b/tests/api-resources/auth/connections.test.ts index ff94370a..66915b5b 100644 --- a/tests/api-resources/auth/connections.test.ts +++ b/tests/api-resources/auth/connections.test.ts @@ -160,4 +160,32 @@ describe('resource connections', () => { expect(dataAndResponse.data).toBe(response); expect(dataAndResponse.response).toBe(rawResponse); }); + + // Mock server tests are disabled + test.skip('timeline', async () => { + const responsePromise = client.auth.connections.timeline('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); + }); + + // Mock server tests are disabled + test.skip('timeline: 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.auth.connections.timeline( + 'id', + { + limit: 100, + offset: 0, + type: 'login', + }, + { path: '/_stainless_unknown_path' }, + ), + ).rejects.toThrow(Kernel.NotFoundError); + }); }); From 5373a256aef2145dcb065933003b82bcdd4b41c1 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 26 Jun 2026 17:38:35 +0000 Subject: [PATCH 464/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index f61d46cf..78b4fb3f 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.70.0" + ".": "0.71.0" } diff --git a/package.json b/package.json index b1fd98e7..2c4fdaa1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.70.0", + "version": "0.71.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 9d083b8f..5f6b920c 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.70.0'; // x-release-please-version +export const VERSION = '0.71.0'; // x-release-please-version From 844443af553b29e573027304cbf71b1613d6532a Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 26 Jun 2026 18:24:15 +0000 Subject: [PATCH 465/551] fix(api): browser pool profile omits save_changes (BrowserPoolProfile) --- .stats.yml | 4 +- src/resources/browser-pools.ts | 111 +++++++++++++++++++--- tests/api-resources/browser-pools.test.ts | 6 +- 3 files changed, 100 insertions(+), 21 deletions(-) diff --git a/.stats.yml b/.stats.yml index ef32d38d..10d90226 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 124 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-4fb45d71a99648425c84bdc8e5780920105cede4ee2d4eac67276d0609ac1e94.yml -openapi_spec_hash: 1f04cb5b36e92db81dfa264c2a59c32a +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-4c243ff089133bd49322d98a6943647589972f71ecadc993fe9e5029972b3995.yml +openapi_spec_hash: a2cb637a19a070d07a1a4343c75444ee config_hash: fb167e754ebb3a14649463725891c9d0 diff --git a/src/resources/browser-pools.ts b/src/resources/browser-pools.ts index d37f04ff..f05c289e 100644 --- a/src/resources/browser-pools.ts +++ b/src/resources/browser-pools.ts @@ -15,7 +15,10 @@ import { path } from '../internal/utils/path'; */ export class BrowserPools extends APIResource { /** - * Create a new browser pool with the specified configuration and size. + * Create a new browser pool with the specified configuration and size. Pooled + * browsers load their profile read-only: any save_changes on the profile is + * ignored (not rejected), so pooled browsers never persist changes back to the + * profile. * * @example * ```ts @@ -43,7 +46,9 @@ export class BrowserPools extends APIResource { } /** - * Updates the configuration used to create browsers in the pool. + * Updates the configuration used to create browsers in the pool. As with creation, + * save_changes on the pool profile is ignored (not rejected); pooled browsers + * never persist changes back to the profile. * * @example * ```ts @@ -236,11 +241,14 @@ export namespace BrowserPool { name?: string; /** - * Profile selection for the browser session. Provide either id or name. If - * specified, the matching profile will be loaded into the browser session. - * Profiles must be created beforehand. + * Profile selection for browsers in a pool. Provide either id or name. The + * matching profile is loaded into every browser in the pool. Profiles must be + * created beforehand. Unlike single browser sessions, pools load the profile + * read-only and never persist changes back to it, so save_changes is omitted here. + * Any save_changes value sent on a pool profile is silently ignored rather than + * rejected, so callers reusing a single-session profile object will not error. */ - profile?: Shared.BrowserProfile; + profile?: BrowserPoolConfig.Profile; /** * Optional proxy to associate to the browser session. Must reference a proxy in @@ -285,6 +293,29 @@ export namespace BrowserPool { */ viewport?: Shared.BrowserViewport; } + + export namespace BrowserPoolConfig { + /** + * Profile selection for browsers in a pool. Provide either id or name. The + * matching profile is loaded into every browser in the pool. Profiles must be + * created beforehand. Unlike single browser sessions, pools load the profile + * read-only and never persist changes back to it, so save_changes is omitted here. + * Any save_changes value sent on a pool profile is silently ignored rather than + * rejected, so callers reusing a single-session profile object will not error. + */ + export interface Profile { + /** + * Profile ID to load for browsers in this pool + */ + id?: string; + + /** + * Profile name to load for browsers in this pool (instead of id). Must be 1-255 + * characters, using letters, numbers, dots, underscores, or hyphens. + */ + name?: string; + } + } } export interface BrowserPoolAcquireResponse { @@ -464,11 +495,14 @@ export interface BrowserPoolCreateParams { name?: string; /** - * Profile selection for the browser session. Provide either id or name. If - * specified, the matching profile will be loaded into the browser session. - * Profiles must be created beforehand. + * Profile selection for browsers in a pool. Provide either id or name. The + * matching profile is loaded into every browser in the pool. Profiles must be + * created beforehand. Unlike single browser sessions, pools load the profile + * read-only and never persist changes back to it, so save_changes is omitted here. + * Any save_changes value sent on a pool profile is silently ignored rather than + * rejected, so callers reusing a single-session profile object will not error. */ - profile?: Shared.BrowserProfile; + profile?: BrowserPoolCreateParams.Profile; /** * Optional proxy to associate to the browser session. Must reference a proxy in @@ -514,6 +548,29 @@ export interface BrowserPoolCreateParams { viewport?: Shared.BrowserViewport; } +export namespace BrowserPoolCreateParams { + /** + * Profile selection for browsers in a pool. Provide either id or name. The + * matching profile is loaded into every browser in the pool. Profiles must be + * created beforehand. Unlike single browser sessions, pools load the profile + * read-only and never persist changes back to it, so save_changes is omitted here. + * Any save_changes value sent on a pool profile is silently ignored rather than + * rejected, so callers reusing a single-session profile object will not error. + */ + export interface Profile { + /** + * Profile ID to load for browsers in this pool + */ + id?: string; + + /** + * Profile name to load for browsers in this pool (instead of id). Must be 1-255 + * characters, using letters, numbers, dots, underscores, or hyphens. + */ + name?: string; + } +} + export interface BrowserPoolUpdateParams { /** * Custom Chrome enterprise policy overrides applied to all browsers in this pool. @@ -558,11 +615,14 @@ export interface BrowserPoolUpdateParams { name?: string; /** - * Profile selection for the browser session. Provide either id or name. If - * specified, the matching profile will be loaded into the browser session. - * Profiles must be created beforehand. + * Profile selection for browsers in a pool. Provide either id or name. The + * matching profile is loaded into every browser in the pool. Profiles must be + * created beforehand. Unlike single browser sessions, pools load the profile + * read-only and never persist changes back to it, so save_changes is omitted here. + * Any save_changes value sent on a pool profile is silently ignored rather than + * rejected, so callers reusing a single-session profile object will not error. */ - profile?: Shared.BrowserProfile; + profile?: BrowserPoolUpdateParams.Profile; /** * Optional proxy to associate to the browser session. Must reference a proxy in @@ -615,6 +675,29 @@ export interface BrowserPoolUpdateParams { viewport?: Shared.BrowserViewport; } +export namespace BrowserPoolUpdateParams { + /** + * Profile selection for browsers in a pool. Provide either id or name. The + * matching profile is loaded into every browser in the pool. Profiles must be + * created beforehand. Unlike single browser sessions, pools load the profile + * read-only and never persist changes back to it, so save_changes is omitted here. + * Any save_changes value sent on a pool profile is silently ignored rather than + * rejected, so callers reusing a single-session profile object will not error. + */ + export interface Profile { + /** + * Profile ID to load for browsers in this pool + */ + id?: string; + + /** + * Profile name to load for browsers in this pool (instead of id). Must be 1-255 + * characters, using letters, numbers, dots, underscores, or hyphens. + */ + name?: string; + } +} + export interface BrowserPoolListParams extends OffsetPaginationParams { /** * Search browser pools by name or ID. diff --git a/tests/api-resources/browser-pools.test.ts b/tests/api-resources/browser-pools.test.ts index ff870709..37fda3c9 100644 --- a/tests/api-resources/browser-pools.test.ts +++ b/tests/api-resources/browser-pools.test.ts @@ -30,11 +30,7 @@ describe('resource browserPools', () => { headless: false, kiosk_mode: true, name: 'my-pool', - profile: { - id: 'id', - name: 'name', - save_changes: true, - }, + profile: { id: 'id', name: 'name' }, proxy_id: 'proxy_id', start_url: 'https://example.com', stealth: true, From ec17d16dda5242edc4dac9f30b43d5aad8501df5 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 26 Jun 2026 18:50:42 +0000 Subject: [PATCH 466/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 78b4fb3f..d5dc7731 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.71.0" + ".": "0.71.1" } diff --git a/package.json b/package.json index 2c4fdaa1..c0a9e645 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.71.0", + "version": "0.71.1", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 5f6b920c..a7af286b 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.71.0'; // x-release-please-version +export const VERSION = '0.71.1'; // x-release-please-version From 10b28b457762b7a8e75662fcec7c3391d400f11c Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 26 Jun 2026 19:45:05 +0000 Subject: [PATCH 467/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index d5dc7731..9e002e98 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.71.1" + ".": "0.72.0" } diff --git a/package.json b/package.json index c0a9e645..26acebb5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.71.1", + "version": "0.72.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index a7af286b..73387f81 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.71.1'; // x-release-please-version +export const VERSION = '0.72.0'; // x-release-please-version From 4c62c13f53ad09f9e341b0f4bdb758d15e61a3fd Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 1 Jul 2026 20:47:06 +0000 Subject: [PATCH 468/551] feat: Add hidden audit-logs export endpoint --- .stats.yml | 8 +-- api.md | 1 + src/client.ts | 2 + src/resources/audit-logs.ts | 74 ++++++++++++++++++++++++++ src/resources/index.ts | 1 + tests/api-resources/audit-logs.test.ts | 17 ++++++ 6 files changed, 99 insertions(+), 4 deletions(-) diff --git a/.stats.yml b/.stats.yml index 10d90226..91180822 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 124 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-4c243ff089133bd49322d98a6943647589972f71ecadc993fe9e5029972b3995.yml -openapi_spec_hash: a2cb637a19a070d07a1a4343c75444ee -config_hash: fb167e754ebb3a14649463725891c9d0 +configured_endpoints: 125 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-55409ab573762d8bc010fb34c885651ca858a97d4353b4776b7aafeaaa313257.yml +openapi_spec_hash: 0cf678d80f2a2b73fb9ec82d05c8cc0a +config_hash: 06186eb40e0058a2a87ac251fc07415d diff --git a/api.md b/api.md index f91b4e8f..d729ebd3 100644 --- a/api.md +++ b/api.md @@ -404,6 +404,7 @@ Types: Methods: - client.auditLogs.list({ ...params }) -> AuditLogEntriesPageTokenPagination +- client.auditLogs.exportChunk({ ...params }) -> Response # APIKeys diff --git a/src/client.ts b/src/client.ts index 80e8aae4..e2f82fd8 100644 --- a/src/client.ts +++ b/src/client.ts @@ -40,6 +40,7 @@ import { AppListParams, AppListResponse, AppListResponsesOffsetPagination, Apps import { AuditLogEntriesPageTokenPagination, AuditLogEntry, + AuditLogExportChunkParams, AuditLogListParams, AuditLogs, } from './resources/audit-logs'; @@ -1150,6 +1151,7 @@ export declare namespace Kernel { type AuditLogEntry as AuditLogEntry, type AuditLogEntriesPageTokenPagination as AuditLogEntriesPageTokenPagination, type AuditLogListParams as AuditLogListParams, + type AuditLogExportChunkParams as AuditLogExportChunkParams, }; export { diff --git a/src/resources/audit-logs.ts b/src/resources/audit-logs.ts index 69366c57..85df4103 100644 --- a/src/resources/audit-logs.ts +++ b/src/resources/audit-logs.ts @@ -1,7 +1,9 @@ // 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 { PagePromise, PageTokenPagination, type PageTokenPaginationParams } from '../core/pagination'; +import { buildHeaders } from '../internal/headers'; import { RequestOptions } from '../internal/request-options'; /** @@ -18,6 +20,20 @@ export class AuditLogs extends APIResource { ): PagePromise { return this._client.getAPIList('/audit-logs', PageTokenPagination, { query, ...options }); } + + /** + * Download an organization's audit log records for a time range as a file, for + * archival, compliance, or offline analysis. For interactive browsing, use GET + * /audit-logs. + */ + exportChunk(query: AuditLogExportChunkParams, options?: RequestOptions): APIPromise { + return this._client.get('/audit-logs/export/chunk', { + query, + ...options, + headers: buildHeaders([{ Accept: 'application/octet-stream' }, options?.headers]), + __binaryResponse: true, + }); + } } export type AuditLogEntriesPageTokenPagination = PageTokenPagination; @@ -126,10 +142,68 @@ export interface AuditLogListParams extends PageTokenPaginationParams { service?: string; } +export interface AuditLogExportChunkParams { + /** + * Upper bound (exclusive) for the audit record timestamp. + */ + end: string; + + /** + * Lower bound (inclusive) for the audit record timestamp. + */ + start: string; + + /** + * Filter by authentication strategy. + */ + auth_strategy?: string; + + /** + * Opaque cursor from X-Next-Cursor for the next chunk of older records. + */ + cursor?: string; + + /** + * Filter out results by HTTP method. + */ + exclude_method?: string; + + /** + * Encoding for the returned chunk. + */ + format?: 'jsonl' | 'jsonl.gz'; + + /** + * Maximum number of records to return in this chunk. + */ + limit?: number; + + /** + * Filter by HTTP method. + */ + method?: string; + + /** + * Free-text search over path, user ID, email, client IP, and status. + */ + search?: string; + + /** + * Additional user IDs to OR into free-text search. + */ + search_user_id?: Array; + + /** + * Filter by service name. + */ + service?: string; +} + export declare namespace AuditLogs { export { type AuditLogEntry as AuditLogEntry, type AuditLogEntriesPageTokenPagination as AuditLogEntriesPageTokenPagination, type AuditLogListParams as AuditLogListParams, + type AuditLogExportChunkParams as AuditLogExportChunkParams, }; } diff --git a/src/resources/index.ts b/src/resources/index.ts index 4704f6a5..a7fdf353 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -22,6 +22,7 @@ export { AuditLogs, type AuditLogEntry, type AuditLogListParams, + type AuditLogExportChunkParams, type AuditLogEntriesPageTokenPagination, } from './audit-logs'; export { Auth } from './auth/auth'; diff --git a/tests/api-resources/audit-logs.test.ts b/tests/api-resources/audit-logs.test.ts index 833cbe15..b1773ceb 100644 --- a/tests/api-resources/audit-logs.test.ts +++ b/tests/api-resources/audit-logs.test.ts @@ -38,4 +38,21 @@ describe('resource auditLogs', () => { service: 'service', }); }); + + // Mock server tests are disabled + test.skip('exportChunk: required and optional params', async () => { + const response = await client.auditLogs.exportChunk({ + end: '2026-01-02T00:00:00Z', + start: '2026-01-01T00:00:00Z', + auth_strategy: 'auth_strategy', + cursor: 'cursor', + exclude_method: 'exclude_method', + format: 'jsonl', + limit: 1, + method: 'method', + search: 'search', + search_user_id: ['string'], + service: 'service', + }); + }); }); From b34df0102d62982a25d4858223ae1e62dde378c4 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 2 Jul 2026 14:10:37 +0000 Subject: [PATCH 469/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 9e002e98..d7203492 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.72.0" + ".": "0.73.0" } diff --git a/package.json b/package.json index 26acebb5..bcbf0b3c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.72.0", + "version": "0.73.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 73387f81..9cf3cf23 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.72.0'; // x-release-please-version +export const VERSION = '0.73.0'; // x-release-please-version From 8672b1c6724f8c697de4fbe909eab9f20c2c6683 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 2 Jul 2026 16:50:28 +0000 Subject: [PATCH 470/551] feat: Add tablet and mobile viewport presets to pool dashboard --- .stats.yml | 4 +- src/resources/browser-pools.ts | 64 ++++++++++++------------ src/resources/browsers/browsers.ts | 80 +++++++++++++++--------------- src/resources/invocations.ts | 16 +++--- src/resources/shared.ts | 16 +++--- 5 files changed, 90 insertions(+), 90 deletions(-) diff --git a/.stats.yml b/.stats.yml index 91180822..a2cf0466 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 125 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-55409ab573762d8bc010fb34c885651ca858a97d4353b4776b7aafeaaa313257.yml -openapi_spec_hash: 0cf678d80f2a2b73fb9ec82d05c8cc0a +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-ea36e417a5dbc80a7dab65b38bd6c892520929d31363e626a3341436d697a17c.yml +openapi_spec_hash: fb15f771cbf9c937a4674f23f9a56050 config_hash: 06186eb40e0058a2a87ac251fc07415d diff --git a/src/resources/browser-pools.ts b/src/resources/browser-pools.ts index f05c289e..2cc6a0e4 100644 --- a/src/resources/browser-pools.ts +++ b/src/resources/browser-pools.ts @@ -282,14 +282,14 @@ export namespace BrowserPool { * image defaults apply (1920x1080@25). For GPU images, the default is * 1920x1080@60. Arbitrary viewport dimensions and refresh rates are accepted. * Known-good presets include: 2560x1440@10, 1920x1080@25, 1920x1200@25, - * 1440x900@25, 1280x800@60, 1024x768@60, 1200x800@60. For GPU images, recommended - * presets use one of these resolutions with refresh rates 60, 30, 25, or 10: - * 800x600, 960x720, 1024x576, 1024x768, 1152x648, 1200x800, 1280x720, 1368x768, - * 1440x900, 1600x900, 1920x1080, 1920x1200, 390x844, 360x250, 768x1024, 800x1600. - * Viewports outside this list may exhibit unstable live view or recording - * behavior. If refresh_rate is not provided, it will be automatically determined - * based on the resolution (higher resolutions use lower refresh rates to keep - * bandwidth reasonable). + * 1440x900@25, 1280x800@60, 1024x768@60, 1200x800@60, 768x1024@60, 390x844@60. For + * GPU images, recommended presets use one of these resolutions with refresh rates + * 60, 30, 25, or 10: 800x600, 960x720, 1024x576, 1024x768, 1152x648, 1200x800, + * 1280x720, 1368x768, 1440x900, 1600x900, 1920x1080, 1920x1200, 390x844, 360x250, + * 768x1024, 800x1600. Viewports outside this list may exhibit unstable live view + * or recording behavior. If refresh_rate is not provided, it will be automatically + * determined based on the resolution (higher resolutions use lower refresh rates + * to keep bandwidth reasonable). */ viewport?: Shared.BrowserViewport; } @@ -438,14 +438,14 @@ export interface BrowserPoolAcquireResponse { * image defaults apply (1920x1080@25). For GPU images, the default is * 1920x1080@60. Arbitrary viewport dimensions and refresh rates are accepted. * Known-good presets include: 2560x1440@10, 1920x1080@25, 1920x1200@25, - * 1440x900@25, 1280x800@60, 1024x768@60, 1200x800@60. For GPU images, recommended - * presets use one of these resolutions with refresh rates 60, 30, 25, or 10: - * 800x600, 960x720, 1024x576, 1024x768, 1152x648, 1200x800, 1280x720, 1368x768, - * 1440x900, 1600x900, 1920x1080, 1920x1200, 390x844, 360x250, 768x1024, 800x1600. - * Viewports outside this list may exhibit unstable live view or recording - * behavior. If refresh_rate is not provided, it will be automatically determined - * based on the resolution (higher resolutions use lower refresh rates to keep - * bandwidth reasonable). + * 1440x900@25, 1280x800@60, 1024x768@60, 1200x800@60, 768x1024@60, 390x844@60. For + * GPU images, recommended presets use one of these resolutions with refresh rates + * 60, 30, 25, or 10: 800x600, 960x720, 1024x576, 1024x768, 1152x648, 1200x800, + * 1280x720, 1368x768, 1440x900, 1600x900, 1920x1080, 1920x1200, 390x844, 360x250, + * 768x1024, 800x1600. Viewports outside this list may exhibit unstable live view + * or recording behavior. If refresh_rate is not provided, it will be automatically + * determined based on the resolution (higher resolutions use lower refresh rates + * to keep bandwidth reasonable). */ viewport?: Shared.BrowserViewport; } @@ -536,14 +536,14 @@ export interface BrowserPoolCreateParams { * image defaults apply (1920x1080@25). For GPU images, the default is * 1920x1080@60. Arbitrary viewport dimensions and refresh rates are accepted. * Known-good presets include: 2560x1440@10, 1920x1080@25, 1920x1200@25, - * 1440x900@25, 1280x800@60, 1024x768@60, 1200x800@60. For GPU images, recommended - * presets use one of these resolutions with refresh rates 60, 30, 25, or 10: - * 800x600, 960x720, 1024x576, 1024x768, 1152x648, 1200x800, 1280x720, 1368x768, - * 1440x900, 1600x900, 1920x1080, 1920x1200, 390x844, 360x250, 768x1024, 800x1600. - * Viewports outside this list may exhibit unstable live view or recording - * behavior. If refresh_rate is not provided, it will be automatically determined - * based on the resolution (higher resolutions use lower refresh rates to keep - * bandwidth reasonable). + * 1440x900@25, 1280x800@60, 1024x768@60, 1200x800@60, 768x1024@60, 390x844@60. For + * GPU images, recommended presets use one of these resolutions with refresh rates + * 60, 30, 25, or 10: 800x600, 960x720, 1024x576, 1024x768, 1152x648, 1200x800, + * 1280x720, 1368x768, 1440x900, 1600x900, 1920x1080, 1920x1200, 390x844, 360x250, + * 768x1024, 800x1600. Viewports outside this list may exhibit unstable live view + * or recording behavior. If refresh_rate is not provided, it will be automatically + * determined based on the resolution (higher resolutions use lower refresh rates + * to keep bandwidth reasonable). */ viewport?: Shared.BrowserViewport; } @@ -663,14 +663,14 @@ export interface BrowserPoolUpdateParams { * image defaults apply (1920x1080@25). For GPU images, the default is * 1920x1080@60. Arbitrary viewport dimensions and refresh rates are accepted. * Known-good presets include: 2560x1440@10, 1920x1080@25, 1920x1200@25, - * 1440x900@25, 1280x800@60, 1024x768@60, 1200x800@60. For GPU images, recommended - * presets use one of these resolutions with refresh rates 60, 30, 25, or 10: - * 800x600, 960x720, 1024x576, 1024x768, 1152x648, 1200x800, 1280x720, 1368x768, - * 1440x900, 1600x900, 1920x1080, 1920x1200, 390x844, 360x250, 768x1024, 800x1600. - * Viewports outside this list may exhibit unstable live view or recording - * behavior. If refresh_rate is not provided, it will be automatically determined - * based on the resolution (higher resolutions use lower refresh rates to keep - * bandwidth reasonable). + * 1440x900@25, 1280x800@60, 1024x768@60, 1200x800@60, 768x1024@60, 390x844@60. For + * GPU images, recommended presets use one of these resolutions with refresh rates + * 60, 30, 25, or 10: 800x600, 960x720, 1024x576, 1024x768, 1152x648, 1200x800, + * 1280x720, 1368x768, 1440x900, 1600x900, 1920x1080, 1920x1200, 390x844, 360x250, + * 768x1024, 800x1600. Viewports outside this list may exhibit unstable live view + * or recording behavior. If refresh_rate is not provided, it will be automatically + * determined based on the resolution (higher resolutions use lower refresh rates + * to keep bandwidth reasonable). */ viewport?: Shared.BrowserViewport; } diff --git a/src/resources/browsers/browsers.ts b/src/resources/browsers/browsers.ts index a14e05a8..c736b882 100644 --- a/src/resources/browsers/browsers.ts +++ b/src/resources/browsers/browsers.ts @@ -449,14 +449,14 @@ export interface BrowserCreateResponse { * image defaults apply (1920x1080@25). For GPU images, the default is * 1920x1080@60. Arbitrary viewport dimensions and refresh rates are accepted. * Known-good presets include: 2560x1440@10, 1920x1080@25, 1920x1200@25, - * 1440x900@25, 1280x800@60, 1024x768@60, 1200x800@60. For GPU images, recommended - * presets use one of these resolutions with refresh rates 60, 30, 25, or 10: - * 800x600, 960x720, 1024x576, 1024x768, 1152x648, 1200x800, 1280x720, 1368x768, - * 1440x900, 1600x900, 1920x1080, 1920x1200, 390x844, 360x250, 768x1024, 800x1600. - * Viewports outside this list may exhibit unstable live view or recording - * behavior. If refresh_rate is not provided, it will be automatically determined - * based on the resolution (higher resolutions use lower refresh rates to keep - * bandwidth reasonable). + * 1440x900@25, 1280x800@60, 1024x768@60, 1200x800@60, 768x1024@60, 390x844@60. For + * GPU images, recommended presets use one of these resolutions with refresh rates + * 60, 30, 25, or 10: 800x600, 960x720, 1024x576, 1024x768, 1152x648, 1200x800, + * 1280x720, 1368x768, 1440x900, 1600x900, 1920x1080, 1920x1200, 390x844, 360x250, + * 768x1024, 800x1600. Viewports outside this list may exhibit unstable live view + * or recording behavior. If refresh_rate is not provided, it will be automatically + * determined based on the resolution (higher resolutions use lower refresh rates + * to keep bandwidth reasonable). */ viewport?: Shared.BrowserViewport; } @@ -581,14 +581,14 @@ export interface BrowserRetrieveResponse { * image defaults apply (1920x1080@25). For GPU images, the default is * 1920x1080@60. Arbitrary viewport dimensions and refresh rates are accepted. * Known-good presets include: 2560x1440@10, 1920x1080@25, 1920x1200@25, - * 1440x900@25, 1280x800@60, 1024x768@60, 1200x800@60. For GPU images, recommended - * presets use one of these resolutions with refresh rates 60, 30, 25, or 10: - * 800x600, 960x720, 1024x576, 1024x768, 1152x648, 1200x800, 1280x720, 1368x768, - * 1440x900, 1600x900, 1920x1080, 1920x1200, 390x844, 360x250, 768x1024, 800x1600. - * Viewports outside this list may exhibit unstable live view or recording - * behavior. If refresh_rate is not provided, it will be automatically determined - * based on the resolution (higher resolutions use lower refresh rates to keep - * bandwidth reasonable). + * 1440x900@25, 1280x800@60, 1024x768@60, 1200x800@60, 768x1024@60, 390x844@60. For + * GPU images, recommended presets use one of these resolutions with refresh rates + * 60, 30, 25, or 10: 800x600, 960x720, 1024x576, 1024x768, 1152x648, 1200x800, + * 1280x720, 1368x768, 1440x900, 1600x900, 1920x1080, 1920x1200, 390x844, 360x250, + * 768x1024, 800x1600. Viewports outside this list may exhibit unstable live view + * or recording behavior. If refresh_rate is not provided, it will be automatically + * determined based on the resolution (higher resolutions use lower refresh rates + * to keep bandwidth reasonable). */ viewport?: Shared.BrowserViewport; } @@ -713,14 +713,14 @@ export interface BrowserUpdateResponse { * image defaults apply (1920x1080@25). For GPU images, the default is * 1920x1080@60. Arbitrary viewport dimensions and refresh rates are accepted. * Known-good presets include: 2560x1440@10, 1920x1080@25, 1920x1200@25, - * 1440x900@25, 1280x800@60, 1024x768@60, 1200x800@60. For GPU images, recommended - * presets use one of these resolutions with refresh rates 60, 30, 25, or 10: - * 800x600, 960x720, 1024x576, 1024x768, 1152x648, 1200x800, 1280x720, 1368x768, - * 1440x900, 1600x900, 1920x1080, 1920x1200, 390x844, 360x250, 768x1024, 800x1600. - * Viewports outside this list may exhibit unstable live view or recording - * behavior. If refresh_rate is not provided, it will be automatically determined - * based on the resolution (higher resolutions use lower refresh rates to keep - * bandwidth reasonable). + * 1440x900@25, 1280x800@60, 1024x768@60, 1200x800@60, 768x1024@60, 390x844@60. For + * GPU images, recommended presets use one of these resolutions with refresh rates + * 60, 30, 25, or 10: 800x600, 960x720, 1024x576, 1024x768, 1152x648, 1200x800, + * 1280x720, 1368x768, 1440x900, 1600x900, 1920x1080, 1920x1200, 390x844, 360x250, + * 768x1024, 800x1600. Viewports outside this list may exhibit unstable live view + * or recording behavior. If refresh_rate is not provided, it will be automatically + * determined based on the resolution (higher resolutions use lower refresh rates + * to keep bandwidth reasonable). */ viewport?: Shared.BrowserViewport; } @@ -845,14 +845,14 @@ export interface BrowserListResponse { * image defaults apply (1920x1080@25). For GPU images, the default is * 1920x1080@60. Arbitrary viewport dimensions and refresh rates are accepted. * Known-good presets include: 2560x1440@10, 1920x1080@25, 1920x1200@25, - * 1440x900@25, 1280x800@60, 1024x768@60, 1200x800@60. For GPU images, recommended - * presets use one of these resolutions with refresh rates 60, 30, 25, or 10: - * 800x600, 960x720, 1024x576, 1024x768, 1152x648, 1200x800, 1280x720, 1368x768, - * 1440x900, 1600x900, 1920x1080, 1920x1200, 390x844, 360x250, 768x1024, 800x1600. - * Viewports outside this list may exhibit unstable live view or recording - * behavior. If refresh_rate is not provided, it will be automatically determined - * based on the resolution (higher resolutions use lower refresh rates to keep - * bandwidth reasonable). + * 1440x900@25, 1280x800@60, 1024x768@60, 1200x800@60, 768x1024@60, 390x844@60. For + * GPU images, recommended presets use one of these resolutions with refresh rates + * 60, 30, 25, or 10: 800x600, 960x720, 1024x576, 1024x768, 1152x648, 1200x800, + * 1280x720, 1368x768, 1440x900, 1600x900, 1920x1080, 1920x1200, 390x844, 360x250, + * 768x1024, 800x1600. Viewports outside this list may exhibit unstable live view + * or recording behavior. If refresh_rate is not provided, it will be automatically + * determined based on the resolution (higher resolutions use lower refresh rates + * to keep bandwidth reasonable). */ viewport?: Shared.BrowserViewport; } @@ -982,14 +982,14 @@ export interface BrowserCreateParams { * image defaults apply (1920x1080@25). For GPU images, the default is * 1920x1080@60. Arbitrary viewport dimensions and refresh rates are accepted. * Known-good presets include: 2560x1440@10, 1920x1080@25, 1920x1200@25, - * 1440x900@25, 1280x800@60, 1024x768@60, 1200x800@60. For GPU images, recommended - * presets use one of these resolutions with refresh rates 60, 30, 25, or 10: - * 800x600, 960x720, 1024x576, 1024x768, 1152x648, 1200x800, 1280x720, 1368x768, - * 1440x900, 1600x900, 1920x1080, 1920x1200, 390x844, 360x250, 768x1024, 800x1600. - * Viewports outside this list may exhibit unstable live view or recording - * behavior. If refresh_rate is not provided, it will be automatically determined - * based on the resolution (higher resolutions use lower refresh rates to keep - * bandwidth reasonable). + * 1440x900@25, 1280x800@60, 1024x768@60, 1200x800@60, 768x1024@60, 390x844@60. For + * GPU images, recommended presets use one of these resolutions with refresh rates + * 60, 30, 25, or 10: 800x600, 960x720, 1024x576, 1024x768, 1152x648, 1200x800, + * 1280x720, 1368x768, 1440x900, 1600x900, 1920x1080, 1920x1200, 390x844, 360x250, + * 768x1024, 800x1600. Viewports outside this list may exhibit unstable live view + * or recording behavior. If refresh_rate is not provided, it will be automatically + * determined based on the resolution (higher resolutions use lower refresh rates + * to keep bandwidth reasonable). */ viewport?: Shared.BrowserViewport; } diff --git a/src/resources/invocations.ts b/src/resources/invocations.ts index 381ff1bc..4c66e43a 100644 --- a/src/resources/invocations.ts +++ b/src/resources/invocations.ts @@ -538,14 +538,14 @@ export namespace InvocationListBrowsersResponse { * image defaults apply (1920x1080@25). For GPU images, the default is * 1920x1080@60. Arbitrary viewport dimensions and refresh rates are accepted. * Known-good presets include: 2560x1440@10, 1920x1080@25, 1920x1200@25, - * 1440x900@25, 1280x800@60, 1024x768@60, 1200x800@60. For GPU images, recommended - * presets use one of these resolutions with refresh rates 60, 30, 25, or 10: - * 800x600, 960x720, 1024x576, 1024x768, 1152x648, 1200x800, 1280x720, 1368x768, - * 1440x900, 1600x900, 1920x1080, 1920x1200, 390x844, 360x250, 768x1024, 800x1600. - * Viewports outside this list may exhibit unstable live view or recording - * behavior. If refresh_rate is not provided, it will be automatically determined - * based on the resolution (higher resolutions use lower refresh rates to keep - * bandwidth reasonable). + * 1440x900@25, 1280x800@60, 1024x768@60, 1200x800@60, 768x1024@60, 390x844@60. For + * GPU images, recommended presets use one of these resolutions with refresh rates + * 60, 30, 25, or 10: 800x600, 960x720, 1024x576, 1024x768, 1152x648, 1200x800, + * 1280x720, 1368x768, 1440x900, 1600x900, 1920x1080, 1920x1200, 390x844, 360x250, + * 768x1024, 800x1600. Viewports outside this list may exhibit unstable live view + * or recording behavior. If refresh_rate is not provided, it will be automatically + * determined based on the resolution (higher resolutions use lower refresh rates + * to keep bandwidth reasonable). */ viewport?: Shared.BrowserViewport; } diff --git a/src/resources/shared.ts b/src/resources/shared.ts index e18de324..ea860cd2 100644 --- a/src/resources/shared.ts +++ b/src/resources/shared.ts @@ -68,14 +68,14 @@ export interface BrowserProfile { * image defaults apply (1920x1080@25). For GPU images, the default is * 1920x1080@60. Arbitrary viewport dimensions and refresh rates are accepted. * Known-good presets include: 2560x1440@10, 1920x1080@25, 1920x1200@25, - * 1440x900@25, 1280x800@60, 1024x768@60, 1200x800@60. For GPU images, recommended - * presets use one of these resolutions with refresh rates 60, 30, 25, or 10: - * 800x600, 960x720, 1024x576, 1024x768, 1152x648, 1200x800, 1280x720, 1368x768, - * 1440x900, 1600x900, 1920x1080, 1920x1200, 390x844, 360x250, 768x1024, 800x1600. - * Viewports outside this list may exhibit unstable live view or recording - * behavior. If refresh_rate is not provided, it will be automatically determined - * based on the resolution (higher resolutions use lower refresh rates to keep - * bandwidth reasonable). + * 1440x900@25, 1280x800@60, 1024x768@60, 1200x800@60, 768x1024@60, 390x844@60. For + * GPU images, recommended presets use one of these resolutions with refresh rates + * 60, 30, 25, or 10: 800x600, 960x720, 1024x576, 1024x768, 1152x648, 1200x800, + * 1280x720, 1368x768, 1440x900, 1600x900, 1920x1080, 1920x1200, 390x844, 360x250, + * 768x1024, 800x1600. Viewports outside this list may exhibit unstable live view + * or recording behavior. If refresh_rate is not provided, it will be automatically + * determined based on the resolution (higher resolutions use lower refresh rates + * to keep bandwidth reasonable). */ export interface BrowserViewport { /** From 85e3abf18b71689fd92bec45504d07e03e39dea0 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 6 Jul 2026 17:37:59 +0000 Subject: [PATCH 471/551] feat: Add order=desc pagination to telemetry event reads --- .stats.yml | 4 ++-- src/resources/browsers/telemetry.ts | 18 ++++++++++++++---- tests/api-resources/browsers/telemetry.test.ts | 1 + 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/.stats.yml b/.stats.yml index a2cf0466..0297d26a 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 125 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-ea36e417a5dbc80a7dab65b38bd6c892520929d31363e626a3341436d697a17c.yml -openapi_spec_hash: fb15f771cbf9c937a4674f23f9a56050 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-ebbe079bb2542625826422afd876a3e8b499c579cf45efc5fd50e7982d34df7d.yml +openapi_spec_hash: db850b61a0d71fe9f4b642df8782d7ae config_hash: 06186eb40e0058a2a87ac251fc07415d diff --git a/src/resources/browsers/telemetry.ts b/src/resources/browsers/telemetry.ts index 59bed198..dcc2894a 100644 --- a/src/resources/browsers/telemetry.ts +++ b/src/resources/browsers/telemetry.ts @@ -14,10 +14,10 @@ import { path } from '../../internal/utils/path'; */ export class Telemetry extends APIResource { /** - * Reads a page of telemetry events for the browser session in ascending sequence - * order. To page through results, pass the X-Next-Offset value from the previous - * response as offset and repeat while X-Has-More is true. Returns an empty list - * when telemetry data is unavailable. + * Reads a page of telemetry events for the browser session. To page through + * results, pass the X-Next-Offset value from the previous response as offset and + * repeat while X-Has-More is true. Returns an empty list when telemetry data is + * unavailable. * * @example * ```ts @@ -2076,6 +2076,16 @@ export interface TelemetryEventsParams extends OffsetPaginationParams { | 'monitor' >; + /** + * Read direction. asc (default) reads oldest first, starting from since or the + * offset cursor. desc reads newest first: each request returns one page of up to + * limit records ending at the offset cursor (or until, or the newest archived + * event); combining desc with since is rejected with a 400. In either direction + * the category filter applies within the page, so a filtered page may be empty + * while X-Has-More is true. + */ + order?: string; + /** * Start of the window: an RFC-3339 timestamp, or a duration like 5m meaning that * long ago. Defaults to 5m. Ignored when offset is set. diff --git a/tests/api-resources/browsers/telemetry.test.ts b/tests/api-resources/browsers/telemetry.test.ts index a36ff8c5..d096d2c5 100644 --- a/tests/api-resources/browsers/telemetry.test.ts +++ b/tests/api-resources/browsers/telemetry.test.ts @@ -30,6 +30,7 @@ describe('resource telemetry', () => { category: ['console'], limit: 1, offset: 0, + order: 'order', since: 'since', until: 'until', }, From c1e1fbf86e2fc5c570837663bd87707312d02103 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 6 Jul 2026 17:45:23 +0000 Subject: [PATCH 472/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index d7203492..52ffe5a9 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.73.0" + ".": "0.74.0" } diff --git a/package.json b/package.json index bcbf0b3c..cae70fdf 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.73.0", + "version": "0.74.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 9cf3cf23..c88d4bfa 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.73.0'; // x-release-please-version +export const VERSION = '0.74.0'; // x-release-please-version From b28555a7acbf20f151ac6dd6094a318f82769cea Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 6 Jul 2026 19:34:50 +0000 Subject: [PATCH 473/551] docs(api): clarify reuse/discard_all_idle pool config staleness --- .stats.yml | 4 ++-- src/resources/browser-pools.ts | 13 ++++++++++--- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/.stats.yml b/.stats.yml index 0297d26a..40adb553 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 125 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-ebbe079bb2542625826422afd876a3e8b499c579cf45efc5fd50e7982d34df7d.yml -openapi_spec_hash: db850b61a0d71fe9f4b642df8782d7ae +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-83323f87ab825547b6cd11caa46e2643ebb0a68bbd326d4e07ccab970638fc03.yml +openapi_spec_hash: 69ed04a66b4ef68e97f7bdc07dfe6df2 config_hash: 06186eb40e0058a2a87ac251fc07415d diff --git a/src/resources/browser-pools.ts b/src/resources/browser-pools.ts index 2cc6a0e4..f157c729 100644 --- a/src/resources/browser-pools.ts +++ b/src/resources/browser-pools.ts @@ -581,8 +581,12 @@ export interface BrowserPoolUpdateParams { chrome_policy?: { [key: string]: unknown }; /** - * Whether to discard all idle browsers and rebuild the pool immediately. Defaults - * to false. + * Whether to discard all idle browsers and rebuild them immediately with the new + * configuration. Defaults to false. Only browsers that are idle when the update + * runs are rebuilt. A browser that is in use during the update keeps its original + * configuration, and if it is later released with `reuse: true` it returns to the + * pool with that stale configuration until it is discarded (by this flag on a + * later update, or by flushing the pool). */ discard_all_idle?: boolean; @@ -752,7 +756,10 @@ export interface BrowserPoolReleaseParams { /** * Whether to reuse the browser instance or destroy it and create a new one. - * Defaults to true. + * Defaults to true. A reused browser keeps the configuration it was created with, + * so it does not pick up pool configuration changes made while it was in use. + * Release with `reuse: false`, or flush the pool afterward, to rebuild it with the + * current configuration. */ reuse?: boolean; } From 52b1f1011c48a9ef6e43aecdcfa878dd3bf7237a Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 6 Jul 2026 20:14:59 +0000 Subject: [PATCH 474/551] feat: Document env var redaction on deployment and app reads --- .stats.yml | 4 ++-- src/resources/apps.ts | 4 +++- src/resources/deployments.ts | 19 ++++++++++++++----- 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/.stats.yml b/.stats.yml index 40adb553..34f90982 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 125 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-83323f87ab825547b6cd11caa46e2643ebb0a68bbd326d4e07ccab970638fc03.yml -openapi_spec_hash: 69ed04a66b4ef68e97f7bdc07dfe6df2 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-89a500b26fe8126183d55aaca53f5615c6a25561d8e01e907f4998239ccc7a0b.yml +openapi_spec_hash: 50236a5e713d5424ca35c0883926b0a5 config_hash: 06186eb40e0058a2a87ac251fc07415d diff --git a/src/resources/apps.ts b/src/resources/apps.ts index 915193db..c6710c98 100644 --- a/src/resources/apps.ts +++ b/src/resources/apps.ts @@ -47,7 +47,9 @@ export interface AppListResponse { deployment: string; /** - * Environment variables configured for this app version + * Environment variables configured for this app version. Values are redacted for + * API key, OAuth, and managed-auth callers, which receive every key with an empty + * string value. Only dashboard sessions receive the actual values. */ env_vars: { [key: string]: string }; diff --git a/src/resources/deployments.ts b/src/resources/deployments.ts index a389f8bd..597dad21 100644 --- a/src/resources/deployments.ts +++ b/src/resources/deployments.ts @@ -159,7 +159,9 @@ export namespace DeploymentStateEvent { entrypoint_rel_path?: string; /** - * Environment variables configured for this deployment + * Environment variables configured for this deployment. Values are redacted for + * API key, OAuth, and managed-auth callers, which receive every key with an empty + * string value. Only dashboard sessions receive the actual values. */ env_vars?: { [key: string]: string }; @@ -205,7 +207,9 @@ export interface DeploymentCreateResponse { entrypoint_rel_path?: string; /** - * Environment variables configured for this deployment + * Environment variables configured for this deployment. Values are redacted for + * API key, OAuth, and managed-auth callers, which receive every key with an empty + * string value. Only dashboard sessions receive the actual values. */ env_vars?: { [key: string]: string }; @@ -250,7 +254,9 @@ export interface DeploymentRetrieveResponse { entrypoint_rel_path?: string; /** - * Environment variables configured for this deployment + * Environment variables configured for this deployment. Values are redacted for + * API key, OAuth, and managed-auth callers, which receive every key with an empty + * string value. Only dashboard sessions receive the actual values. */ env_vars?: { [key: string]: string }; @@ -295,7 +301,9 @@ export interface DeploymentListResponse { entrypoint_rel_path?: string; /** - * Environment variables configured for this deployment + * Environment variables configured for this deployment. Values are redacted for + * API key, OAuth, and managed-auth callers, which receive every key with an empty + * string value. Only dashboard sessions receive the actual values. */ env_vars?: { [key: string]: string }; @@ -361,7 +369,8 @@ export namespace DeploymentFollowResponse { version: string; /** - * Environment variables configured for this app version + * Environment variables configured for this app version. Not currently populated + * on streamed app_version_summary events. */ env_vars?: { [key: string]: string }; } From 715824c9af0f587ec32e9accd307a01ab4b7659e Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 7 Jul 2026 18:01:45 +0000 Subject: [PATCH 475/551] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 34f90982..199caa16 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 125 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-89a500b26fe8126183d55aaca53f5615c6a25561d8e01e907f4998239ccc7a0b.yml -openapi_spec_hash: 50236a5e713d5424ca35c0883926b0a5 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-073bade6de836ae1cf0cb3f8551cc5c6635f98649d7cf5059ef6819e9ce0f508.yml +openapi_spec_hash: e84f887c72b5c7335158b706e4218bc7 config_hash: 06186eb40e0058a2a87ac251fc07415d From 2453e7b5cdc3b353880e3d22615c260966b3425f Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 7 Jul 2026 21:27:39 +0000 Subject: [PATCH 476/551] feat: Reject API key self-deletion --- .stats.yml | 4 ++-- src/resources/api-keys.ts | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.stats.yml b/.stats.yml index 199caa16..02a158e4 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 125 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-073bade6de836ae1cf0cb3f8551cc5c6635f98649d7cf5059ef6819e9ce0f508.yml -openapi_spec_hash: e84f887c72b5c7335158b706e4218bc7 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-bd00e13bd6d37c150009e612ebeb6ef03d050610f80aaed517e283812c7b9ba9.yml +openapi_spec_hash: 08c7c031877d6b882ff291b389937028 config_hash: 06186eb40e0058a2a87ac251fc07415d diff --git a/src/resources/api-keys.ts b/src/resources/api-keys.ts index 60b41f54..a82e2c32 100644 --- a/src/resources/api-keys.ts +++ b/src/resources/api-keys.ts @@ -75,7 +75,8 @@ export class APIKeys extends APIResource { } /** - * Delete an API key. + * Delete an API key. A key cannot delete itself; use a different key to delete + * this one. * * @example * ```ts From fc200cae260a3038a5f0be607aa613e0ca860341 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 7 Jul 2026 21:51:35 +0000 Subject: [PATCH 477/551] feat: Store and return a sha256 checksum for uploaded extensions --- .stats.yml | 4 ++-- src/resources/extensions.ts | 27 +++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 02a158e4..06a81919 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 125 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-bd00e13bd6d37c150009e612ebeb6ef03d050610f80aaed517e283812c7b9ba9.yml -openapi_spec_hash: 08c7c031877d6b882ff291b389937028 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-e123113e7c86e8a61c763f0078adec5b0a7df621f2c31824e8f553331cf7a624.yml +openapi_spec_hash: 940fb94967b6cb5e13daef6161d3abbf config_hash: 06186eb40e0058a2a87ac251fc07415d diff --git a/src/resources/extensions.ts b/src/resources/extensions.ts index 79e98e12..809c2a3e 100644 --- a/src/resources/extensions.ts +++ b/src/resources/extensions.ts @@ -147,6 +147,15 @@ export interface ExtensionListResponse { */ size_bytes: number; + /** + * SHA-256 checksum, encoded as lowercase hexadecimal, of the exact uploaded + * extension archive bytes. This is not a normalized checksum of the extension + * contents; archive metadata, file ordering, and compression can change the + * checksum for otherwise identical contents. Omitted for legacy rows and + * server-repackaged Chrome Web Store extensions. + */ + checksum?: string | null; + /** * Timestamp when the extension was last used */ @@ -178,6 +187,15 @@ export interface ExtensionGetResponse { */ size_bytes: number; + /** + * SHA-256 checksum, encoded as lowercase hexadecimal, of the exact uploaded + * extension archive bytes. This is not a normalized checksum of the extension + * contents; archive metadata, file ordering, and compression can change the + * checksum for otherwise identical contents. Omitted for legacy rows and + * server-repackaged Chrome Web Store extensions. + */ + checksum?: string | null; + /** * Timestamp when the extension was last used */ @@ -209,6 +227,15 @@ export interface ExtensionUploadResponse { */ size_bytes: number; + /** + * SHA-256 checksum, encoded as lowercase hexadecimal, of the exact uploaded + * extension archive bytes. This is not a normalized checksum of the extension + * contents; archive metadata, file ordering, and compression can change the + * checksum for otherwise identical contents. Omitted for legacy rows and + * server-repackaged Chrome Web Store extensions. + */ + checksum?: string | null; + /** * Timestamp when the extension was last used */ From b6cc0bb3de10ac9afdf5b424bcb3d57ef1c54945 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 7 Jul 2026 22:19:52 +0000 Subject: [PATCH 478/551] =?UTF-8?q?feat:=20Revert=20"Store=20and=20return?= =?UTF-8?q?=20a=20sha256=20checksum=20for=20uploaded=20extensions=20(#?= =?UTF-8?q?=E2=80=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .stats.yml | 4 ++-- src/resources/extensions.ts | 27 --------------------------- 2 files changed, 2 insertions(+), 29 deletions(-) diff --git a/.stats.yml b/.stats.yml index 06a81919..70c2c4fc 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 125 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-e123113e7c86e8a61c763f0078adec5b0a7df621f2c31824e8f553331cf7a624.yml -openapi_spec_hash: 940fb94967b6cb5e13daef6161d3abbf +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-4395690aa03bf5e2482d60132f7eebdbf88265af3d53098789f6c2f3c623d769.yml +openapi_spec_hash: ad7c56d655a6e3899532caa4588a02b7 config_hash: 06186eb40e0058a2a87ac251fc07415d diff --git a/src/resources/extensions.ts b/src/resources/extensions.ts index 809c2a3e..79e98e12 100644 --- a/src/resources/extensions.ts +++ b/src/resources/extensions.ts @@ -147,15 +147,6 @@ export interface ExtensionListResponse { */ size_bytes: number; - /** - * SHA-256 checksum, encoded as lowercase hexadecimal, of the exact uploaded - * extension archive bytes. This is not a normalized checksum of the extension - * contents; archive metadata, file ordering, and compression can change the - * checksum for otherwise identical contents. Omitted for legacy rows and - * server-repackaged Chrome Web Store extensions. - */ - checksum?: string | null; - /** * Timestamp when the extension was last used */ @@ -187,15 +178,6 @@ export interface ExtensionGetResponse { */ size_bytes: number; - /** - * SHA-256 checksum, encoded as lowercase hexadecimal, of the exact uploaded - * extension archive bytes. This is not a normalized checksum of the extension - * contents; archive metadata, file ordering, and compression can change the - * checksum for otherwise identical contents. Omitted for legacy rows and - * server-repackaged Chrome Web Store extensions. - */ - checksum?: string | null; - /** * Timestamp when the extension was last used */ @@ -227,15 +209,6 @@ export interface ExtensionUploadResponse { */ size_bytes: number; - /** - * SHA-256 checksum, encoded as lowercase hexadecimal, of the exact uploaded - * extension archive bytes. This is not a normalized checksum of the extension - * contents; archive metadata, file ordering, and compression can change the - * checksum for otherwise identical contents. Omitted for legacy rows and - * server-repackaged Chrome Web Store extensions. - */ - checksum?: string | null; - /** * Timestamp when the extension was last used */ From 46bdefcd6ad22cf55efba478c085f66502c3d344 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 8 Jul 2026 15:31:24 +0000 Subject: [PATCH 479/551] feat: Accept comma-separated search_user_id in audit-logs endpoints --- .stats.yml | 4 ++-- yarn.lock | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.stats.yml b/.stats.yml index 70c2c4fc..2c231f14 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 125 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-4395690aa03bf5e2482d60132f7eebdbf88265af3d53098789f6c2f3c623d769.yml -openapi_spec_hash: ad7c56d655a6e3899532caa4588a02b7 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-f6795e5d85e37b74f59876434c74b598e34171f99bc598c85b789abbb60614f1.yml +openapi_spec_hash: 98e86fcbf0710a693bb1e03170ca85c3 config_hash: 06186eb40e0058a2a87ac251fc07415d diff --git a/yarn.lock b/yarn.lock index 06fc1085..38236e67 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1215,9 +1215,9 @@ baseline-browser-mapping@^2.9.0: integrity sha512-B0xUquLkiGLgHhpPBqvl7GWegWBUNuujQ6kXd/r1U38ElPT6Ok8KZ8e+FpUGEc2ZoRQUzq/aUnaKFc/svWUGSg== brace-expansion@^2.0.2: - version "2.1.1" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.1.1.tgz#c68b1c4111c76aae3a6fba55d496cee10c39dad8" - integrity sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA== + version "2.1.2" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.1.2.tgz#0bba2271feb7d458b0d31ad13625aaa4754431e2" + integrity sha512-w5JZcKgdhDOgOwm8H+KgbosopHMuGcl6qbulwjtz3SM7I7P3yW1eAjzMPLrIE+NQ9vjgANKHWeMHnrT0OXW1oA== dependencies: balanced-match "^1.0.0" From 08f8b9d65c2e7472438036fbebc5fb392728ff27 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 8 Jul 2026 17:42:41 +0000 Subject: [PATCH 480/551] feat: Auto-flush pools when a managed auth profile re-authenticates --- .stats.yml | 4 +- src/resources/browser-pools.ts | 91 ++++++++++++++--------- tests/api-resources/browser-pools.test.ts | 1 + 3 files changed, 57 insertions(+), 39 deletions(-) diff --git a/.stats.yml b/.stats.yml index 2c231f14..d888de6d 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 125 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-f6795e5d85e37b74f59876434c74b598e34171f99bc598c85b789abbb60614f1.yml -openapi_spec_hash: 98e86fcbf0710a693bb1e03170ca85c3 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-58ad412d62b3d94e3258c911d7028716d71191358ff769ce494c4b2d87027254.yml +openapi_spec_hash: 45d710b7d2a9beadff021514bb997ba1 config_hash: 06186eb40e0058a2a87ac251fc07415d diff --git a/src/resources/browser-pools.ts b/src/resources/browser-pools.ts index f157c729..39c9d8b8 100644 --- a/src/resources/browser-pools.ts +++ b/src/resources/browser-pools.ts @@ -48,7 +48,9 @@ export class BrowserPools extends APIResource { /** * Updates the configuration used to create browsers in the pool. As with creation, * save_changes on the pool profile is ignored (not rejected); pooled browsers - * never persist changes back to the profile. + * never persist changes back to the profile. To clear the profile reference, send + * `profile: { "id": "" }`. Clearing the profile also disables + * `refresh_on_profile_update`. * * @example * ```ts @@ -241,12 +243,11 @@ export namespace BrowserPool { name?: string; /** - * Profile selection for browsers in a pool. Provide either id or name. The - * matching profile is loaded into every browser in the pool. Profiles must be - * created beforehand. Unlike single browser sessions, pools load the profile - * read-only and never persist changes back to it, so save_changes is omitted here. - * Any save_changes value sent on a pool profile is silently ignored rather than - * rejected, so callers reusing a single-session profile object will not error. + * Profile configuration for browsers in a pool. Provide either id or name. + * Profiles must be created beforehand. Unlike single browser sessions, pools load + * the profile read-only and never persist changes back to it, so save_changes is + * omitted here. Any save_changes value sent on a pool profile is silently ignored + * rather than rejected. */ profile?: BrowserPoolConfig.Profile; @@ -256,6 +257,13 @@ export namespace BrowserPool { */ proxy_id?: string; + /** + * When true, flush idle browsers when the profile the pool uses is updated, so + * pool browsers pick up the latest profile data. Requires a profile to be set on + * the pool. + */ + refresh_on_profile_update?: boolean; + /** * Optional URL to navigate to when a new browser is warmed into the pool. * Best-effort: failures to navigate do not fail pool fill. Only applied to @@ -296,12 +304,11 @@ export namespace BrowserPool { export namespace BrowserPoolConfig { /** - * Profile selection for browsers in a pool. Provide either id or name. The - * matching profile is loaded into every browser in the pool. Profiles must be - * created beforehand. Unlike single browser sessions, pools load the profile - * read-only and never persist changes back to it, so save_changes is omitted here. - * Any save_changes value sent on a pool profile is silently ignored rather than - * rejected, so callers reusing a single-session profile object will not error. + * Profile configuration for browsers in a pool. Provide either id or name. + * Profiles must be created beforehand. Unlike single browser sessions, pools load + * the profile read-only and never persist changes back to it, so save_changes is + * omitted here. Any save_changes value sent on a pool profile is silently ignored + * rather than rejected. */ export interface Profile { /** @@ -495,12 +502,11 @@ export interface BrowserPoolCreateParams { name?: string; /** - * Profile selection for browsers in a pool. Provide either id or name. The - * matching profile is loaded into every browser in the pool. Profiles must be - * created beforehand. Unlike single browser sessions, pools load the profile - * read-only and never persist changes back to it, so save_changes is omitted here. - * Any save_changes value sent on a pool profile is silently ignored rather than - * rejected, so callers reusing a single-session profile object will not error. + * Profile configuration for browsers in a pool. Provide either id or name. + * Profiles must be created beforehand. Unlike single browser sessions, pools load + * the profile read-only and never persist changes back to it, so save_changes is + * omitted here. Any save_changes value sent on a pool profile is silently ignored + * rather than rejected. */ profile?: BrowserPoolCreateParams.Profile; @@ -510,6 +516,13 @@ export interface BrowserPoolCreateParams { */ proxy_id?: string; + /** + * When true, flush idle browsers when the profile the pool uses is updated, so + * pool browsers pick up the latest profile data. Requires a profile to be set on + * the pool. + */ + refresh_on_profile_update?: boolean; + /** * Optional URL to navigate to when a new browser is warmed into the pool. * Best-effort: failures to navigate do not fail pool fill. Only applied to @@ -550,12 +563,11 @@ export interface BrowserPoolCreateParams { export namespace BrowserPoolCreateParams { /** - * Profile selection for browsers in a pool. Provide either id or name. The - * matching profile is loaded into every browser in the pool. Profiles must be - * created beforehand. Unlike single browser sessions, pools load the profile - * read-only and never persist changes back to it, so save_changes is omitted here. - * Any save_changes value sent on a pool profile is silently ignored rather than - * rejected, so callers reusing a single-session profile object will not error. + * Profile configuration for browsers in a pool. Provide either id or name. + * Profiles must be created beforehand. Unlike single browser sessions, pools load + * the profile read-only and never persist changes back to it, so save_changes is + * omitted here. Any save_changes value sent on a pool profile is silently ignored + * rather than rejected. */ export interface Profile { /** @@ -619,12 +631,11 @@ export interface BrowserPoolUpdateParams { name?: string; /** - * Profile selection for browsers in a pool. Provide either id or name. The - * matching profile is loaded into every browser in the pool. Profiles must be - * created beforehand. Unlike single browser sessions, pools load the profile - * read-only and never persist changes back to it, so save_changes is omitted here. - * Any save_changes value sent on a pool profile is silently ignored rather than - * rejected, so callers reusing a single-session profile object will not error. + * Profile configuration for browsers in a pool. Provide either id or name. + * Profiles must be created beforehand. Unlike single browser sessions, pools load + * the profile read-only and never persist changes back to it, so save_changes is + * omitted here. Any save_changes value sent on a pool profile is silently ignored + * rather than rejected. */ profile?: BrowserPoolUpdateParams.Profile; @@ -634,6 +645,13 @@ export interface BrowserPoolUpdateParams { */ proxy_id?: string; + /** + * When true, flush idle browsers when the profile the pool uses is updated, so + * pool browsers pick up the latest profile data. Requires a profile to be set on + * the pool. + */ + refresh_on_profile_update?: boolean; + /** * Number of browsers to maintain in the pool. The maximum size is determined by * your organization's pooled sessions limit (the sum of all pool sizes cannot @@ -681,12 +699,11 @@ export interface BrowserPoolUpdateParams { export namespace BrowserPoolUpdateParams { /** - * Profile selection for browsers in a pool. Provide either id or name. The - * matching profile is loaded into every browser in the pool. Profiles must be - * created beforehand. Unlike single browser sessions, pools load the profile - * read-only and never persist changes back to it, so save_changes is omitted here. - * Any save_changes value sent on a pool profile is silently ignored rather than - * rejected, so callers reusing a single-session profile object will not error. + * Profile configuration for browsers in a pool. Provide either id or name. + * Profiles must be created beforehand. Unlike single browser sessions, pools load + * the profile read-only and never persist changes back to it, so save_changes is + * omitted here. Any save_changes value sent on a pool profile is silently ignored + * rather than rejected. */ export interface Profile { /** diff --git a/tests/api-resources/browser-pools.test.ts b/tests/api-resources/browser-pools.test.ts index 37fda3c9..bb7370a6 100644 --- a/tests/api-resources/browser-pools.test.ts +++ b/tests/api-resources/browser-pools.test.ts @@ -32,6 +32,7 @@ describe('resource browserPools', () => { name: 'my-pool', profile: { id: 'id', name: 'name' }, proxy_id: 'proxy_id', + refresh_on_profile_update: true, start_url: 'https://example.com', stealth: true, timeout_seconds: 10, From 4c0ad064959a8af7397a4210a8dbc81b5a643106 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 8 Jul 2026 17:59:28 +0000 Subject: [PATCH 481/551] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index d888de6d..9c64d8cf 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 125 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-58ad412d62b3d94e3258c911d7028716d71191358ff769ce494c4b2d87027254.yml -openapi_spec_hash: 45d710b7d2a9beadff021514bb997ba1 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-4655211f0824a1eb5d534731697ea215c19e769e3c63ac61ca306c7a3140b0b4.yml +openapi_spec_hash: 0a440e663f1704d4b9a3a3ac5fa75ffb config_hash: 06186eb40e0058a2a87ac251fc07415d From 63600e65b4539af6066472ffc8e2d1d2523379cc Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 8 Jul 2026 19:54:55 +0000 Subject: [PATCH 482/551] feat: Store and return a sha256 checksum for uploaded extensions (reland) --- .stats.yml | 4 ++-- src/resources/extensions.ts | 27 +++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 9c64d8cf..1d73bab6 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 125 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-4655211f0824a1eb5d534731697ea215c19e769e3c63ac61ca306c7a3140b0b4.yml -openapi_spec_hash: 0a440e663f1704d4b9a3a3ac5fa75ffb +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-f040d3f5c26d6e0d312206b294d3745b272e26b883e7d704f6b4c45dd438cd01.yml +openapi_spec_hash: 56f4918d2e3f8d717ffe3643a20feb96 config_hash: 06186eb40e0058a2a87ac251fc07415d diff --git a/src/resources/extensions.ts b/src/resources/extensions.ts index 79e98e12..809c2a3e 100644 --- a/src/resources/extensions.ts +++ b/src/resources/extensions.ts @@ -147,6 +147,15 @@ export interface ExtensionListResponse { */ size_bytes: number; + /** + * SHA-256 checksum, encoded as lowercase hexadecimal, of the exact uploaded + * extension archive bytes. This is not a normalized checksum of the extension + * contents; archive metadata, file ordering, and compression can change the + * checksum for otherwise identical contents. Omitted for legacy rows and + * server-repackaged Chrome Web Store extensions. + */ + checksum?: string | null; + /** * Timestamp when the extension was last used */ @@ -178,6 +187,15 @@ export interface ExtensionGetResponse { */ size_bytes: number; + /** + * SHA-256 checksum, encoded as lowercase hexadecimal, of the exact uploaded + * extension archive bytes. This is not a normalized checksum of the extension + * contents; archive metadata, file ordering, and compression can change the + * checksum for otherwise identical contents. Omitted for legacy rows and + * server-repackaged Chrome Web Store extensions. + */ + checksum?: string | null; + /** * Timestamp when the extension was last used */ @@ -209,6 +227,15 @@ export interface ExtensionUploadResponse { */ size_bytes: number; + /** + * SHA-256 checksum, encoded as lowercase hexadecimal, of the exact uploaded + * extension archive bytes. This is not a normalized checksum of the extension + * contents; archive metadata, file ordering, and compression can change the + * checksum for otherwise identical contents. Omitted for legacy rows and + * server-repackaged Chrome Web Store extensions. + */ + checksum?: string | null; + /** * Timestamp when the extension was last used */ From e5b9a26032bb8a2115666bddaf37d418d68f5f67 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 8 Jul 2026 21:17:18 +0000 Subject: [PATCH 483/551] feat: Expose resolved profile_id and extension_ids on browser pool reads --- .stats.yml | 4 ++-- src/resources/browser-pools.ts | 16 ++++++++++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 1d73bab6..f8ffb2dd 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 125 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-f040d3f5c26d6e0d312206b294d3745b272e26b883e7d704f6b4c45dd438cd01.yml -openapi_spec_hash: 56f4918d2e3f8d717ffe3643a20feb96 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-f0486d0b8e34ddf8ba34e36ff97856cf973e0797e021ff621e04e4840970966e.yml +openapi_spec_hash: 12a71ce5ac80fc65f6a8779f0ca29223 config_hash: 06186eb40e0058a2a87ac251fc07415d diff --git a/src/resources/browser-pools.ts b/src/resources/browser-pools.ts index 39c9d8b8..a810bc8f 100644 --- a/src/resources/browser-pools.ts +++ b/src/resources/browser-pools.ts @@ -188,10 +188,26 @@ export interface BrowserPool { */ created_at: string; + /** + * Resolved extension IDs attached to the pool, in configured load order. Empty + * when no extensions are attached. Authoritative for programmatic consumers; the + * extensions inside `browser_pool_config` reflect the configured selector (echoed + * as sent on create). + */ + extension_ids: Array; + /** * Browser pool name, if set */ name?: string; + + /** + * Resolved profile ID the pool is attached to. Omitted when no profile is + * attached. Authoritative for programmatic consumers; the profile inside + * `browser_pool_config` reflects the configured selector (echoed as sent on + * create). + */ + profile_id?: string; } export namespace BrowserPool { From bac8e3894cf08e3f50f80c223da1c9978c13e8e1 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 9 Jul 2026 16:07:14 +0000 Subject: [PATCH 484/551] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index f8ffb2dd..639bc208 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 125 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-f0486d0b8e34ddf8ba34e36ff97856cf973e0797e021ff621e04e4840970966e.yml -openapi_spec_hash: 12a71ce5ac80fc65f6a8779f0ca29223 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-8af2d28c8540273b1b413f49b8f9bcaa5df25fa2332d187d2693ec01502a2ac2.yml +openapi_spec_hash: ee71b9231754b4682377a514d1a2c249 config_hash: 06186eb40e0058a2a87ac251fc07415d From fdb22e8d87dd3ef3c13a49dfd3afabd8fb091da9 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 9 Jul 2026 16:52:29 +0000 Subject: [PATCH 485/551] feat: Layer telemetry request config onto the default set --- .stats.yml | 4 +-- src/resources/browsers/browsers.ts | 50 ++++++++++++++++++++--------- src/resources/browsers/telemetry.ts | 16 ++++----- 3 files changed, 44 insertions(+), 26 deletions(-) diff --git a/.stats.yml b/.stats.yml index 639bc208..adc4cc21 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 125 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-8af2d28c8540273b1b413f49b8f9bcaa5df25fa2332d187d2693ec01502a2ac2.yml -openapi_spec_hash: ee71b9231754b4682377a514d1a2c249 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-61dab8d0d01c2838febaf4319114ae35aa169a813a102e93af6598ca0d445da2.yml +openapi_spec_hash: c9fbe809670384dc5141dccb60e45672 config_hash: 06186eb40e0058a2a87ac251fc07415d diff --git a/src/resources/browsers/browsers.ts b/src/resources/browsers/browsers.ts index c736b882..dbf7b191 100644 --- a/src/resources/browsers/browsers.ts +++ b/src/resources/browsers/browsers.ts @@ -1004,18 +1004,27 @@ export namespace BrowserCreateParams { */ export interface Telemetry { /** - * Per-category capture flags. Selection is opt-in: only the categories set to - * enabled=true are captured; anything omitted is off. If enabled is true and - * browser is omitted or empty, the default category set is used. A browser config - * that enables nothing stops capture on update and starts no capture on create. + * Per-category capture flags. The operational categories (control, connection, + * system, captcha) are captured whenever telemetry is enabled; set one to + * enabled=false to opt out. The CDP categories (console, network, page, + * interaction) and screenshot are off by default; set enabled=true to opt in. On + * create, provided categories layer onto the default set. On update, provided + * categories merge onto the session's current config; when no telemetry is active + * this falls back to the default set (matching create). If browser is omitted or + * empty, the default set is used. A browser config that disables every category + * stops capture on update and starts no capture on create. */ browser?: TelemetryAPI.BrowserTelemetryCategoriesConfig; /** - * Request shortcut for browser telemetry capture. True enables capture using the - * default category set unless browser category settings are provided. False stops - * capture on update and starts no capture on create. enabled=false cannot be - * combined with browser category settings. + * Request shortcut for browser telemetry capture. True enables capture; with no + * browser category settings it captures the default set (control, connection, + * system, captcha), and any browser category settings are layered onto that + * default set. On update, enabled=true resolves the config fresh from the default + * set plus any provided categories, replacing the session's current selection + * rather than merging onto it; omit enabled to merge categories onto the current + * selection instead. False stops capture on update and starts no capture on + * create. enabled=false cannot be combined with browser category settings. */ enabled?: boolean; } @@ -1086,18 +1095,27 @@ export namespace BrowserUpdateParams { */ export interface Telemetry { /** - * Per-category capture flags. Selection is opt-in: only the categories set to - * enabled=true are captured; anything omitted is off. If enabled is true and - * browser is omitted or empty, the default category set is used. A browser config - * that enables nothing stops capture on update and starts no capture on create. + * Per-category capture flags. The operational categories (control, connection, + * system, captcha) are captured whenever telemetry is enabled; set one to + * enabled=false to opt out. The CDP categories (console, network, page, + * interaction) and screenshot are off by default; set enabled=true to opt in. On + * create, provided categories layer onto the default set. On update, provided + * categories merge onto the session's current config; when no telemetry is active + * this falls back to the default set (matching create). If browser is omitted or + * empty, the default set is used. A browser config that disables every category + * stops capture on update and starts no capture on create. */ browser?: TelemetryAPI.BrowserTelemetryCategoriesConfig; /** - * Request shortcut for browser telemetry capture. True enables capture using the - * default category set unless browser category settings are provided. False stops - * capture on update and starts no capture on create. enabled=false cannot be - * combined with browser category settings. + * Request shortcut for browser telemetry capture. True enables capture; with no + * browser category settings it captures the default set (control, connection, + * system, captcha), and any browser category settings are layered onto that + * default set. On update, enabled=true resolves the config fresh from the default + * set plus any provided categories, replacing the session's current selection + * rather than merging onto it; omit enabled to merge categories onto the current + * selection instead. False stops capture on update and starts no capture on + * create. enabled=false cannot be combined with browser category settings. */ enabled?: boolean; } diff --git a/src/resources/browsers/telemetry.ts b/src/resources/browsers/telemetry.ts index dcc2894a..c11affc2 100644 --- a/src/resources/browsers/telemetry.ts +++ b/src/resources/browsers/telemetry.ts @@ -1879,12 +1879,11 @@ export namespace BrowserSystemOomKillEvent { } /** - * Per-category telemetry capture settings. Selection is opt-in: set a category to - * enabled=true to capture it; anything omitted is off. The default set (used by - * enabled=true with no per-category settings) is the lightweight operational - * signals: control, connection, system, captcha. The CDP categories (console, - * network, page, interaction) and screenshot are off by default and must be opted - * into. + * Per-category telemetry capture settings layered onto the default set. The + * operational signals (control, connection, system, captcha) are on by default and + * are opt-out: set one to enabled=false to stop capturing it. The CDP categories + * (console, network, page, interaction) and screenshot are off by default and are + * opt-in: set enabled=true to capture them. */ export interface BrowserTelemetryCategoriesConfig { /** @@ -1948,8 +1947,9 @@ export interface BrowserTelemetryCategoriesConfig { */ export interface BrowserTelemetryCategoryConfig { /** - * Whether this category is captured. Selection is opt-in, so an omitted category - * is not captured. + * Whether this category is captured. Operational categories (control, connection, + * system, captcha) default to true; set false to opt out. CDP categories (console, + * network, page, interaction) and screenshot default to false; set true to opt in. */ enabled?: boolean; } From cf45bf09200ec392bb3f2d627451fc8ef3fb464a Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 9 Jul 2026 18:32:39 +0000 Subject: [PATCH 486/551] feat: Return credential value keys and support removing values on update --- .stats.yml | 4 ++-- src/resources/credentials.ts | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index adc4cc21..3f7dec3b 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 125 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-61dab8d0d01c2838febaf4319114ae35aa169a813a102e93af6598ca0d445da2.yml -openapi_spec_hash: c9fbe809670384dc5141dccb60e45672 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-ba32039d3975da7aa6d28e5184f0a44c9fbfe36ab7dbc71985d14e2ecc0867b9.yml +openapi_spec_hash: a9f32fc90c2add2ae85af828c298e35b config_hash: 06186eb40e0058a2a87ac251fc07415d diff --git a/src/resources/credentials.ts b/src/resources/credentials.ts index 19842027..09aba3a2 100644 --- a/src/resources/credentials.ts +++ b/src/resources/credentials.ts @@ -202,6 +202,13 @@ export interface Credential { * When the totp_code expires. Only included when totp_code is present. */ totp_code_expires_at?: string; + + /** + * The field names stored in this credential's values (e.g., username, password). + * Values themselves are never returned. Included on single-credential responses + * (create, get by id or name, update); omitted from list responses. + */ + value_keys?: Array; } /** @@ -213,6 +220,12 @@ export interface UpdateCredentialRequest { */ name?: string; + /** + * Field names to remove from the credential's stored values. Removals are applied + * before `values` are merged, so a key present in both is kept with its new value. + */ + remove_value_keys?: Array; + /** * If set, indicates this credential should be used with the specified SSO * provider. Set to empty string or null to remove. @@ -281,6 +294,12 @@ export interface CredentialUpdateParams { */ name?: string; + /** + * Field names to remove from the credential's stored values. Removals are applied + * before `values` are merged, so a key present in both is kept with its new value. + */ + remove_value_keys?: Array; + /** * If set, indicates this credential should be used with the specified SSO * provider. Set to empty string or null to remove. From d056680989c20070a9091902c0b6c73c5c7ebfda Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 9 Jul 2026 18:51:14 +0000 Subject: [PATCH 487/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 52ffe5a9..5f3243d4 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.74.0" + ".": "0.76.0" } diff --git a/package.json b/package.json index cae70fdf..3fe8084d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.74.0", + "version": "0.76.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index c88d4bfa..2c80dbec 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.74.0'; // x-release-please-version +export const VERSION = '0.76.0'; // x-release-please-version From a207c93e197ccd66fd9779632b7fce2ad6c27db7 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 9 Jul 2026 23:07:50 +0000 Subject: [PATCH 488/551] docs(openapi): describe unified concurrency limit, deprecate max_pooled_sessions (CUS-275) --- .stats.yml | 4 ++-- src/resources/organization/limits.ts | 27 +++++++++++++------------ src/resources/projects/limits.ts | 30 +++++++++++++++++----------- 3 files changed, 34 insertions(+), 27 deletions(-) diff --git a/.stats.yml b/.stats.yml index 3f7dec3b..c7028199 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 125 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-ba32039d3975da7aa6d28e5184f0a44c9fbfe36ab7dbc71985d14e2ecc0867b9.yml -openapi_spec_hash: a9f32fc90c2add2ae85af828c298e35b +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-db45aab5b114bc0848eab997c85bfc02a653be9f929f8d090ec24187462733ee.yml +openapi_spec_hash: 82f4282312699f8d54bec207e981efe8 config_hash: 06186eb40e0058a2a87ac251fc07415d diff --git a/src/resources/organization/limits.ts b/src/resources/organization/limits.ts index 53f2f5c0..f0948cbd 100644 --- a/src/resources/organization/limits.ts +++ b/src/resources/organization/limits.ts @@ -9,8 +9,9 @@ import { RequestOptions } from '../../internal/request-options'; */ export class Limits extends APIResource { /** - * Get the organization's concurrent session ceiling and the default per-project - * concurrency cap applied to projects without an explicit override. + * Get the organization's concurrency limit — the maximum browsers running at once + * across on-demand sessions and browser pool reservations — and the default + * per-project concurrency cap applied to projects without an explicit override. */ retrieve(options?: RequestOptions): APIPromise { return this._client.get('/org/limits', options); @@ -19,8 +20,7 @@ export class Limits extends APIResource { /** * Set the default per-project concurrency cap applied to projects without an * explicit override. Set the value to 0 to remove the default; omit to leave it - * unchanged. The default cannot exceed the organization's concurrent session - * ceiling. + * unchanged. The default cannot exceed the organization's concurrency limit. */ update(body: LimitUpdateParams, options?: RequestOptions): APIPromise { return this._client.patch('/org/limits', { body, ...options }); @@ -29,7 +29,7 @@ export class Limits extends APIResource { export interface OrgLimits { /** - * Default maximum concurrent browser sessions applied to every project that has no + * Default maximum concurrent browsers applied to every project that has no * explicit per-project override. Null means no org-level default, so such projects * are uncapped (only the org-wide limit applies). Applies to existing and newly * created projects. @@ -37,8 +37,9 @@ export interface OrgLimits { default_project_max_concurrent_sessions?: number | null; /** - * The organization's effective concurrent browser session ceiling, from its plan - * or an override. Read-only and shared across all projects in the org; a + * The organization's effective concurrency limit — the maximum browsers running at + * once, covering both on-demand sessions and browser pool reservations — from its + * plan or an override. Read-only and shared across all projects in the org; a * per-project default cannot exceed it. */ max_concurrent_sessions?: number; @@ -46,18 +47,18 @@ export interface OrgLimits { export interface UpdateOrgLimitsRequest { /** - * Default maximum concurrent browser sessions for projects without an explicit - * override. Set to 0 to remove the default; omit to leave unchanged. Cannot exceed - * the organization's concurrent session ceiling. + * Default maximum concurrent browsers for projects without an explicit override. + * Set to 0 to remove the default; omit to leave unchanged. Cannot exceed the + * organization's concurrency limit. */ default_project_max_concurrent_sessions?: number | null; } export interface LimitUpdateParams { /** - * Default maximum concurrent browser sessions for projects without an explicit - * override. Set to 0 to remove the default; omit to leave unchanged. Cannot exceed - * the organization's concurrent session ceiling. + * Default maximum concurrent browsers for projects without an explicit override. + * Set to 0 to remove the default; omit to leave unchanged. Cannot exceed the + * organization's concurrency limit. */ default_project_max_concurrent_sessions?: number | null; } diff --git a/src/resources/projects/limits.ts b/src/resources/projects/limits.ts index 52ec16ac..d1a3e53c 100644 --- a/src/resources/projects/limits.ts +++ b/src/resources/projects/limits.ts @@ -49,14 +49,16 @@ export interface ProjectLimits { max_concurrent_invocations?: number | null; /** - * Maximum concurrent browser sessions for this project. Null means no - * project-level cap. + * Maximum concurrent browsers for this project, covering both on-demand sessions + * (`browsers.create()`) and browser pool reservations. Null means no project-level + * cap. */ max_concurrent_sessions?: number | null; /** - * Maximum pooled sessions capacity for this project. Null means no project-level - * cap. + * @deprecated Deprecated: pooled browsers now count toward + * `max_concurrent_sessions`. Always null once the unified concurrency limit is + * enabled for your organization. */ max_pooled_sessions?: number | null; } @@ -69,14 +71,16 @@ export interface UpdateProjectLimitsRequest { max_concurrent_invocations?: number | null; /** - * Maximum concurrent browser sessions for this project. Set to 0 to remove the - * cap; omit to leave unchanged. + * Maximum concurrent browsers for this project, covering both on-demand sessions + * and browser pool reservations. Set to 0 to remove the cap; omit to leave + * unchanged. */ max_concurrent_sessions?: number | null; /** - * Maximum pooled sessions capacity for this project. Set to 0 to remove the cap; - * omit to leave unchanged. + * @deprecated Deprecated: pooled browsers now count toward + * `max_concurrent_sessions`. Requests that set this field are rejected with a 400 + * once the unified concurrency limit is enabled for your organization. */ max_pooled_sessions?: number | null; } @@ -89,14 +93,16 @@ export interface LimitUpdateParams { max_concurrent_invocations?: number | null; /** - * Maximum concurrent browser sessions for this project. Set to 0 to remove the - * cap; omit to leave unchanged. + * Maximum concurrent browsers for this project, covering both on-demand sessions + * and browser pool reservations. Set to 0 to remove the cap; omit to leave + * unchanged. */ max_concurrent_sessions?: number | null; /** - * Maximum pooled sessions capacity for this project. Set to 0 to remove the cap; - * omit to leave unchanged. + * @deprecated Deprecated: pooled browsers now count toward + * `max_concurrent_sessions`. Requests that set this field are rejected with a 400 + * once the unified concurrency limit is enabled for your organization. */ max_pooled_sessions?: number | null; } From 8f9af89a16895afa9cfad45cb4ca0b4ddabd36cb Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 10 Jul 2026 13:46:00 +0000 Subject: [PATCH 489/551] feat: Add name-only rename for profiles and proxies --- .stats.yml | 8 +- api.md | 3 + src/client.ts | 7 +- src/resources/index.ts | 9 +- src/resources/profiles.ts | 78 +++++++++- src/resources/proxies.ts | 213 +++++++++++++++++++++++++++ tests/api-resources/profiles.test.ts | 17 +++ tests/api-resources/proxies.test.ts | 17 +++ 8 files changed, 344 insertions(+), 8 deletions(-) diff --git a/.stats.yml b/.stats.yml index c7028199..09109a9b 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 125 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-db45aab5b114bc0848eab997c85bfc02a653be9f929f8d090ec24187462733ee.yml -openapi_spec_hash: 82f4282312699f8d54bec207e981efe8 -config_hash: 06186eb40e0058a2a87ac251fc07415d +configured_endpoints: 127 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-bc33d13e669972493e9ab0da82a71999822dc049eb14b113f446753c917ffcdb.yml +openapi_spec_hash: 133a2e0d0cdc4023f98b3c2e589cf5d8 +config_hash: 77ee715aa17061166f9a02b264a21b8d diff --git a/api.md b/api.md index d729ebd3..f7950f3e 100644 --- a/api.md +++ b/api.md @@ -252,6 +252,7 @@ Methods: - client.profiles.create({ ...params }) -> Profile - client.profiles.retrieve(idOrName) -> Profile +- client.profiles.update(idOrName, { ...params }) -> Profile - client.profiles.list({ ...params }) -> ProfilesOffsetPagination - client.profiles.delete(idOrName) -> void - client.profiles.download(idOrName) -> Response @@ -289,6 +290,7 @@ Types: - ProxyCreateResponse - ProxyRetrieveResponse +- ProxyUpdateResponse - ProxyListResponse - ProxyCheckResponse @@ -296,6 +298,7 @@ Methods: - client.proxies.create({ ...params }) -> ProxyCreateResponse - client.proxies.retrieve(id) -> ProxyRetrieveResponse +- client.proxies.update(id, { ...params }) -> ProxyUpdateResponse - client.proxies.list({ ...params }) -> ProxyListResponsesOffsetPagination - client.proxies.delete(id) -> void - client.proxies.check(id, { ...params }) -> ProxyCheckResponse diff --git a/src/client.ts b/src/client.ts index e2f82fd8..b82d2d76 100644 --- a/src/client.ts +++ b/src/client.ts @@ -117,7 +117,7 @@ import { InvocationUpdateResponse, Invocations, } from './resources/invocations'; -import { ProfileCreateParams, ProfileListParams, Profiles } from './resources/profiles'; +import { ProfileCreateParams, ProfileListParams, ProfileUpdateParams, Profiles } from './resources/profiles'; import { Proxies, ProxyCheckParams, @@ -128,6 +128,8 @@ import { ProxyListResponse, ProxyListResponsesOffsetPagination, ProxyRetrieveResponse, + ProxyUpdateParams, + ProxyUpdateResponse, } from './resources/proxies'; import { Auth } from './resources/auth/auth'; import { @@ -1080,6 +1082,7 @@ export declare namespace Kernel { export { Profiles as Profiles, type ProfileCreateParams as ProfileCreateParams, + type ProfileUpdateParams as ProfileUpdateParams, type ProfileListParams as ProfileListParams, }; @@ -1089,10 +1092,12 @@ export declare namespace Kernel { Proxies as Proxies, type ProxyCreateResponse as ProxyCreateResponse, type ProxyRetrieveResponse as ProxyRetrieveResponse, + type ProxyUpdateResponse as ProxyUpdateResponse, type ProxyListResponse as ProxyListResponse, type ProxyCheckResponse as ProxyCheckResponse, type ProxyListResponsesOffsetPagination as ProxyListResponsesOffsetPagination, type ProxyCreateParams as ProxyCreateParams, + type ProxyUpdateParams as ProxyUpdateParams, type ProxyListParams as ProxyListParams, type ProxyCheckParams as ProxyCheckParams, }; diff --git a/src/resources/index.ts b/src/resources/index.ts index a7fdf353..797de87a 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -120,7 +120,12 @@ export { type InvocationListResponsesOffsetPagination, } from './invocations'; export { Organization } from './organization/organization'; -export { Profiles, type ProfileCreateParams, type ProfileListParams } from './profiles'; +export { + Profiles, + type ProfileCreateParams, + type ProfileUpdateParams, + type ProfileListParams, +} from './profiles'; export { Projects, type CreateProjectRequest, @@ -135,9 +140,11 @@ export { Proxies, type ProxyCreateResponse, type ProxyRetrieveResponse, + type ProxyUpdateResponse, type ProxyListResponse, type ProxyCheckResponse, type ProxyCreateParams, + type ProxyUpdateParams, type ProxyListParams, type ProxyCheckParams, type ProxyListResponsesOffsetPagination, diff --git a/src/resources/profiles.ts b/src/resources/profiles.ts index aa78a014..29708d84 100644 --- a/src/resources/profiles.ts +++ b/src/resources/profiles.ts @@ -16,6 +16,11 @@ export class Profiles extends APIResource { /** * Create a browser profile that can be used to load state into future browser * sessions. + * + * @example + * ```ts + * const profile = await client.profiles.create(); + * ``` */ create(body: ProfileCreateParams, options?: RequestOptions): APIPromise { return this._client.post('/profiles', { body, ...options }); @@ -23,13 +28,52 @@ export class Profiles extends APIResource { /** * Retrieve details for a single profile by its ID or name. + * + * @example + * ```ts + * const profile = await client.profiles.retrieve( + * 'id_or_name', + * ); + * ``` */ retrieve(idOrName: string, options?: RequestOptions): APIPromise { return this._client.get(path`/profiles/${idOrName}`, options); } + /** + * Update a profile's name. Names must be unique within the logical project; during + * the default-project migration, unscoped profiles and profiles in the org default + * project are treated as the same project. Duplicate-name conflicts are checked + * before update but are best-effort because there is no backing unique index. + * Renaming a profile while a browser session references it by name may prevent + * that session's changes from saving; prefer renaming when the profile is not in + * use. + * + * @example + * ```ts + * const profile = await client.profiles.update('id_or_name', { + * name: 'my-renamed-profile', + * }); + * ``` + */ + update( + idOrName: string, + body: ProfileUpdateParams, + options?: RequestOptions, + ): APIPromise { + return this._client.patch(path`/profiles/${idOrName}`, { body, ...options }); + } + /** * List profiles with optional filtering and pagination. + * + * @example + * ```ts + * // Automatically fetches more pages as needed. + * for await (const profile of client.profiles.list()) { + * // ... + * } + * ``` */ list( query: ProfileListParams | null | undefined = {}, @@ -40,6 +84,11 @@ export class Profiles extends APIResource { /** * Delete a profile by its ID or by its name. + * + * @example + * ```ts + * await client.profiles.delete('id_or_name'); + * ``` */ delete(idOrName: string, options?: RequestOptions): APIPromise { return this._client.delete(path`/profiles/${idOrName}`, { @@ -50,6 +99,16 @@ export class Profiles extends APIResource { /** * Returns a zstd-compressed tar file of the full user-data directory. + * + * @example + * ```ts + * const response = await client.profiles.download( + * 'id_or_name', + * ); + * + * const content = await response.blob(); + * console.log(content); + * ``` */ download(idOrName: string, options?: RequestOptions): APIPromise { return this._client.get(path`/profiles/${idOrName}/download`, { @@ -62,11 +121,22 @@ export class Profiles extends APIResource { export interface ProfileCreateParams { /** - * Optional name of the profile. Must be unique within the project. + * Optional name of the profile. Must be unique within the logical project; during + * the default-project migration, unscoped profiles and profiles in the org default + * project are treated as the same project. */ name?: string; } +export interface ProfileUpdateParams { + /** + * New profile name. Must be unique within the logical project; during the + * default-project migration, unscoped profiles and profiles in the org default + * project are treated as the same project. + */ + name: string; +} + export interface ProfileListParams extends OffsetPaginationParams { /** * Search profiles by name or ID. @@ -75,7 +145,11 @@ export interface ProfileListParams extends OffsetPaginationParams { } export declare namespace Profiles { - export { type ProfileCreateParams as ProfileCreateParams, type ProfileListParams as ProfileListParams }; + export { + type ProfileCreateParams as ProfileCreateParams, + type ProfileUpdateParams as ProfileUpdateParams, + type ProfileListParams as ProfileListParams, + }; } export { type ProfilesOffsetPagination }; diff --git a/src/resources/proxies.ts b/src/resources/proxies.ts index 3dda98f5..a9295fae 100644 --- a/src/resources/proxies.ts +++ b/src/resources/proxies.ts @@ -13,6 +13,13 @@ import { path } from '../internal/utils/path'; export class Proxies extends APIResource { /** * Create a new proxy configuration in the resolved project. + * + * @example + * ```ts + * const proxy = await client.proxies.create({ + * type: 'datacenter', + * }); + * ``` */ create(body: ProxyCreateParams, options?: RequestOptions): APIPromise { return this._client.post('/proxies', { body, ...options }); @@ -20,13 +27,43 @@ export class Proxies extends APIResource { /** * Retrieve a proxy in the resolved project by ID. + * + * @example + * ```ts + * const proxy = await client.proxies.retrieve('id'); + * ``` */ retrieve(id: string, options?: RequestOptions): APIPromise { return this._client.get(path`/proxies/${id}`, options); } + /** + * Update a proxy's name. Proxy names are not unique and are not ID-or-name + * addressable on this endpoint; duplicate names are allowed. Name-based + * session-create lookups can remain ambiguous until callers resolve proxies by ID + * or the API adds a stronger uniqueness contract. + * + * @example + * ```ts + * const proxy = await client.proxies.update('id', { + * name: 'my-renamed-proxy', + * }); + * ``` + */ + update(id: string, body: ProxyUpdateParams, options?: RequestOptions): APIPromise { + return this._client.patch(path`/proxies/${id}`, { body, ...options }); + } + /** * List proxies in the resolved project. + * + * @example + * ```ts + * // Automatically fetches more pages as needed. + * for await (const proxyListResponse of client.proxies.list()) { + * // ... + * } + * ``` */ list( query: ProxyListParams | null | undefined = {}, @@ -37,6 +74,11 @@ export class Proxies extends APIResource { /** * Soft delete a proxy. Sessions referencing it are not modified. + * + * @example + * ```ts + * await client.proxies.delete('id'); + * ``` */ delete(id: string, options?: RequestOptions): APIPromise { return this._client.delete(path`/proxies/${id}`, { @@ -52,6 +94,11 @@ export class Proxies extends APIResource { * exit IP. For residential and mobile proxies, the exit node varies between * requests, so this validates proxy configuration and connectivity rather than * guaranteeing site-specific reachability. + * + * @example + * ```ts + * const response = await client.proxies.check('id'); + * ``` */ check( id: string, @@ -376,6 +423,162 @@ export namespace ProxyRetrieveResponse { } } +/** + * Configuration for routing traffic through a proxy. + */ +export interface ProxyUpdateResponse { + /** + * Proxy type to use. In terms of quality for avoiding bot-detection, from best to + * worst: `mobile` > `residential` > `isp` > `datacenter`. + */ + type: 'datacenter' | 'isp' | 'residential' | 'mobile' | 'custom'; + + id?: string; + + /** + * Hostnames that should bypass the parent proxy and connect directly. + */ + bypass_hosts?: Array; + + /** + * Configuration specific to the selected proxy `type`. + */ + config?: + | ProxyUpdateResponse.DatacenterProxyConfig + | ProxyUpdateResponse.IspProxyConfig + | ProxyUpdateResponse.ResidentialProxyConfig + | ProxyUpdateResponse.MobileProxyConfig + | ProxyUpdateResponse.CustomProxyConfig; + + /** + * IP address that the proxy uses when making requests. + */ + ip_address?: string; + + /** + * Timestamp of the last health check performed on this proxy. + */ + last_checked?: string; + + /** + * Readable name of the proxy. + */ + name?: string; + + /** + * Protocol to use for the proxy connection. + */ + protocol?: 'http' | 'https'; + + /** + * Current health status of the proxy. + */ + status?: 'available' | 'unavailable'; +} + +export namespace ProxyUpdateResponse { + /** + * Configuration for a datacenter proxy. + */ + export interface DatacenterProxyConfig { + /** + * ISO 3166 country code. Defaults to US if not provided. + */ + country?: string; + } + + /** + * Configuration for an ISP proxy. + */ + export interface IspProxyConfig { + /** + * ISO 3166 country code. Defaults to US if not provided. + */ + country?: string; + } + + /** + * Configuration for residential proxies. + */ + export interface ResidentialProxyConfig { + /** + * Autonomous system number. See https://bgp.potaroo.net/cidr/autnums.html + */ + asn?: string; + + /** + * City name (no spaces, e.g. `sanfrancisco`). If provided, `country` must also be + * provided. + */ + city?: string; + + /** + * ISO 3166 country code. + */ + country?: string; + + /** + * @deprecated Operating system of the residential device. + */ + os?: 'windows' | 'macos' | 'android'; + + /** + * Two-letter state code. + */ + state?: string; + + /** + * US ZIP code. + */ + zip?: string; + } + + /** + * Configuration for mobile proxies. + */ + export interface MobileProxyConfig { + /** + * Provider city alias. Mobile carrier routing can make observed geo vary. + */ + city?: string; + + /** + * ISO 3166 country code + */ + country?: string; + + /** + * US-only state code. Mobile carrier routing can make observed geo vary. + */ + state?: string; + } + + /** + * Configuration for a custom proxy (e.g., private proxy server). + */ + export interface CustomProxyConfig { + /** + * Proxy host address or IP. + */ + host: string; + + /** + * Proxy port. + */ + port: number; + + /** + * Whether the proxy has a password. + */ + has_password?: boolean; + + /** + * Username for proxy authentication. + */ + username?: string; + } +} + /** * Configuration for routing traffic through a proxy. */ @@ -824,6 +1027,14 @@ export namespace ProxyCreateParams { } } +export interface ProxyUpdateParams { + /** + * New proxy name. Proxy names are trimmed and length-checked only; duplicates are + * allowed because proxies are updated by ID, not by name. + */ + name: string; +} + export interface ProxyListParams extends OffsetPaginationParams { /** * Search proxies by name, host, IP address, or ID. @@ -853,10 +1064,12 @@ export declare namespace Proxies { export { type ProxyCreateResponse as ProxyCreateResponse, type ProxyRetrieveResponse as ProxyRetrieveResponse, + type ProxyUpdateResponse as ProxyUpdateResponse, type ProxyListResponse as ProxyListResponse, type ProxyCheckResponse as ProxyCheckResponse, type ProxyListResponsesOffsetPagination as ProxyListResponsesOffsetPagination, type ProxyCreateParams as ProxyCreateParams, + type ProxyUpdateParams as ProxyUpdateParams, type ProxyListParams as ProxyListParams, type ProxyCheckParams as ProxyCheckParams, }; diff --git a/tests/api-resources/profiles.test.ts b/tests/api-resources/profiles.test.ts index 0bbb5574..2cfe7ecc 100644 --- a/tests/api-resources/profiles.test.ts +++ b/tests/api-resources/profiles.test.ts @@ -32,6 +32,23 @@ describe('resource profiles', () => { expect(dataAndResponse.response).toBe(rawResponse); }); + // Mock server tests are disabled + test.skip('update: only required params', async () => { + const responsePromise = client.profiles.update('id_or_name', { name: 'my-renamed-profile' }); + 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); + }); + + // Mock server tests are disabled + test.skip('update: required and optional params', async () => { + const response = await client.profiles.update('id_or_name', { name: 'my-renamed-profile' }); + }); + // Mock server tests are disabled test.skip('list', async () => { const responsePromise = client.profiles.list(); diff --git a/tests/api-resources/proxies.test.ts b/tests/api-resources/proxies.test.ts index e64b2747..00eff027 100644 --- a/tests/api-resources/proxies.test.ts +++ b/tests/api-resources/proxies.test.ts @@ -43,6 +43,23 @@ describe('resource proxies', () => { expect(dataAndResponse.response).toBe(rawResponse); }); + // Mock server tests are disabled + test.skip('update: only required params', async () => { + const responsePromise = client.proxies.update('id', { name: 'my-renamed-proxy' }); + 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); + }); + + // Mock server tests are disabled + test.skip('update: required and optional params', async () => { + const response = await client.proxies.update('id', { name: 'my-renamed-proxy' }); + }); + // Mock server tests are disabled test.skip('list', async () => { const responsePromise = client.proxies.list(); From 2ded1c6524ad35a18ac57fbe6fdaeb75d7d6709a Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 10 Jul 2026 14:19:19 +0000 Subject: [PATCH 490/551] feat: Document name uniqueness and query match semantics --- .stats.yml | 4 +-- src/resources/api-keys.ts | 5 ++-- src/resources/auth/connections.ts | 40 ++++++++++++++++++++------- src/resources/browser-pools.ts | 3 +- src/resources/credential-providers.ts | 3 +- src/resources/credentials.ts | 3 +- src/resources/extensions.ts | 3 +- src/resources/profiles.ts | 2 +- src/resources/proxies.ts | 3 +- 9 files changed, 46 insertions(+), 20 deletions(-) diff --git a/.stats.yml b/.stats.yml index 09109a9b..b058b75d 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 127 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-bc33d13e669972493e9ab0da82a71999822dc049eb14b113f446753c917ffcdb.yml -openapi_spec_hash: 133a2e0d0cdc4023f98b3c2e589cf5d8 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-6c7cbaefd8a84ec26a1677681f37041323290080dac3fd1a409bb7cd01dd2ae3.yml +openapi_spec_hash: 75085a25c8a5cdb5417f0dbfad0ed6b6 config_hash: 77ee715aa17061166f9a02b264a21b8d diff --git a/src/resources/api-keys.ts b/src/resources/api-keys.ts index a82e2c32..96b17f31 100644 --- a/src/resources/api-keys.ts +++ b/src/resources/api-keys.ts @@ -141,7 +141,8 @@ export interface APIKey { masked_key: string; /** - * API key name + * Label for the API key. API keys are not addressable by name; use the ID or key + * identifier for stable references. */ name: string; @@ -188,7 +189,7 @@ export interface CreatedAPIKey extends APIKey { export interface APIKeyCreateParams { /** - * API key name (1-255 characters) + * Label for the API key (1-255 characters). API keys are not addressable by name. */ name: string; diff --git a/src/resources/auth/connections.ts b/src/resources/auth/connections.ts index 67d067b7..9e5f8a49 100644 --- a/src/resources/auth/connections.ts +++ b/src/resources/auth/connections.ts @@ -729,7 +729,9 @@ export interface ManagedAuthCreateRequest { /** * Proxy selection. Provide either id or name. The proxy must be in the same - * project as the resource referencing it. + * project as the resource referencing it. When selecting by name, the name must + * match exactly one active proxy in the project. Ambiguous names return a 400; use + * id for stable references. */ proxy?: ManagedAuthCreateRequest.Proxy; @@ -778,7 +780,9 @@ export namespace ManagedAuthCreateRequest { /** * Proxy selection. Provide either id or name. The proxy must be in the same - * project as the resource referencing it. + * project as the resource referencing it. When selecting by name, the name must + * match exactly one active proxy in the project. Ambiguous names return a 400; use + * id for stable references. */ export interface Proxy { /** @@ -917,7 +921,9 @@ export interface ManagedAuthUpdateRequest { /** * Proxy selection. Provide either id or name. The proxy must be in the same - * project as the resource referencing it. + * project as the resource referencing it. When selecting by name, the name must + * match exactly one active proxy in the project. Ambiguous names return a 400; use + * id for stable references. */ proxy?: ManagedAuthUpdateRequest.Proxy; @@ -964,7 +970,9 @@ export namespace ManagedAuthUpdateRequest { /** * Proxy selection. Provide either id or name. The proxy must be in the same - * project as the resource referencing it. + * project as the resource referencing it. When selecting by name, the name must + * match exactly one active proxy in the project. Ambiguous names return a 400; use + * id for stable references. */ export interface Proxy { /** @@ -1320,7 +1328,9 @@ export interface ConnectionCreateParams { /** * Proxy selection. Provide either id or name. The proxy must be in the same - * project as the resource referencing it. + * project as the resource referencing it. When selecting by name, the name must + * match exactly one active proxy in the project. Ambiguous names return a 400; use + * id for stable references. */ proxy?: ConnectionCreateParams.Proxy; @@ -1369,7 +1379,9 @@ export namespace ConnectionCreateParams { /** * Proxy selection. Provide either id or name. The proxy must be in the same - * project as the resource referencing it. + * project as the resource referencing it. When selecting by name, the name must + * match exactly one active proxy in the project. Ambiguous names return a 400; use + * id for stable references. */ export interface Proxy { /** @@ -1430,7 +1442,9 @@ export interface ConnectionUpdateParams { /** * Proxy selection. Provide either id or name. The proxy must be in the same - * project as the resource referencing it. + * project as the resource referencing it. When selecting by name, the name must + * match exactly one active proxy in the project. Ambiguous names return a 400; use + * id for stable references. */ proxy?: ConnectionUpdateParams.Proxy; @@ -1477,7 +1491,9 @@ export namespace ConnectionUpdateParams { /** * Proxy selection. Provide either id or name. The proxy must be in the same - * project as the resource referencing it. + * project as the resource referencing it. When selecting by name, the name must + * match exactly one active proxy in the project. Ambiguous names return a 400; use + * id for stable references. */ export interface Proxy { /** @@ -1512,7 +1528,9 @@ export interface ConnectionListParams extends OffsetPaginationParams { export interface ConnectionLoginParams { /** * Proxy selection. Provide either id or name. The proxy must be in the same - * project as the resource referencing it. + * project as the resource referencing it. When selecting by name, the name must + * match exactly one active proxy in the project. Ambiguous names return a 400; use + * id for stable references. */ proxy?: ConnectionLoginParams.Proxy; @@ -1526,7 +1544,9 @@ export interface ConnectionLoginParams { export namespace ConnectionLoginParams { /** * Proxy selection. Provide either id or name. The proxy must be in the same - * project as the resource referencing it. + * project as the resource referencing it. When selecting by name, the name must + * match exactly one active proxy in the project. Ambiguous names return a 400; use + * id for stable references. */ export interface Proxy { /** diff --git a/src/resources/browser-pools.ts b/src/resources/browser-pools.ts index a810bc8f..0b0bc160 100644 --- a/src/resources/browser-pools.ts +++ b/src/resources/browser-pools.ts @@ -737,7 +737,8 @@ export namespace BrowserPoolUpdateParams { export interface BrowserPoolListParams extends OffsetPaginationParams { /** - * Search browser pools by name or ID. + * Case-insensitive substring match against browser pool name. IDs match by exact + * value. */ query?: string; } diff --git a/src/resources/credential-providers.ts b/src/resources/credential-providers.ts index 601cf269..d85d198e 100644 --- a/src/resources/credential-providers.ts +++ b/src/resources/credential-providers.ts @@ -346,7 +346,8 @@ export interface CredentialProviderUpdateParams { export interface CredentialProviderListParams extends OffsetPaginationParams { /** - * Search credential providers by name or ID. + * Case-insensitive substring match against credential provider name. IDs match by + * exact value. */ query?: string; } diff --git a/src/resources/credentials.ts b/src/resources/credentials.ts index 09aba3a2..da4992a1 100644 --- a/src/resources/credentials.ts +++ b/src/resources/credentials.ts @@ -326,7 +326,8 @@ export interface CredentialListParams extends OffsetPaginationParams { domain?: string; /** - * Search credentials by name, domain, or ID. + * Case-insensitive substring match against credential name or domain. IDs match by + * exact value. */ query?: string; } diff --git a/src/resources/extensions.ts b/src/resources/extensions.ts index 809c2a3e..e5d0dbd0 100644 --- a/src/resources/extensions.ts +++ b/src/resources/extensions.ts @@ -250,7 +250,8 @@ export interface ExtensionUploadResponse { export interface ExtensionListParams extends OffsetPaginationParams { /** - * Search extensions by name or ID. + * Case-insensitive substring match against extension name. IDs match by exact + * value. */ query?: string; } diff --git a/src/resources/profiles.ts b/src/resources/profiles.ts index 29708d84..8b50420c 100644 --- a/src/resources/profiles.ts +++ b/src/resources/profiles.ts @@ -139,7 +139,7 @@ export interface ProfileUpdateParams { export interface ProfileListParams extends OffsetPaginationParams { /** - * Search profiles by name or ID. + * Case-insensitive substring match against profile name or ID. */ query?: string; } diff --git a/src/resources/proxies.ts b/src/resources/proxies.ts index a9295fae..b3cbefbb 100644 --- a/src/resources/proxies.ts +++ b/src/resources/proxies.ts @@ -1037,7 +1037,8 @@ export interface ProxyUpdateParams { export interface ProxyListParams extends OffsetPaginationParams { /** - * Search proxies by name, host, IP address, or ID. + * Case-insensitive substring match against proxy name, host, or IP address. IDs + * match by exact value. */ query?: string; } From bd4228d5e74326c61c5ecb4d8129e4f8c0d852b0 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 10 Jul 2026 14:37:24 +0000 Subject: [PATCH 491/551] feat: Add exact-match name filter to list endpoints --- .stats.yml | 4 ++-- src/resources/api-keys.ts | 8 ++++++++ src/resources/browser-pools.ts | 8 ++++++++ src/resources/extensions.ts | 8 ++++++++ src/resources/profiles.ts | 8 ++++++++ src/resources/projects/projects.ts | 6 ++++++ src/resources/proxies.ts | 7 +++++++ tests/api-resources/api-keys.test.ts | 1 + tests/api-resources/browser-pools.test.ts | 1 + tests/api-resources/extensions.test.ts | 1 + tests/api-resources/profiles.test.ts | 1 + tests/api-resources/projects/projects.test.ts | 1 + tests/api-resources/proxies.test.ts | 1 + 13 files changed, 53 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index b058b75d..f7ef7fe6 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 127 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-6c7cbaefd8a84ec26a1677681f37041323290080dac3fd1a409bb7cd01dd2ae3.yml -openapi_spec_hash: 75085a25c8a5cdb5417f0dbfad0ed6b6 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-b20fcf2fc1cdb91b51ffd354adcd12d63b950ea98b69e13bee6a78a58498c2cd.yml +openapi_spec_hash: bc8b527a963dd2c2d74b6f9e6ca56652 config_hash: 77ee715aa17061166f9a02b264a21b8d diff --git a/src/resources/api-keys.ts b/src/resources/api-keys.ts index 96b17f31..7901f3cc 100644 --- a/src/resources/api-keys.ts +++ b/src/resources/api-keys.ts @@ -226,6 +226,14 @@ export interface APIKeyListParams extends OffsetPaginationParams { */ include_deleted?: boolean; + /** + * Exact-match filter on API key name using the database collation. In production, + * matching is case- and accent-insensitive. Names are not required to be unique, + * so multiple keys may match. When status=all or include_deleted=true is set, + * soft-deleted keys with the same name may also match. + */ + name?: string; + /** * Case-insensitive substring match against API key name, creator, and project. API * key identifiers and masked keys match by exact value or prefix. diff --git a/src/resources/browser-pools.ts b/src/resources/browser-pools.ts index 0b0bc160..e84ce49d 100644 --- a/src/resources/browser-pools.ts +++ b/src/resources/browser-pools.ts @@ -736,6 +736,14 @@ export namespace BrowserPoolUpdateParams { } export interface BrowserPoolListParams extends OffsetPaginationParams { + /** + * Exact-match filter on browser pool name using the database collation. In + * production, matching is case- and accent-insensitive. During the default-project + * migration, unscoped requests prefer a concrete default-project browser pool over + * a legacy unscoped browser pool with the same name. + */ + name?: string; + /** * Case-insensitive substring match against browser pool name. IDs match by exact * value. diff --git a/src/resources/extensions.ts b/src/resources/extensions.ts index e5d0dbd0..0d306ce1 100644 --- a/src/resources/extensions.ts +++ b/src/resources/extensions.ts @@ -249,6 +249,14 @@ export interface ExtensionUploadResponse { } export interface ExtensionListParams extends OffsetPaginationParams { + /** + * Exact-match filter on extension name using the database collation. In + * production, matching is case- and accent-insensitive. During the default-project + * migration, unscoped requests prefer a concrete default-project extension over a + * legacy unscoped extension with the same name. + */ + name?: string; + /** * Case-insensitive substring match against extension name. IDs match by exact * value. diff --git a/src/resources/profiles.ts b/src/resources/profiles.ts index 8b50420c..52546235 100644 --- a/src/resources/profiles.ts +++ b/src/resources/profiles.ts @@ -138,6 +138,14 @@ export interface ProfileUpdateParams { } export interface ProfileListParams extends OffsetPaginationParams { + /** + * Exact-match filter on profile name using the database collation. In production, + * matching is case- and accent-insensitive. During the default-project migration, + * unscoped requests prefer a concrete default-project profile over a legacy + * unscoped profile with the same name. + */ + name?: string; + /** * Case-insensitive substring match against profile name or ID. */ diff --git a/src/resources/projects/projects.ts b/src/resources/projects/projects.ts index e20a1c2e..9fbc1f49 100644 --- a/src/resources/projects/projects.ts +++ b/src/resources/projects/projects.ts @@ -155,6 +155,12 @@ export interface ProjectUpdateParams { } export interface ProjectListParams extends OffsetPaginationParams { + /** + * Exact-match filter on project name using the database collation. In production, + * matching is case- and accent-insensitive. + */ + name?: string; + /** * Case-insensitive substring match against project name */ diff --git a/src/resources/proxies.ts b/src/resources/proxies.ts index b3cbefbb..28c592cc 100644 --- a/src/resources/proxies.ts +++ b/src/resources/proxies.ts @@ -1036,6 +1036,13 @@ export interface ProxyUpdateParams { } export interface ProxyListParams extends OffsetPaginationParams { + /** + * Exact-match filter on proxy name using the database collation. In production, + * matching is case- and accent-insensitive. Names are not required to be unique, + * so multiple proxies may match. + */ + name?: string; + /** * Case-insensitive substring match against proxy name, host, or IP address. IDs * match by exact value. diff --git a/tests/api-resources/api-keys.test.ts b/tests/api-resources/api-keys.test.ts index b179ccfb..6456eace 100644 --- a/tests/api-resources/api-keys.test.ts +++ b/tests/api-resources/api-keys.test.ts @@ -86,6 +86,7 @@ describe('resource apiKeys', () => { { include_deleted: true, limit: 100, + name: 'name', offset: 0, query: 'query', sort_by: 'created_at', diff --git a/tests/api-resources/browser-pools.test.ts b/tests/api-resources/browser-pools.test.ts index bb7370a6..e061f651 100644 --- a/tests/api-resources/browser-pools.test.ts +++ b/tests/api-resources/browser-pools.test.ts @@ -87,6 +87,7 @@ describe('resource browserPools', () => { client.browserPools.list( { limit: 1, + name: 'name', offset: 0, query: 'query', }, diff --git a/tests/api-resources/extensions.test.ts b/tests/api-resources/extensions.test.ts index 8d196d93..ecdcdc2e 100644 --- a/tests/api-resources/extensions.test.ts +++ b/tests/api-resources/extensions.test.ts @@ -27,6 +27,7 @@ describe('resource extensions', () => { client.extensions.list( { limit: 1, + name: 'name', offset: 0, query: 'query', }, diff --git a/tests/api-resources/profiles.test.ts b/tests/api-resources/profiles.test.ts index 2cfe7ecc..13ff21e4 100644 --- a/tests/api-resources/profiles.test.ts +++ b/tests/api-resources/profiles.test.ts @@ -68,6 +68,7 @@ describe('resource profiles', () => { client.profiles.list( { limit: 1, + name: 'name', offset: 0, query: 'query', }, diff --git a/tests/api-resources/projects/projects.test.ts b/tests/api-resources/projects/projects.test.ts index 229d6581..f4be4431 100644 --- a/tests/api-resources/projects/projects.test.ts +++ b/tests/api-resources/projects/projects.test.ts @@ -68,6 +68,7 @@ describe('resource projects', () => { client.projects.list( { limit: 100, + name: 'name', offset: 0, query: 'query', }, diff --git a/tests/api-resources/proxies.test.ts b/tests/api-resources/proxies.test.ts index 00eff027..800ba2c0 100644 --- a/tests/api-resources/proxies.test.ts +++ b/tests/api-resources/proxies.test.ts @@ -79,6 +79,7 @@ describe('resource proxies', () => { client.proxies.list( { limit: 1, + name: 'name', offset: 0, query: 'query', }, From 8f61405b84ef00e19b3ba4d7ff4a9fb601d179d2 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 10 Jul 2026 14:56:12 +0000 Subject: [PATCH 492/551] feat: Make the browser pool OpenAPI contract truthful --- .stats.yml | 4 +- src/resources/browser-pools.ts | 80 +++++++++++++++++----------------- 2 files changed, 42 insertions(+), 42 deletions(-) diff --git a/.stats.yml b/.stats.yml index f7ef7fe6..c403f2c1 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 127 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-b20fcf2fc1cdb91b51ffd354adcd12d63b950ea98b69e13bee6a78a58498c2cd.yml -openapi_spec_hash: bc8b527a963dd2c2d74b6f9e6ca56652 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-d7ab1ecb886cb7f86e7ce0926207db423a6650e8e12e7283a71f8682fbb472ae.yml +openapi_spec_hash: 9323b0ba38d2d50b8506be4d7401c04d config_hash: 77ee715aa17061166f9a02b264a21b8d diff --git a/src/resources/browser-pools.ts b/src/resources/browser-pools.ts index e84ce49d..2617a58a 100644 --- a/src/resources/browser-pools.ts +++ b/src/resources/browser-pools.ts @@ -216,7 +216,7 @@ export namespace BrowserPool { */ export interface BrowserPoolConfig { /** - * Number of browsers to maintain in the pool. The maximum size is determined by + * Number of browsers maintained in the pool. The maximum size is determined by * your organization's pooled sessions limit (the sum of all pool sizes cannot * exceed your limit). */ @@ -226,7 +226,8 @@ export namespace BrowserPool { * Custom Chrome enterprise policy overrides applied to all browsers in this pool. * Keys are Chrome enterprise policy names; values must match their expected types. * Blocked: kernel-managed policies (extensions, proxy, CDP/automation). See - * https://chromeenterprise.google/policies/ + * https://chromeenterprise.google/policies/ The serialized JSON payload is capped + * at 5 MiB. */ chrome_policy?: { [key: string]: unknown }; @@ -236,14 +237,13 @@ export namespace BrowserPool { extensions?: Array; /** - * Percentage of the pool to fill per minute. Defaults to 10. The cap is 25 for - * most organizations but can be raised per-organization, so only the lower bound - * is enforced here. + * Percentage of the pool to fill per minute. The cap is 25 for most organizations + * but can be raised per-organization, so only the lower bound is enforced here. */ fill_rate_per_minute?: number; /** - * If true, launches the browser using a headless image. Defaults to false. + * If true, launches the browser using a headless image. */ headless?: boolean; @@ -268,8 +268,8 @@ export namespace BrowserPool { profile?: BrowserPoolConfig.Profile; /** - * Optional proxy to associate to the browser session. Must reference a proxy in - * the same project as the browser session. + * Optional proxy associated to the browser session. References a proxy in the same + * project as the browser session. */ proxy_id?: string; @@ -297,7 +297,7 @@ export namespace BrowserPool { /** * Default idle timeout in seconds for browsers acquired from this pool before they - * are destroyed. Defaults to 600 seconds. Minimum 10, maximum 259200 (72 hours). + * are destroyed. Minimum 10, maximum 259200 (72 hours). */ timeout_seconds?: number; @@ -485,7 +485,8 @@ export interface BrowserPoolCreateParams { * Custom Chrome enterprise policy overrides applied to all browsers in this pool. * Keys are Chrome enterprise policy names; values must match their expected types. * Blocked: kernel-managed policies (extensions, proxy, CDP/automation). See - * https://chromeenterprise.google/policies/ + * https://chromeenterprise.google/policies/ The serialized JSON payload is capped + * at 5 MiB. */ chrome_policy?: { [key: string]: unknown }; @@ -508,7 +509,7 @@ export interface BrowserPoolCreateParams { /** * If true, launches the browser in kiosk mode to hide address bar and tabs in live - * view. + * view. Defaults to false. */ kiosk_mode?: boolean; @@ -550,7 +551,7 @@ export interface BrowserPoolCreateParams { /** * If true, launches the browser in stealth mode to reduce detection by anti-bot - * mechanisms. + * mechanisms. Defaults to false. */ stealth?: boolean; @@ -601,10 +602,12 @@ export namespace BrowserPoolCreateParams { export interface BrowserPoolUpdateParams { /** - * Custom Chrome enterprise policy overrides applied to all browsers in this pool. - * Keys are Chrome enterprise policy names; values must match their expected types. + * If provided, replaces the custom Chrome enterprise policy overrides applied to + * all browsers in this pool. Empty object clears any previously-set policy. Keys + * are Chrome enterprise policy names; values must match their expected types. * Blocked: kernel-managed policies (extensions, proxy, CDP/automation). See - * https://chromeenterprise.google/policies/ + * https://chromeenterprise.google/policies/ The serialized JSON payload is capped + * at 5 MiB. */ chrome_policy?: { [key: string]: unknown }; @@ -619,30 +622,31 @@ export interface BrowserPoolUpdateParams { discard_all_idle?: boolean; /** - * List of browser extensions to load into the session. Provide each by id or name. + * If provided, replaces the extension list. Empty array clears all + * previously-selected extensions. Omit this field to leave extensions unchanged. */ extensions?: Array; /** - * Percentage of the pool to fill per minute. Defaults to 10. The cap is 25 for - * most organizations but can be raised per-organization, so only the lower bound - * is enforced here. + * If provided, replaces the percentage of the pool to fill per minute. The cap is + * 25 for most organizations but can be raised per-organization, so only the lower + * bound is enforced here. */ fill_rate_per_minute?: number; /** - * If true, launches the browser using a headless image. Defaults to false. + * If provided, replaces whether browsers launch using a headless image. */ headless?: boolean; /** - * If true, launches the browser in kiosk mode to hide address bar and tabs in live - * view. + * If provided, replaces whether browsers launch in kiosk mode. */ kiosk_mode?: boolean; /** - * Optional name for the browser pool. Must be unique within the project. + * If provided, replaces the pool name. Empty string is a no-op; the pool name + * cannot be cleared or reset to empty once assigned. */ name?: string; @@ -656,43 +660,39 @@ export interface BrowserPoolUpdateParams { profile?: BrowserPoolUpdateParams.Profile; /** - * Optional proxy to associate to the browser session. Must reference a proxy in - * the same project as the browser session. + * Empty string clears the previously-selected proxy. Omit this field to leave the + * proxy unchanged. */ proxy_id?: string; /** - * When true, flush idle browsers when the profile the pool uses is updated, so - * pool browsers pick up the latest profile data. Requires a profile to be set on - * the pool. + * If provided, replaces whether idle browsers are flushed when the profile the + * pool uses is updated. Requires a profile to be set on the pool. */ refresh_on_profile_update?: boolean; /** - * Number of browsers to maintain in the pool. The maximum size is determined by - * your organization's pooled sessions limit (the sum of all pool sizes cannot - * exceed your limit). + * If provided, replaces the number of browsers to maintain in the pool. The + * maximum size is determined by your organization's pooled sessions limit (the sum + * of all pool sizes cannot exceed your limit). */ size?: number; /** - * Optional URL to navigate to when a new browser is warmed into the pool. - * Best-effort: failures to navigate do not fail pool fill. Only applied to - * newly-warmed browsers; browsers reused via release/acquire keep whatever URL the - * previous lease left them on. Accepts any URL Chromium can resolve, including - * chrome:// pages. + * If provided, replaces the URL to navigate to when a new browser is warmed into + * the pool. Empty string clears the previously-set URL. Omit this field to leave + * it unchanged. */ start_url?: string; /** - * If true, launches the browser in stealth mode to reduce detection by anti-bot - * mechanisms. + * If provided, replaces whether browsers launch in stealth mode. */ stealth?: boolean; /** - * Default idle timeout in seconds for browsers acquired from this pool before they - * are destroyed. Defaults to 600 seconds. Minimum 10, maximum 259200 (72 hours). + * If provided, replaces the default idle timeout in seconds for browsers acquired + * from this pool before they are destroyed. Minimum 10, maximum 259200 (72 hours). */ timeout_seconds?: number; From 62cbc5a53a009e63549afd41017c0308eefd8241 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 10 Jul 2026 15:32:45 +0000 Subject: [PATCH 493/551] feat: Persist and echo deployment source identity --- .stats.yml | 4 +- src/resources/deployments.ts | 132 +++++++++++++++++++++++++++++++++++ 2 files changed, 134 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index c403f2c1..f6f61824 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 127 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-d7ab1ecb886cb7f86e7ce0926207db423a6650e8e12e7283a71f8682fbb472ae.yml -openapi_spec_hash: 9323b0ba38d2d50b8506be4d7401c04d +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-d61b5e5ca18ce30a6b4d05483bcd67969ce0f4aee2e9e8c379be4f22f1362b01.yml +openapi_spec_hash: 23121d1c1552e41177b472c4c39d154e config_hash: 77ee715aa17061166f9a02b264a21b8d diff --git a/src/resources/deployments.ts b/src/resources/deployments.ts index 597dad21..8e3c7622 100644 --- a/src/resources/deployments.ts +++ b/src/resources/deployments.ts @@ -165,6 +165,39 @@ export namespace DeploymentStateEvent { */ env_vars?: { [key: string]: string }; + /** + * Hex-encoded SHA-256 checksum of the source archive. For file uploads, this + * hashes the uploaded archive; for GitHub-sourced deployments, this hashes the + * GitHub archive downloaded by the API. Omitted for deployments created before + * this field was recorded. + */ + source_checksum?: string; + + /** + * For GitHub-sourced deployments, the subpath within the repository that was used + * as the deploy root. Omitted when the repo root was used or for file uploads. + */ + source_path?: string; + + /** + * For GitHub-sourced deployments, the git ref as requested at deploy time (branch, + * tag, or commit SHA — not resolved to a commit). Omitted for file uploads. + */ + source_ref?: string; + + /** + * Origin of the deployed source code. This is read-only response provenance; + * `file` indicates an uploaded archive and `github` indicates a repository fetched + * by the API. + */ + source_type?: 'file' | 'github'; + + /** + * For GitHub-sourced deployments, the repository URL that was fetched. Omitted for + * file uploads. + */ + source_url?: string; + /** * Status reason */ @@ -213,6 +246,39 @@ export interface DeploymentCreateResponse { */ env_vars?: { [key: string]: string }; + /** + * Hex-encoded SHA-256 checksum of the source archive. For file uploads, this + * hashes the uploaded archive; for GitHub-sourced deployments, this hashes the + * GitHub archive downloaded by the API. Omitted for deployments created before + * this field was recorded. + */ + source_checksum?: string; + + /** + * For GitHub-sourced deployments, the subpath within the repository that was used + * as the deploy root. Omitted when the repo root was used or for file uploads. + */ + source_path?: string; + + /** + * For GitHub-sourced deployments, the git ref as requested at deploy time (branch, + * tag, or commit SHA — not resolved to a commit). Omitted for file uploads. + */ + source_ref?: string; + + /** + * Origin of the deployed source code. This is read-only response provenance; + * `file` indicates an uploaded archive and `github` indicates a repository fetched + * by the API. + */ + source_type?: 'file' | 'github'; + + /** + * For GitHub-sourced deployments, the repository URL that was fetched. Omitted for + * file uploads. + */ + source_url?: string; + /** * Status reason */ @@ -260,6 +326,39 @@ export interface DeploymentRetrieveResponse { */ env_vars?: { [key: string]: string }; + /** + * Hex-encoded SHA-256 checksum of the source archive. For file uploads, this + * hashes the uploaded archive; for GitHub-sourced deployments, this hashes the + * GitHub archive downloaded by the API. Omitted for deployments created before + * this field was recorded. + */ + source_checksum?: string; + + /** + * For GitHub-sourced deployments, the subpath within the repository that was used + * as the deploy root. Omitted when the repo root was used or for file uploads. + */ + source_path?: string; + + /** + * For GitHub-sourced deployments, the git ref as requested at deploy time (branch, + * tag, or commit SHA — not resolved to a commit). Omitted for file uploads. + */ + source_ref?: string; + + /** + * Origin of the deployed source code. This is read-only response provenance; + * `file` indicates an uploaded archive and `github` indicates a repository fetched + * by the API. + */ + source_type?: 'file' | 'github'; + + /** + * For GitHub-sourced deployments, the repository URL that was fetched. Omitted for + * file uploads. + */ + source_url?: string; + /** * Status reason */ @@ -307,6 +406,39 @@ export interface DeploymentListResponse { */ env_vars?: { [key: string]: string }; + /** + * Hex-encoded SHA-256 checksum of the source archive. For file uploads, this + * hashes the uploaded archive; for GitHub-sourced deployments, this hashes the + * GitHub archive downloaded by the API. Omitted for deployments created before + * this field was recorded. + */ + source_checksum?: string; + + /** + * For GitHub-sourced deployments, the subpath within the repository that was used + * as the deploy root. Omitted when the repo root was used or for file uploads. + */ + source_path?: string; + + /** + * For GitHub-sourced deployments, the git ref as requested at deploy time (branch, + * tag, or commit SHA — not resolved to a commit). Omitted for file uploads. + */ + source_ref?: string; + + /** + * Origin of the deployed source code. This is read-only response provenance; + * `file` indicates an uploaded archive and `github` indicates a repository fetched + * by the API. + */ + source_type?: 'file' | 'github'; + + /** + * For GitHub-sourced deployments, the repository URL that was fetched. Omitted for + * file uploads. + */ + source_url?: string; + /** * Status reason */ From df06f9ff7e59fc0474281ad641f513c1c696b39a Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 10 Jul 2026 15:59:42 +0000 Subject: [PATCH 494/551] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index f6f61824..38aa69be 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 127 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-d61b5e5ca18ce30a6b4d05483bcd67969ce0f4aee2e9e8c379be4f22f1362b01.yml -openapi_spec_hash: 23121d1c1552e41177b472c4c39d154e +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-9143bc729ef60beffa0bbd9b601bb095083e41e23c8994553e69302f586882f5.yml +openapi_spec_hash: bd04c530cfa8188af0e63a784129645d config_hash: 77ee715aa17061166f9a02b264a21b8d From 26681604e4bd085ea1c9594d9d980f7a45eff265 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 10 Jul 2026 19:29:07 +0000 Subject: [PATCH 495/551] feat: Auto-default refresh_on_profile_update when browser pool profile changes --- .stats.yml | 4 ++-- src/resources/browser-pools.ts | 13 ++++++++----- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/.stats.yml b/.stats.yml index 38aa69be..5882e06c 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 127 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-9143bc729ef60beffa0bbd9b601bb095083e41e23c8994553e69302f586882f5.yml -openapi_spec_hash: bd04c530cfa8188af0e63a784129645d +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-25b48b79d356843aeda41e5e5c3c407c5bd5c12f9548500ffc0a6696e6acd941.yml +openapi_spec_hash: f710169690ab7aca30c91968e752cff7 config_hash: 77ee715aa17061166f9a02b264a21b8d diff --git a/src/resources/browser-pools.ts b/src/resources/browser-pools.ts index 2617a58a..086e30cf 100644 --- a/src/resources/browser-pools.ts +++ b/src/resources/browser-pools.ts @@ -275,8 +275,8 @@ export namespace BrowserPool { /** * When true, flush idle browsers when the profile the pool uses is updated, so - * pool browsers pick up the latest profile data. Requires a profile to be set on - * the pool. + * pool browsers pick up the latest profile data. When a profile is provided during + * creation, this defaults to true. Requires a profile to be set on the pool. */ refresh_on_profile_update?: boolean; @@ -535,8 +535,8 @@ export interface BrowserPoolCreateParams { /** * When true, flush idle browsers when the profile the pool uses is updated, so - * pool browsers pick up the latest profile data. Requires a profile to be set on - * the pool. + * pool browsers pick up the latest profile data. When a profile is provided during + * creation, this defaults to true. Requires a profile to be set on the pool. */ refresh_on_profile_update?: boolean; @@ -667,7 +667,10 @@ export interface BrowserPoolUpdateParams { /** * If provided, replaces whether idle browsers are flushed when the profile the - * pool uses is updated. Requires a profile to be set on the pool. + * pool uses is updated. When the pool's profile reference is changed (including + * newly attached) and this field is omitted, it defaults to true. Re-sending the + * same profile reference leaves this setting unchanged. Clearing the profile also + * disables this setting. Requires a profile to be set on the pool. */ refresh_on_profile_update?: boolean; From c1c672081d395bb29d769e809959a88420eb6f2f Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 11 Jul 2026 02:12:56 +0000 Subject: [PATCH 496/551] fix(ci): bump @arethetypeswrong/cli to ^0.18.0 and run CI workflows on Node 24 --- .github/workflows/ci.yml | 6 ++-- .github/workflows/publish-npm.yml | 2 +- package.json | 2 +- yarn.lock | 51 +++++++++++++++++++------------ 4 files changed, 37 insertions(+), 24 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d920d7bf..3125f0fd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,7 +26,7 @@ jobs: - name: Set up Node uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: - node-version: '20' + node-version: '24' - name: Bootstrap run: ./scripts/bootstrap @@ -48,7 +48,7 @@ jobs: - name: Set up Node uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: - node-version: '20' + node-version: '24' - name: Bootstrap run: ./scripts/bootstrap @@ -85,7 +85,7 @@ jobs: - name: Set up Node uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: - node-version: '20' + node-version: '24' - name: Bootstrap run: ./scripts/bootstrap diff --git a/.github/workflows/publish-npm.yml b/.github/workflows/publish-npm.yml index 664e42c3..d01da10b 100644 --- a/.github/workflows/publish-npm.yml +++ b/.github/workflows/publish-npm.yml @@ -22,7 +22,7 @@ jobs: - name: Set up Node uses: actions/setup-node@3235b876344d2a9aa001b8d1453c930bba69e610 # v3.9.1 with: - node-version: '20' + node-version: '24' - name: Install dependencies run: | diff --git a/package.json b/package.json index 3fe8084d..2e8d5e7e 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ }, "dependencies": {}, "devDependencies": { - "@arethetypeswrong/cli": "^0.17.0", + "@arethetypeswrong/cli": "^0.18.0", "@swc/core": "^1.3.102", "@swc/jest": "^0.2.29", "@types/jest": "^29.4.0", diff --git a/yarn.lock b/yarn.lock index 38236e67..443cc054 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12,12 +12,12 @@ resolved "https://registry.yarnpkg.com/@andrewbranch/untar.js/-/untar.js-1.0.3.tgz#ba9494f85eb83017c5c855763969caf1d0adea00" integrity sha512-Jh15/qVmrLGhkKJBdXlK1+9tY4lZruYjsgkDFj08ZmDiWVBLJcqkok7Z0/R0In+i1rScBpJlSvrTS2Lm41Pbnw== -"@arethetypeswrong/cli@^0.17.0": - version "0.17.0" - resolved "https://registry.yarnpkg.com/@arethetypeswrong/cli/-/cli-0.17.0.tgz#f97f10926b3f9f9eb5117550242d2e06c25cadac" - integrity sha512-xSMW7bfzVWpYw5JFgZqBXqr6PdR0/REmn3DkxCES5N0JTcB0CVgbIynJCvKBFmXaPc3hzmmTrb7+yPDRoOSZdA== +"@arethetypeswrong/cli@^0.18.0": + version "0.18.4" + resolved "https://registry.yarnpkg.com/@arethetypeswrong/cli/-/cli-0.18.4.tgz#c31f54f3b0d0e0f3256ab3edb6530beeb5e64b4b" + integrity sha512-kNWo6LTzGAuLYPpJ7Sgo63whSUeeSuKMlYx6IBgzs4ONEG807gW4hSSENvpeCHzO2H2wIzG5EFl0OKBbqGBAyA== dependencies: - "@arethetypeswrong/core" "0.17.0" + "@arethetypeswrong/core" "0.18.4" chalk "^4.1.2" cli-table3 "^0.6.3" commander "^10.0.1" @@ -25,15 +25,16 @@ marked-terminal "^7.1.0" semver "^7.5.4" -"@arethetypeswrong/core@0.17.0": - version "0.17.0" - resolved "https://registry.yarnpkg.com/@arethetypeswrong/core/-/core-0.17.0.tgz#abb3b5f425056d37193644c2a2de4aecf866b76b" - integrity sha512-FHyhFizXNetigTVsIhqXKGYLpazPS5YNojEPpZEUcBPt9wVvoEbNIvG+hybuBR+pjlRcbyuqhukHZm1fr+bDgA== +"@arethetypeswrong/core@0.18.4": + version "0.18.4" + resolved "https://registry.yarnpkg.com/@arethetypeswrong/core/-/core-0.18.4.tgz#24edea3d651dea7d32bf6f1cc9ee9a00db39de49" + integrity sha512-M5F0ePyN6h2Z6XxRiyIPqjGbltotXLjR0CKA0uKspsDu0QmgTNYvRb4RSQPMUs2ZXZHCCYpbaZbFbYOXLxCjUA== dependencies: "@andrewbranch/untar.js" "^1.0.3" + "@loaderkit/resolve" "^1.0.2" cjs-module-lexer "^1.2.3" - fflate "^0.8.2" - lru-cache "^10.4.3" + fflate "^0.8.3" + lru-cache "^11.0.1" semver "^7.5.4" typescript "5.6.1-rc" validate-npm-package-name "^5.0.0" @@ -306,6 +307,11 @@ resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== +"@braidai/lang@^1.0.0": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@braidai/lang/-/lang-1.1.2.tgz#65bc2bc1db6d00e153b95ac7006f4573e289e9be" + integrity sha512-qBcknbBufNHlui137Hft8xauQMTZDKdophmLFv05r2eNmdIv/MlPuP4TdUknHG68UdWLgVZwgxVe735HzJNIwA== + "@colors/colors@1.5.0": version "1.5.0" resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9" @@ -688,6 +694,13 @@ "@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" +"@loaderkit/resolve@^1.0.2": + version "1.0.6" + resolved "https://registry.yarnpkg.com/@loaderkit/resolve/-/resolve-1.0.6.tgz#8d45341e688faecc25b3ae919c0f45d94c4e26c9" + integrity sha512-G8FdIoF5CypfwmD9rl8BXod5HDn8JqB0CCNBXDTaRZ+yRYhARrrSToX1zg1zy9jX3zLqigsELwhT4gNtkdQAUg== + dependencies: + "@braidai/lang" "^1.0.0" + "@nodelib/fs.scandir@2.1.5": version "2.1.5" resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" @@ -1696,10 +1709,10 @@ fb-watchman@^2.0.0: dependencies: bser "2.1.1" -fflate@^0.8.2: - version "0.8.2" - resolved "https://registry.yarnpkg.com/fflate/-/fflate-0.8.2.tgz#fc8631f5347812ad6028bbe4a2308b2792aa1dea" - integrity sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A== +fflate@^0.8.3: + version "0.8.3" + resolved "https://registry.yarnpkg.com/fflate/-/fflate-0.8.3.tgz#bc27d8eb30343d4d512abb03480202ce65d825fc" + integrity sha512-tbZNuJrLwGUp3zshBtdy4W+ORxZuIh8a5ilyIEQDC5rY1f3U20JMry0Ll3WBzU58EZKsEuJFXhb5gwv8CsPvgA== file-entry-cache@^8.0.0: version "8.0.0" @@ -2490,10 +2503,10 @@ lodash.merge@^4.6.2: resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== -lru-cache@^10.4.3: - version "10.4.3" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.4.3.tgz#410fc8a17b70e598013df257c2446b7f3383f119" - integrity sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ== +lru-cache@^11.0.1: + version "11.5.2" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-11.5.2.tgz#00e16665c90c620fba14a3c368732a976493f760" + integrity sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g== lru-cache@^5.1.1: version "5.1.1" From a0d1b490b1287d9c58a55dc96d2de1fe88783bf8 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 13 Jul 2026 15:43:48 +0000 Subject: [PATCH 497/551] feat: Support multiple audit log method exclusions --- .stats.yml | 4 ++-- src/resources/audit-logs.ts | 4 ++-- tests/api-resources/audit-logs.test.ts | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.stats.yml b/.stats.yml index 5882e06c..a855b9ce 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 127 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-25b48b79d356843aeda41e5e5c3c407c5bd5c12f9548500ffc0a6696e6acd941.yml -openapi_spec_hash: f710169690ab7aca30c91968e752cff7 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-f0003e336fc8dc54d9cac4728c847fb80c32d50a9165738c5b70aa83a09bb0f5.yml +openapi_spec_hash: a2099eec27728b1cfd9032dc71b9bb57 config_hash: 77ee715aa17061166f9a02b264a21b8d diff --git a/src/resources/audit-logs.ts b/src/resources/audit-logs.ts index 85df4103..9367dc9a 100644 --- a/src/resources/audit-logs.ts +++ b/src/resources/audit-logs.ts @@ -119,7 +119,7 @@ export interface AuditLogListParams extends PageTokenPaginationParams { /** * Filter out results by HTTP method. */ - exclude_method?: string; + exclude_method?: Array; /** * Filter by HTTP method. @@ -166,7 +166,7 @@ export interface AuditLogExportChunkParams { /** * Filter out results by HTTP method. */ - exclude_method?: string; + exclude_method?: Array; /** * Encoding for the returned chunk. diff --git a/tests/api-resources/audit-logs.test.ts b/tests/api-resources/audit-logs.test.ts index b1773ceb..ebce088d 100644 --- a/tests/api-resources/audit-logs.test.ts +++ b/tests/api-resources/audit-logs.test.ts @@ -29,7 +29,7 @@ describe('resource auditLogs', () => { end: '2026-01-02T00:00:00Z', start: '2026-01-01T00:00:00Z', auth_strategy: 'auth_strategy', - exclude_method: 'exclude_method', + exclude_method: ['string'], limit: 1, method: 'method', page_token: 'page_token', @@ -46,7 +46,7 @@ describe('resource auditLogs', () => { start: '2026-01-01T00:00:00Z', auth_strategy: 'auth_strategy', cursor: 'cursor', - exclude_method: 'exclude_method', + exclude_method: ['string'], format: 'jsonl', limit: 1, method: 'method', From 94d4c3c7a4e50a4da0a91acbf8ea71617d47cf18 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 13 Jul 2026 16:13:47 +0000 Subject: [PATCH 498/551] feat: Expose telemetry exception message in API/SDK --- .stats.yml | 4 ++-- src/resources/browsers/telemetry.ts | 5 ++++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/.stats.yml b/.stats.yml index a855b9ce..04d533eb 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 127 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-f0003e336fc8dc54d9cac4728c847fb80c32d50a9165738c5b70aa83a09bb0f5.yml -openapi_spec_hash: a2099eec27728b1cfd9032dc71b9bb57 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-1413d61d06059008b4c1e204c783d8b2e7dca9af23f6e3b6d2552493ea2d9853.yml +openapi_spec_hash: 80aca500caddd300cb03a6daf568fddb config_hash: 77ee715aa17061166f9a02b264a21b8d diff --git a/src/resources/browsers/telemetry.ts b/src/resources/browsers/telemetry.ts index c11affc2..7b41c677 100644 --- a/src/resources/browsers/telemetry.ts +++ b/src/resources/browsers/telemetry.ts @@ -371,7 +371,10 @@ export namespace BrowserConsoleErrorEvent { */ export interface Data extends TelemetryAPI.BrowserEventContext { /** - * Error message text. Present in both source paths. + * Human-readable error text, as the browser console would display it. For + * console.error() calls, the first argument coerced to a string. For uncaught + * exceptions, the prefix and error message, e.g. "Uncaught Error: boom" or + * "Uncaught (in promise) TypeError: x is not a function". */ text: string; From 3f2e37d454ca6f526cf64410f05bdfb6f145ec88 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 13 Jul 2026 18:34:12 +0000 Subject: [PATCH 499/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 5f3243d4..2fc68753 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.76.0" + ".": "0.78.0" } diff --git a/package.json b/package.json index 2e8d5e7e..741d5d09 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.76.0", + "version": "0.78.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 2c80dbec..3d604761 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.76.0'; // x-release-please-version +export const VERSION = '0.78.0'; // x-release-please-version From 9518070a34ee5070c3bafbc1d860514fa912eb7b Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 15 Jul 2026 15:26:47 +0000 Subject: [PATCH 500/551] feat: Default dashboard browser pools to 25% fill rate --- .stats.yml | 4 ++-- src/resources/browser-pools.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.stats.yml b/.stats.yml index 04d533eb..7f088e43 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 127 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-1413d61d06059008b4c1e204c783d8b2e7dca9af23f6e3b6d2552493ea2d9853.yml -openapi_spec_hash: 80aca500caddd300cb03a6daf568fddb +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-92c776855f978ae03a778fbbac49bf1edc65852530644772c382838b6eab9fe5.yml +openapi_spec_hash: 4a9fbcb607be408ad646e207fe90687f config_hash: 77ee715aa17061166f9a02b264a21b8d diff --git a/src/resources/browser-pools.ts b/src/resources/browser-pools.ts index 086e30cf..67b5c726 100644 --- a/src/resources/browser-pools.ts +++ b/src/resources/browser-pools.ts @@ -496,7 +496,7 @@ export interface BrowserPoolCreateParams { extensions?: Array; /** - * Percentage of the pool to fill per minute. Defaults to 10. The cap is 25 for + * Percentage of the pool to fill per minute. Defaults to 25. The cap is 25 for * most organizations but can be raised per-organization, so only the lower bound * is enforced here. */ From e0d30be7e11ecb8555fa5b856c067d57b81cb196 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 15 Jul 2026 15:39:48 +0000 Subject: [PATCH 501/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 2fc68753..fc55571e 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.78.0" + ".": "0.78.1" } diff --git a/package.json b/package.json index 741d5d09..8f3f2e79 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.78.0", + "version": "0.78.1", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 3d604761..bb9ec875 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.78.0'; // x-release-please-version +export const VERSION = '0.78.1'; // x-release-please-version From d2b888e88eba40cb0ae7573dedd831a1264ff081 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 15 Jul 2026 20:54:39 +0000 Subject: [PATCH 502/551] feat: Add telemetry support for browser pools with BAA enforcement --- .stats.yml | 4 +- src/resources/browser-pools.ts | 149 ++++++++++++++++++++++ tests/api-resources/browser-pools.test.ts | 14 ++ 3 files changed, 165 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 7f088e43..3807b2f3 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 127 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-92c776855f978ae03a778fbbac49bf1edc65852530644772c382838b6eab9fe5.yml -openapi_spec_hash: 4a9fbcb607be408ad646e207fe90687f +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-e04362b2c82b88f4f7fb43209c764fa9fdf37fe98932e142547be43a1e99c50b.yml +openapi_spec_hash: b16e79bfd6cac36090c815a8184b9e09 config_hash: 77ee715aa17061166f9a02b264a21b8d diff --git a/src/resources/browser-pools.ts b/src/resources/browser-pools.ts index 67b5c726..4b2d9c40 100644 --- a/src/resources/browser-pools.ts +++ b/src/resources/browser-pools.ts @@ -295,6 +295,12 @@ export namespace BrowserPool { */ stealth?: boolean; + /** + * Active telemetry configuration applied to browsers warmed into this pool, if + * any. + */ + telemetry?: TelemetryAPI.BrowserTelemetryConfig | null; + /** * Default idle timeout in seconds for browsers acquired from this pool before they * are destroyed. Minimum 10, maximum 259200 (72 hours). @@ -555,6 +561,16 @@ export interface BrowserPoolCreateParams { */ stealth?: boolean; + /** + * Telemetry configuration applied to browsers warmed into this pool. Set enabled + * to true to start capture using the default set, or provide browser category + * settings. If omitted, null, set to an empty object ({}), set to enabled: false + * without browser category settings, or all four CDP categories are explicitly + * disabled, no telemetry is configured on the pool. Only applied to newly-warmed + * browsers. + */ + telemetry?: BrowserPoolCreateParams.Telemetry | null; + /** * Default idle timeout in seconds for browsers acquired from this pool before they * are destroyed. Defaults to 600 seconds. Minimum 10, maximum 259200 (72 hours). @@ -598,6 +614,41 @@ export namespace BrowserPoolCreateParams { */ name?: string; } + + /** + * Telemetry configuration applied to browsers warmed into this pool. Set enabled + * to true to start capture using the default set, or provide browser category + * settings. If omitted, null, set to an empty object ({}), set to enabled: false + * without browser category settings, or all four CDP categories are explicitly + * disabled, no telemetry is configured on the pool. Only applied to newly-warmed + * browsers. + */ + export interface Telemetry { + /** + * Per-category capture flags. The operational categories (control, connection, + * system, captcha) are captured whenever telemetry is enabled; set one to + * enabled=false to opt out. The CDP categories (console, network, page, + * interaction) and screenshot are off by default; set enabled=true to opt in. On + * create, provided categories layer onto the default set. On update, provided + * categories merge onto the session's current config; when no telemetry is active + * this falls back to the default set (matching create). If browser is omitted or + * empty, the default set is used. A browser config that disables every category + * stops capture on update and starts no capture on create. + */ + browser?: TelemetryAPI.BrowserTelemetryCategoriesConfig; + + /** + * Request shortcut for browser telemetry capture. True enables capture; with no + * browser category settings it captures the default set (control, connection, + * system, captcha), and any browser category settings are layered onto that + * default set. On update, enabled=true resolves the config fresh from the default + * set plus any provided categories, replacing the session's current selection + * rather than merging onto it; omit enabled to merge categories onto the current + * selection instead. False stops capture on update and starts no capture on + * create. enabled=false cannot be combined with browser category settings. + */ + enabled?: boolean; + } } export interface BrowserPoolUpdateParams { @@ -693,6 +744,17 @@ export interface BrowserPoolUpdateParams { */ stealth?: boolean; + /** + * If provided, updates the pool's telemetry configuration. Omit, set to null, or + * set to an empty object ({}) to leave the existing configuration unchanged. Set + * enabled to true to enable capture using the default set. Set enabled to false to + * clear the pool's telemetry. Provide browser category settings for per-category + * updates, merged onto the pool's current configuration. Only applied to browsers + * warmed after the update; browsers already in the pool keep their configuration + * until discarded. + */ + telemetry?: BrowserPoolUpdateParams.Telemetry | null; + /** * If provided, replaces the default idle timeout in seconds for browsers acquired * from this pool before they are destroyed. Minimum 10, maximum 259200 (72 hours). @@ -736,6 +798,42 @@ export namespace BrowserPoolUpdateParams { */ name?: string; } + + /** + * If provided, updates the pool's telemetry configuration. Omit, set to null, or + * set to an empty object ({}) to leave the existing configuration unchanged. Set + * enabled to true to enable capture using the default set. Set enabled to false to + * clear the pool's telemetry. Provide browser category settings for per-category + * updates, merged onto the pool's current configuration. Only applied to browsers + * warmed after the update; browsers already in the pool keep their configuration + * until discarded. + */ + export interface Telemetry { + /** + * Per-category capture flags. The operational categories (control, connection, + * system, captcha) are captured whenever telemetry is enabled; set one to + * enabled=false to opt out. The CDP categories (console, network, page, + * interaction) and screenshot are off by default; set enabled=true to opt in. On + * create, provided categories layer onto the default set. On update, provided + * categories merge onto the session's current config; when no telemetry is active + * this falls back to the default set (matching create). If browser is omitted or + * empty, the default set is used. A browser config that disables every category + * stops capture on update and starts no capture on create. + */ + browser?: TelemetryAPI.BrowserTelemetryCategoriesConfig; + + /** + * Request shortcut for browser telemetry capture. True enables capture; with no + * browser category settings it captures the default set (control, connection, + * system, captcha), and any browser category settings are layered onto that + * default set. On update, enabled=true resolves the config fresh from the default + * set plus any provided categories, replacing the session's current selection + * rather than merging onto it; omit enabled to merge categories onto the current + * selection instead. False stops capture on update and starts no capture on + * create. enabled=false cannot be combined with browser category settings. + */ + enabled?: boolean; + } } export interface BrowserPoolListParams extends OffsetPaginationParams { @@ -791,6 +889,57 @@ export interface BrowserPoolAcquireParams { * the browser is released back to the pool. Up to 50 pairs. */ tags?: BrowsersAPI.Tags; + + /** + * Telemetry override for the acquired browser, applied to this lease only. Merges + * onto the browser's current (pool-inherited) telemetry using the same + * per-category semantics as PATCH /browsers: provided categories override the + * current configuration, omitted categories are inherited. Set enabled to true to + * resolve the config fresh from the default set, or enabled to false to stop + * capture. When the browser is released back to the pool with reuse, its telemetry + * is reset to the pool's baseline, so the override does not carry over to the next + * lease. + */ + telemetry?: BrowserPoolAcquireParams.Telemetry | null; +} + +export namespace BrowserPoolAcquireParams { + /** + * Telemetry override for the acquired browser, applied to this lease only. Merges + * onto the browser's current (pool-inherited) telemetry using the same + * per-category semantics as PATCH /browsers: provided categories override the + * current configuration, omitted categories are inherited. Set enabled to true to + * resolve the config fresh from the default set, or enabled to false to stop + * capture. When the browser is released back to the pool with reuse, its telemetry + * is reset to the pool's baseline, so the override does not carry over to the next + * lease. + */ + export interface Telemetry { + /** + * Per-category capture flags. The operational categories (control, connection, + * system, captcha) are captured whenever telemetry is enabled; set one to + * enabled=false to opt out. The CDP categories (console, network, page, + * interaction) and screenshot are off by default; set enabled=true to opt in. On + * create, provided categories layer onto the default set. On update, provided + * categories merge onto the session's current config; when no telemetry is active + * this falls back to the default set (matching create). If browser is omitted or + * empty, the default set is used. A browser config that disables every category + * stops capture on update and starts no capture on create. + */ + browser?: TelemetryAPI.BrowserTelemetryCategoriesConfig; + + /** + * Request shortcut for browser telemetry capture. True enables capture; with no + * browser category settings it captures the default set (control, connection, + * system, captcha), and any browser category settings are layered onto that + * default set. On update, enabled=true resolves the config fresh from the default + * set plus any provided categories, replacing the session's current selection + * rather than merging onto it; omit enabled to merge categories onto the current + * selection instead. False stops capture on update and starts no capture on + * create. enabled=false cannot be combined with browser category settings. + */ + enabled?: boolean; + } } export interface BrowserPoolReleaseParams { diff --git a/tests/api-resources/browser-pools.test.ts b/tests/api-resources/browser-pools.test.ts index e061f651..362a190c 100644 --- a/tests/api-resources/browser-pools.test.ts +++ b/tests/api-resources/browser-pools.test.ts @@ -35,6 +35,20 @@ describe('resource browserPools', () => { refresh_on_profile_update: true, start_url: 'https://example.com', stealth: true, + telemetry: { + browser: { + captcha: { enabled: true }, + connection: { enabled: true }, + console: { enabled: true }, + control: { enabled: true }, + interaction: { enabled: true }, + network: { enabled: true }, + page: { enabled: true }, + screenshot: { enabled: true }, + system: { enabled: true }, + }, + enabled: true, + }, timeout_seconds: 10, viewport: { height: 800, From 468bf1c4c03ff34a2f4edb44a344c27530a8a6e3 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 16 Jul 2026 04:49:23 +0000 Subject: [PATCH 503/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index fc55571e..954743f6 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.78.1" + ".": "0.79.0" } diff --git a/package.json b/package.json index 8f3f2e79..bc9c2c39 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.78.1", + "version": "0.79.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index bb9ec875..68f919f7 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.78.1'; // x-release-please-version +export const VERSION = '0.79.0'; // x-release-please-version From 2556e04236c01df1c93c4c73640678ec8bcdf456 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 16 Jul 2026 19:15:33 +0000 Subject: [PATCH 504/551] feat: Add example to ProxyCheckRequest.url so API reference sample shows it --- .stats.yml | 4 ++-- tests/api-resources/proxies.test.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.stats.yml b/.stats.yml index 3807b2f3..ef859acd 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 127 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-e04362b2c82b88f4f7fb43209c764fa9fdf37fe98932e142547be43a1e99c50b.yml -openapi_spec_hash: b16e79bfd6cac36090c815a8184b9e09 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-0c99f133dc7e81a8e74e829299f4a7bfdd9f4fadc40e69a9a10c81ab28318f7a.yml +openapi_spec_hash: 6e7e04300dc9554b2d1cf4284ee46504 config_hash: 77ee715aa17061166f9a02b264a21b8d diff --git a/tests/api-resources/proxies.test.ts b/tests/api-resources/proxies.test.ts index 800ba2c0..ddac608e 100644 --- a/tests/api-resources/proxies.test.ts +++ b/tests/api-resources/proxies.test.ts @@ -116,7 +116,7 @@ describe('resource proxies', () => { test.skip('check: 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.proxies.check('id', { url: 'url' }, { path: '/_stainless_unknown_path' }), + client.proxies.check('id', { url: 'https://example.com' }, { path: '/_stainless_unknown_path' }), ).rejects.toThrow(Kernel.NotFoundError); }); }); From d11bf4936d8cd7ef5739cb39e05c4ef17332851a Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 17 Jul 2026 00:05:19 +0000 Subject: [PATCH 505/551] feat(managed-auth): add TS CUA worker contract (KERNEL-1456) --- .stats.yml | 4 +- src/resources/auth/connections.ts | 194 +++++++++++++++++++++++++++++- 2 files changed, 194 insertions(+), 4 deletions(-) diff --git a/.stats.yml b/.stats.yml index ef859acd..9e326663 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 127 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-0c99f133dc7e81a8e74e829299f4a7bfdd9f4fadc40e69a9a10c81ab28318f7a.yml -openapi_spec_hash: 6e7e04300dc9554b2d1cf4284ee46504 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-5b9eb5cdadbc7a5f404f5c2cec40f726e5fece54bf8e2dd29ab5c7700eb44f0e.yml +openapi_spec_hash: 63dd0798a4c0ed6477af50fff397f5dc config_hash: 77ee715aa17061166f9a02b264a21b8d diff --git a/src/resources/auth/connections.ts b/src/resources/auth/connections.ts index 9e5f8a49..b9567179 100644 --- a/src/resources/auth/connections.ts +++ b/src/resources/auth/connections.ts @@ -352,6 +352,12 @@ export interface ManagedAuth { | 'requires_sms_code' | 'requires_email_code'; + /** + * Canonical choices awaiting selection. Prefer this over pending_sso_buttons, + * mfa_options, and sign_in_options when present. + */ + choices?: Array | null; + /** * Reference to credentials for the auth connection. Use one of: * @@ -383,6 +389,12 @@ export interface ManagedAuth { */ external_action_message?: string | null; + /** + * Canonical fields awaiting input. Prefer this over discovered_fields when + * present. + */ + fields?: Array | null; + /** * When the current flow expires (null when no flow in progress). A flow past this * timestamp is no longer valid and its `flow_status` will be `EXPIRED`. Clients @@ -503,6 +515,43 @@ export interface ManagedAuth { } export namespace ManagedAuth { + /** + * Canonical auth-flow choice awaiting user selection. + */ + export interface Choice { + /** + * Stable choice identifier for canonical submit. + */ + id: string; + + /** + * Human-readable choice label. + */ + label: string; + + /** + * Choice type. + */ + type: + | 'mfa_method' + | 'sso_provider' + | 'sign_in_method' + | 'auth_method' + | 'identifier_method' + | 'account' + | 'other'; + + /** + * Additional context for the choice. + */ + description?: string | null; + + /** + * Selector for the visible choice, when available. + */ + observed_selector?: string | null; + } + /** * Reference to credentials for the auth connection. Use one of: * @@ -579,6 +628,41 @@ export namespace ManagedAuth { required?: boolean; } + /** + * Canonical field awaiting user input. + */ + export interface Field { + /** + * Stable field identifier for canonical submit. + */ + id: string; + + /** + * Credential reference name to store the submitted value under. + */ + ref: string; + + /** + * Managed-auth field type. + */ + type: 'identifier' | 'password' | 'code' | 'totp_code' | 'totp_secret' | 'text'; + + /** + * Human-readable label shown to the user. + */ + label?: string; + + /** + * Selector for the visible field, when available. + */ + observed_selector?: string | null; + + /** + * Whether this field is required. + */ + required?: boolean; + } + /** * An MFA method option for verification */ @@ -989,10 +1073,17 @@ export namespace ManagedAuthUpdateRequest { /** * Request to submit field values, click an SSO button, select an MFA method, or - * select a sign-in option. Provide exactly one of fields, sso_button_selector, - * sso_provider, mfa_option_id, or sign_in_option_id. + * select a sign-in option. Prefer canonical selected_choice_id/field_values when + * the API returns fields/choices; legacy + * fields/sso_button_selector/sso_provider/mfa_option_id/sign_in_option_id remain + * supported during deprecation. */ export interface SubmitFieldsRequest { + /** + * Canonical map of field ID to submitted value. + */ + field_values?: { [key: string]: string }; + /** * Map of field name to value */ @@ -1003,6 +1094,11 @@ export interface SubmitFieldsRequest { */ mfa_option_id?: string; + /** + * Canonical choice ID selected by the user. + */ + selected_choice_id?: string; + /** * The sign-in option ID to select (when sign_in_options were returned) */ @@ -1064,6 +1160,12 @@ export namespace ConnectionFollowResponse { */ timestamp: string; + /** + * Canonical choices awaiting selection. Prefer this over pending_sso_buttons, + * mfa_options, and sign_in_options when present. + */ + choices?: Array; + /** * Fields awaiting input (present when flow_step=AWAITING_INPUT; may also be * present with AWAITING_EXTERNAL_ACTION as fallback actions). @@ -1086,6 +1188,12 @@ export namespace ConnectionFollowResponse { */ external_action_message?: string; + /** + * Canonical fields awaiting input. Prefer this over discovered_fields when + * present. + */ + fields?: Array; + /** * Type of the current flow. */ @@ -1133,6 +1241,43 @@ export namespace ConnectionFollowResponse { } export namespace ManagedAuthStateEvent { + /** + * Canonical auth-flow choice awaiting user selection. + */ + export interface Choice { + /** + * Stable choice identifier for canonical submit. + */ + id: string; + + /** + * Human-readable choice label. + */ + label: string; + + /** + * Choice type. + */ + type: + | 'mfa_method' + | 'sso_provider' + | 'sign_in_method' + | 'auth_method' + | 'identifier_method' + | 'account' + | 'other'; + + /** + * Additional context for the choice. + */ + description?: string | null; + + /** + * Selector for the visible choice, when available. + */ + observed_selector?: string | null; + } + /** * A discovered form field */ @@ -1180,6 +1325,41 @@ export namespace ConnectionFollowResponse { required?: boolean; } + /** + * Canonical field awaiting user input. + */ + export interface Field { + /** + * Stable field identifier for canonical submit. + */ + id: string; + + /** + * Credential reference name to store the submitted value under. + */ + ref: string; + + /** + * Managed-auth field type. + */ + type: 'identifier' | 'password' | 'code' | 'totp_code' | 'totp_secret' | 'text'; + + /** + * Human-readable label shown to the user. + */ + label?: string; + + /** + * Selector for the visible field, when available. + */ + observed_selector?: string | null; + + /** + * Whether this field is required. + */ + required?: boolean; + } + /** * An MFA method option for verification */ @@ -1562,6 +1742,11 @@ export namespace ConnectionLoginParams { } export interface ConnectionSubmitParams { + /** + * Canonical map of field ID to submitted value. + */ + field_values?: { [key: string]: string }; + /** * Map of field name to value */ @@ -1572,6 +1757,11 @@ export interface ConnectionSubmitParams { */ mfa_option_id?: string; + /** + * Canonical choice ID selected by the user. + */ + selected_choice_id?: string; + /** * The sign-in option ID to select (when sign_in_options were returned) */ From 269e9113173d2123bd8ac6187cc9ef37a2309d52 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 18 Jul 2026 02:08:28 +0000 Subject: [PATCH 506/551] feat(stlc): configurable CI runner and private-production-repo support in workflow templates --- .github/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3125f0fd..03467204 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,7 +18,7 @@ jobs: lint: timeout-minutes: 10 name: lint - runs-on: ${{ github.repository == 'stainless-sdks/kernel-typescript' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} + runs-on: ${{ startsWith(github.repository, 'stainless-sdks/') && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} if: (github.event_name == 'push' || github.event.pull_request.head.repo.fork) && (github.event_name != 'push' || github.event.head_commit.message != 'codegen metadata') steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 @@ -37,7 +37,7 @@ jobs: build: timeout-minutes: 5 name: build - runs-on: ${{ github.repository == 'stainless-sdks/kernel-typescript' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} + runs-on: ${{ startsWith(github.repository, 'stainless-sdks/') && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} if: (github.event_name == 'push' || github.event.pull_request.head.repo.fork) && (github.event_name != 'push' || github.event.head_commit.message != 'codegen metadata') permissions: contents: read @@ -77,7 +77,7 @@ jobs: test: timeout-minutes: 10 name: test - runs-on: ${{ github.repository == 'stainless-sdks/kernel-typescript' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} + runs-on: ${{ startsWith(github.repository, 'stainless-sdks/') && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} if: github.event_name == 'push' || github.event.pull_request.head.repo.fork steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 From d2736436b9df77fbb3abce6a364d9704cea10ac9 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 18 Jul 2026 06:13:45 +0000 Subject: [PATCH 507/551] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 9e326663..d995362c 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 127 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-5b9eb5cdadbc7a5f404f5c2cec40f726e5fece54bf8e2dd29ab5c7700eb44f0e.yml -openapi_spec_hash: 63dd0798a4c0ed6477af50fff397f5dc +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-a7f011596b06b94e4be1999585d4675992a5c08e13bc3943764971b78412f020.yml +openapi_spec_hash: 6c6b46659fd5220d57d5ef806986154c config_hash: 77ee715aa17061166f9a02b264a21b8d From ae4eecdd993e969471fc024cbaf85857943a071b Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sun, 19 Jul 2026 19:16:35 +0000 Subject: [PATCH 508/551] feat: Expose browser sessions on auth timeline events --- .stats.yml | 4 ++-- src/resources/auth/connections.ts | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index d995362c..c189c7a2 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 127 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-a7f011596b06b94e4be1999585d4675992a5c08e13bc3943764971b78412f020.yml -openapi_spec_hash: 6c6b46659fd5220d57d5ef806986154c +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-1dffe057847b596dd311ce4b6e0e8036126dce3e97d390636c9c8e6d2f4823e1.yml +openapi_spec_hash: c06336c199ee64c222ba3122deae9463 config_hash: 77ee715aa17061166f9a02b264a21b8d diff --git a/src/resources/auth/connections.ts b/src/resources/auth/connections.ts index b9567179..2ecbb713 100644 --- a/src/resources/auth/connections.ts +++ b/src/resources/auth/connections.ts @@ -909,6 +909,11 @@ export interface ManagedAuthTimelineEvent { */ type: 'login' | 'reauth' | 'health_check'; + /** + * Browser session that produced the event, if one was created. + */ + browser_session_id?: string; + /** * Machine-readable error code. Present when a login/reauth event failed. */ From 22adf35950b3cbeeedac64fb8b885bcecbba28fe Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sun, 19 Jul 2026 19:58:50 +0000 Subject: [PATCH 509/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 954743f6..2e534d65 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.79.0" + ".": "0.80.0" } diff --git a/package.json b/package.json index bc9c2c39..336d302d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.79.0", + "version": "0.80.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 68f919f7..bc177f48 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.79.0'; // x-release-please-version +export const VERSION = '0.80.0'; // x-release-please-version From 0384fbd54f993c722be95f87119710300317487c Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 21 Jul 2026 18:54:23 +0000 Subject: [PATCH 510/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 2e534d65..3f0c280c 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.80.0" + ".": "0.81.0" } diff --git a/package.json b/package.json index 336d302d..6ee021d0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.80.0", + "version": "0.81.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index bc177f48..3446cca0 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.80.0'; // x-release-please-version +export const VERSION = '0.81.0'; // x-release-please-version From 694fbf879c65d6d4d7a64beb26eda84f1361dcfa Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 22 Jul 2026 22:05:00 +0000 Subject: [PATCH 511/551] feat: Count project names by Unicode code point --- .stats.yml | 4 ++-- src/resources/projects/projects.ts | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.stats.yml b/.stats.yml index c189c7a2..f5843501 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 127 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-1dffe057847b596dd311ce4b6e0e8036126dce3e97d390636c9c8e6d2f4823e1.yml -openapi_spec_hash: c06336c199ee64c222ba3122deae9463 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-6568ec20bad9bc5257619dae6b6817eedc308f8b74453912e660df95e329e44a.yml +openapi_spec_hash: 17b9ed1a0a3193731c52c4b1aac2b5b8 config_hash: 77ee715aa17061166f9a02b264a21b8d diff --git a/src/resources/projects/projects.ts b/src/resources/projects/projects.ts index 9fbc1f49..0480b729 100644 --- a/src/resources/projects/projects.ts +++ b/src/resources/projects/projects.ts @@ -91,7 +91,7 @@ export type ProjectsOffsetPagination = OffsetPagination; export interface CreateProjectRequest { /** - * Project name (1-255 characters) + * Project name (1-255 Unicode code points) */ name: string; } @@ -125,7 +125,7 @@ export interface Project { export interface UpdateProjectRequest { /** - * New project name + * New project name (1-255 Unicode code points) */ name?: string; @@ -137,14 +137,14 @@ export interface UpdateProjectRequest { export interface ProjectCreateParams { /** - * Project name (1-255 characters) + * Project name (1-255 Unicode code points) */ name: string; } export interface ProjectUpdateParams { /** - * New project name + * New project name (1-255 Unicode code points) */ name?: string; From eead2ec5be1bd2208b31555bfef3f6dabc5d87aa Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 23 Jul 2026 19:39:22 +0000 Subject: [PATCH 512/551] feat: Stream profile downloads as tar archives --- .stats.yml | 4 ++-- api.md | 2 +- src/client.ts | 9 ++++++++- src/resources/index.ts | 1 + src/resources/profiles.ts | 23 ++++++++++++++++++++--- tests/api-resources/profiles.test.ts | 8 ++++++++ 6 files changed, 40 insertions(+), 7 deletions(-) diff --git a/.stats.yml b/.stats.yml index f5843501..3dedd81c 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 127 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-6568ec20bad9bc5257619dae6b6817eedc308f8b74453912e660df95e329e44a.yml -openapi_spec_hash: 17b9ed1a0a3193731c52c4b1aac2b5b8 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-5163e8941e42f7fb84e10f572f538202b31722c84bb980db74ccd44a960eb87f.yml +openapi_spec_hash: 8aa974cf7843681d6ae3e6dcf099596d config_hash: 77ee715aa17061166f9a02b264a21b8d diff --git a/api.md b/api.md index f7950f3e..d5d74e88 100644 --- a/api.md +++ b/api.md @@ -255,7 +255,7 @@ Methods: - client.profiles.update(idOrName, { ...params }) -> Profile - client.profiles.list({ ...params }) -> ProfilesOffsetPagination - client.profiles.delete(idOrName) -> void -- client.profiles.download(idOrName) -> Response +- client.profiles.download(idOrName, { ...params }) -> Response # Auth diff --git a/src/client.ts b/src/client.ts index b82d2d76..b4e96b73 100644 --- a/src/client.ts +++ b/src/client.ts @@ -117,7 +117,13 @@ import { InvocationUpdateResponse, Invocations, } from './resources/invocations'; -import { ProfileCreateParams, ProfileListParams, ProfileUpdateParams, Profiles } from './resources/profiles'; +import { + ProfileCreateParams, + ProfileDownloadParams, + ProfileListParams, + ProfileUpdateParams, + Profiles, +} from './resources/profiles'; import { Proxies, ProxyCheckParams, @@ -1084,6 +1090,7 @@ export declare namespace Kernel { type ProfileCreateParams as ProfileCreateParams, type ProfileUpdateParams as ProfileUpdateParams, type ProfileListParams as ProfileListParams, + type ProfileDownloadParams as ProfileDownloadParams, }; export { Auth as Auth }; diff --git a/src/resources/index.ts b/src/resources/index.ts index 797de87a..8afbadf4 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -125,6 +125,7 @@ export { type ProfileCreateParams, type ProfileUpdateParams, type ProfileListParams, + type ProfileDownloadParams, } from './profiles'; export { Projects, diff --git a/src/resources/profiles.ts b/src/resources/profiles.ts index 52546235..b524f768 100644 --- a/src/resources/profiles.ts +++ b/src/resources/profiles.ts @@ -98,7 +98,10 @@ export class Profiles extends APIResource { } /** - * Returns a zstd-compressed tar file of the full user-data directory. + * Downloads the profile in its stored format by default. Current profiles are + * returned as zstd-compressed tar archives, while legacy profiles remain JSON. Set + * `format=tar` to decompress current profiles during download; legacy profiles + * remain JSON. * * @example * ```ts @@ -110,10 +113,15 @@ export class Profiles extends APIResource { * console.log(content); * ``` */ - download(idOrName: string, options?: RequestOptions): APIPromise { + download( + idOrName: string, + query: ProfileDownloadParams | null | undefined = {}, + options?: RequestOptions, + ): APIPromise { return this._client.get(path`/profiles/${idOrName}/download`, { + query, ...options, - headers: buildHeaders([{ Accept: 'application/octet-stream' }, options?.headers]), + headers: buildHeaders([{ Accept: 'application/zstd' }, options?.headers]), __binaryResponse: true, }); } @@ -152,11 +160,20 @@ export interface ProfileListParams extends OffsetPaginationParams { query?: string; } +export interface ProfileDownloadParams { + /** + * Response format for current profile archives. Legacy profiles are always + * returned as JSON. + */ + format?: 'tar.zst' | 'tar'; +} + export declare namespace Profiles { export { type ProfileCreateParams as ProfileCreateParams, type ProfileUpdateParams as ProfileUpdateParams, type ProfileListParams as ProfileListParams, + type ProfileDownloadParams as ProfileDownloadParams, }; } diff --git a/tests/api-resources/profiles.test.ts b/tests/api-resources/profiles.test.ts index 13ff21e4..85449482 100644 --- a/tests/api-resources/profiles.test.ts +++ b/tests/api-resources/profiles.test.ts @@ -88,4 +88,12 @@ describe('resource profiles', () => { expect(dataAndResponse.data).toBe(response); expect(dataAndResponse.response).toBe(rawResponse); }); + + // Mock server tests are disabled + test.skip('download: 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.profiles.download('id_or_name', { format: 'tar.zst' }, { path: '/_stainless_unknown_path' }), + ).rejects.toThrow(Kernel.NotFoundError); + }); }); From 52d8c8c7449b510275f6a2078b124c5e8f6c243d Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 23 Jul 2026 20:16:41 +0000 Subject: [PATCH 513/551] feat: Use format-neutral profile download Accept header --- .stats.yml | 4 ++-- src/resources/profiles.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.stats.yml b/.stats.yml index 3dedd81c..c9122258 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 127 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-5163e8941e42f7fb84e10f572f538202b31722c84bb980db74ccd44a960eb87f.yml -openapi_spec_hash: 8aa974cf7843681d6ae3e6dcf099596d +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-477bd1ff6f7053f2bd4687d7c5fc9a6a1d56a584be42f927abc6fc858ff35718.yml +openapi_spec_hash: 3bf4cc824f6497c4ad109abd3187eede config_hash: 77ee715aa17061166f9a02b264a21b8d diff --git a/src/resources/profiles.ts b/src/resources/profiles.ts index b524f768..3249beb9 100644 --- a/src/resources/profiles.ts +++ b/src/resources/profiles.ts @@ -121,7 +121,7 @@ export class Profiles extends APIResource { return this._client.get(path`/profiles/${idOrName}/download`, { query, ...options, - headers: buildHeaders([{ Accept: 'application/zstd' }, options?.headers]), + headers: buildHeaders([{ Accept: 'application/octet-stream' }, options?.headers]), __binaryResponse: true, }); } From 826deb02f0a6cdf442dcceb96524cf00ee0ac76c Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 23 Jul 2026 20:42:22 +0000 Subject: [PATCH 514/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 3f0c280c..b6d685d1 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.81.0" + ".": "0.82.0" } diff --git a/package.json b/package.json index 6ee021d0..3beacec0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.81.0", + "version": "0.82.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 3446cca0..79ea53aa 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.81.0'; // x-release-please-version +export const VERSION = '0.82.0'; // x-release-please-version From 38cc4369f3033fc73e74f3830b00f0da71f7d408 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 24 Jul 2026 17:49:47 +0000 Subject: [PATCH 515/551] feat: Add browser telemetry to managed auth connections --- .stats.yml | 4 +- src/resources/auth/connections.ts | 235 +++++++++++++++++++ tests/api-resources/auth/connections.test.ts | 28 +++ 3 files changed, 265 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index c9122258..d1ed25e5 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 127 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-477bd1ff6f7053f2bd4687d7c5fc9a6a1d56a584be42f927abc6fc858ff35718.yml -openapi_spec_hash: 3bf4cc824f6497c4ad109abd3187eede +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-a4b8f40deaf572d0dab92ebe0cafa865e1357a18f8720c3f003810da89aa4203.yml +openapi_spec_hash: d06e9bf804151f7d9f7fab77f2e1669c config_hash: 77ee715aa17061166f9a02b264a21b8d diff --git a/src/resources/auth/connections.ts b/src/resources/auth/connections.ts index 2ecbb713..7a459424 100644 --- a/src/resources/auth/connections.ts +++ b/src/resources/auth/connections.ts @@ -2,6 +2,7 @@ import { APIResource } from '../../core/resource'; import * as Shared from '../shared'; +import * as TelemetryAPI from '../browsers/telemetry'; import { APIPromise } from '../../core/api-promise'; import { OffsetPagination, type OffsetPaginationParams, PagePromise } from '../../core/pagination'; import { Stream } from '../../core/streaming'; @@ -297,6 +298,13 @@ export interface ManagedAuth { */ browser_session_id?: string | null; + /** + * Browser telemetry configuration used by this connection's browser sessions by + * default. The exact create-browser configuration is preserved and can be + * overridden per-login. + */ + browser_telemetry?: ManagedAuth.BrowserTelemetry | null; + /** * Whether Kernel can automatically re-authenticate this connection when the * session expires. Requires a prior successful login plus either a Kernel @@ -515,6 +523,38 @@ export interface ManagedAuth { } export namespace ManagedAuth { + /** + * Browser telemetry configuration used by this connection's browser sessions by + * default. The exact create-browser configuration is preserved and can be + * overridden per-login. + */ + export interface BrowserTelemetry { + /** + * Per-category capture flags. The operational categories (control, connection, + * system, captcha) are captured whenever telemetry is enabled; set one to + * enabled=false to opt out. The CDP categories (console, network, page, + * interaction) and screenshot are off by default; set enabled=true to opt in. On + * create, provided categories layer onto the default set. On update, provided + * categories merge onto the session's current config; when no telemetry is active + * this falls back to the default set (matching create). If browser is omitted or + * empty, the default set is used. A browser config that disables every category + * stops capture on update and starts no capture on create. + */ + browser?: TelemetryAPI.BrowserTelemetryCategoriesConfig; + + /** + * Request shortcut for browser telemetry capture. True enables capture; with no + * browser category settings it captures the default set (control, connection, + * system, captcha), and any browser category settings are layered onto that + * default set. On update, enabled=true resolves the config fresh from the default + * set plus any provided categories, replacing the session's current selection + * rather than merging onto it; omit enabled to merge categories onto the current + * selection instead. False stops capture on update and starts no capture on + * create. enabled=false cannot be combined with browser category settings. + */ + enabled?: boolean; + } + /** * Canonical auth-flow choice awaiting user selection. */ @@ -780,6 +820,13 @@ export interface ManagedAuthCreateRequest { */ auto_reauth?: boolean; + /** + * Browser telemetry configuration used by this connection's browser sessions by + * default. Uses the exact create-browser configuration. Can be overridden + * per-login. + */ + browser_telemetry?: ManagedAuthCreateRequest.BrowserTelemetry | null; + /** * Reference to credentials for the auth connection. Use one of: * @@ -833,6 +880,38 @@ export interface ManagedAuthCreateRequest { } export namespace ManagedAuthCreateRequest { + /** + * Browser telemetry configuration used by this connection's browser sessions by + * default. Uses the exact create-browser configuration. Can be overridden + * per-login. + */ + export interface BrowserTelemetry { + /** + * Per-category capture flags. The operational categories (control, connection, + * system, captcha) are captured whenever telemetry is enabled; set one to + * enabled=false to opt out. The CDP categories (console, network, page, + * interaction) and screenshot are off by default; set enabled=true to opt in. On + * create, provided categories layer onto the default set. On update, provided + * categories merge onto the session's current config; when no telemetry is active + * this falls back to the default set (matching create). If browser is omitted or + * empty, the default set is used. A browser config that disables every category + * stops capture on update and starts no capture on create. + */ + browser?: TelemetryAPI.BrowserTelemetryCategoriesConfig; + + /** + * Request shortcut for browser telemetry capture. True enables capture; with no + * browser category settings it captures the default set (control, connection, + * system, captcha), and any browser category settings are layered onto that + * default set. On update, enabled=true resolves the config fresh from the default + * set plus any provided categories, replacing the session's current selection + * rather than merging onto it; omit enabled to merge categories onto the current + * selection instead. False stops capture on update and starts no capture on + * create. enabled=false cannot be combined with browser category settings. + */ + enabled?: boolean; + } + /** * Reference to credentials for the auth connection. Use one of: * @@ -981,6 +1060,13 @@ export interface ManagedAuthUpdateRequest { */ auto_reauth?: boolean; + /** + * Browser telemetry configuration used by future browser sessions for this + * connection. Uses the exact create-browser configuration. Set enabled to false to + * disable telemetry. + */ + browser_telemetry?: ManagedAuthUpdateRequest.BrowserTelemetry | null; + /** * Reference to credentials for the auth connection. Use one of: * @@ -1028,6 +1114,38 @@ export interface ManagedAuthUpdateRequest { } export namespace ManagedAuthUpdateRequest { + /** + * Browser telemetry configuration used by future browser sessions for this + * connection. Uses the exact create-browser configuration. Set enabled to false to + * disable telemetry. + */ + export interface BrowserTelemetry { + /** + * Per-category capture flags. The operational categories (control, connection, + * system, captcha) are captured whenever telemetry is enabled; set one to + * enabled=false to opt out. The CDP categories (console, network, page, + * interaction) and screenshot are off by default; set enabled=true to opt in. On + * create, provided categories layer onto the default set. On update, provided + * categories merge onto the session's current config; when no telemetry is active + * this falls back to the default set (matching create). If browser is omitted or + * empty, the default set is used. A browser config that disables every category + * stops capture on update and starts no capture on create. + */ + browser?: TelemetryAPI.BrowserTelemetryCategoriesConfig; + + /** + * Request shortcut for browser telemetry capture. True enables capture; with no + * browser category settings it captures the default set (control, connection, + * system, captcha), and any browser category settings are layered onto that + * default set. On update, enabled=true resolves the config fresh from the default + * set plus any provided categories, replacing the session's current selection + * rather than merging onto it; omit enabled to merge categories onto the current + * selection instead. False stops capture on update and starts no capture on + * create. enabled=false cannot be combined with browser category settings. + */ + enabled?: boolean; + } + /** * Reference to credentials for the auth connection. Use one of: * @@ -1480,6 +1598,13 @@ export interface ConnectionCreateParams { */ auto_reauth?: boolean; + /** + * Browser telemetry configuration used by this connection's browser sessions by + * default. Uses the exact create-browser configuration. Can be overridden + * per-login. + */ + browser_telemetry?: ConnectionCreateParams.BrowserTelemetry | null; + /** * Reference to credentials for the auth connection. Use one of: * @@ -1533,6 +1658,38 @@ export interface ConnectionCreateParams { } export namespace ConnectionCreateParams { + /** + * Browser telemetry configuration used by this connection's browser sessions by + * default. Uses the exact create-browser configuration. Can be overridden + * per-login. + */ + export interface BrowserTelemetry { + /** + * Per-category capture flags. The operational categories (control, connection, + * system, captcha) are captured whenever telemetry is enabled; set one to + * enabled=false to opt out. The CDP categories (console, network, page, + * interaction) and screenshot are off by default; set enabled=true to opt in. On + * create, provided categories layer onto the default set. On update, provided + * categories merge onto the session's current config; when no telemetry is active + * this falls back to the default set (matching create). If browser is omitted or + * empty, the default set is used. A browser config that disables every category + * stops capture on update and starts no capture on create. + */ + browser?: TelemetryAPI.BrowserTelemetryCategoriesConfig; + + /** + * Request shortcut for browser telemetry capture. True enables capture; with no + * browser category settings it captures the default set (control, connection, + * system, captcha), and any browser category settings are layered onto that + * default set. On update, enabled=true resolves the config fresh from the default + * set plus any provided categories, replacing the session's current selection + * rather than merging onto it; omit enabled to merge categories onto the current + * selection instead. False stops capture on update and starts no capture on + * create. enabled=false cannot be combined with browser category settings. + */ + enabled?: boolean; + } + /** * Reference to credentials for the auth connection. Use one of: * @@ -1598,6 +1755,13 @@ export interface ConnectionUpdateParams { */ auto_reauth?: boolean; + /** + * Browser telemetry configuration used by future browser sessions for this + * connection. Uses the exact create-browser configuration. Set enabled to false to + * disable telemetry. + */ + browser_telemetry?: ConnectionUpdateParams.BrowserTelemetry | null; + /** * Reference to credentials for the auth connection. Use one of: * @@ -1645,6 +1809,38 @@ export interface ConnectionUpdateParams { } export namespace ConnectionUpdateParams { + /** + * Browser telemetry configuration used by future browser sessions for this + * connection. Uses the exact create-browser configuration. Set enabled to false to + * disable telemetry. + */ + export interface BrowserTelemetry { + /** + * Per-category capture flags. The operational categories (control, connection, + * system, captcha) are captured whenever telemetry is enabled; set one to + * enabled=false to opt out. The CDP categories (console, network, page, + * interaction) and screenshot are off by default; set enabled=true to opt in. On + * create, provided categories layer onto the default set. On update, provided + * categories merge onto the session's current config; when no telemetry is active + * this falls back to the default set (matching create). If browser is omitted or + * empty, the default set is used. A browser config that disables every category + * stops capture on update and starts no capture on create. + */ + browser?: TelemetryAPI.BrowserTelemetryCategoriesConfig; + + /** + * Request shortcut for browser telemetry capture. True enables capture; with no + * browser category settings it captures the default set (control, connection, + * system, captcha), and any browser category settings are layered onto that + * default set. On update, enabled=true resolves the config fresh from the default + * set plus any provided categories, replacing the session's current selection + * rather than merging onto it; omit enabled to merge categories onto the current + * selection instead. False stops capture on update and starts no capture on + * create. enabled=false cannot be combined with browser category settings. + */ + enabled?: boolean; + } + /** * Reference to credentials for the auth connection. Use one of: * @@ -1711,6 +1907,13 @@ export interface ConnectionListParams extends OffsetPaginationParams { } export interface ConnectionLoginParams { + /** + * Override the connection's default browser telemetry configuration for this + * login. When omitted, the connection's browser_telemetry default is used. Uses + * the exact create-browser configuration. + */ + browser_telemetry?: ConnectionLoginParams.BrowserTelemetry | null; + /** * Proxy selection. Provide either id or name. The proxy must be in the same * project as the resource referencing it. When selecting by name, the name must @@ -1727,6 +1930,38 @@ export interface ConnectionLoginParams { } export namespace ConnectionLoginParams { + /** + * Override the connection's default browser telemetry configuration for this + * login. When omitted, the connection's browser_telemetry default is used. Uses + * the exact create-browser configuration. + */ + export interface BrowserTelemetry { + /** + * Per-category capture flags. The operational categories (control, connection, + * system, captcha) are captured whenever telemetry is enabled; set one to + * enabled=false to opt out. The CDP categories (console, network, page, + * interaction) and screenshot are off by default; set enabled=true to opt in. On + * create, provided categories layer onto the default set. On update, provided + * categories merge onto the session's current config; when no telemetry is active + * this falls back to the default set (matching create). If browser is omitted or + * empty, the default set is used. A browser config that disables every category + * stops capture on update and starts no capture on create. + */ + browser?: TelemetryAPI.BrowserTelemetryCategoriesConfig; + + /** + * Request shortcut for browser telemetry capture. True enables capture; with no + * browser category settings it captures the default set (control, connection, + * system, captcha), and any browser category settings are layered onto that + * default set. On update, enabled=true resolves the config fresh from the default + * set plus any provided categories, replacing the session's current selection + * rather than merging onto it; omit enabled to merge categories onto the current + * selection instead. False stops capture on update and starts no capture on + * create. enabled=false cannot be combined with browser category settings. + */ + enabled?: boolean; + } + /** * Proxy selection. Provide either id or name. The proxy must be in the same * project as the resource referencing it. When selecting by name, the name must diff --git a/tests/api-resources/auth/connections.test.ts b/tests/api-resources/auth/connections.test.ts index 66915b5b..6094561e 100644 --- a/tests/api-resources/auth/connections.test.ts +++ b/tests/api-resources/auth/connections.test.ts @@ -30,6 +30,20 @@ describe('resource connections', () => { profile_name: 'user-123', allowed_domains: ['login.netflix.com', 'auth.netflix.com'], auto_reauth: true, + browser_telemetry: { + browser: { + captcha: { enabled: true }, + connection: { enabled: true }, + console: { enabled: true }, + control: { enabled: true }, + interaction: { enabled: true }, + network: { enabled: true }, + page: { enabled: true }, + screenshot: { enabled: true }, + system: { enabled: true }, + }, + enabled: true, + }, credential: { auto: true, name: 'my-netflix-creds', @@ -141,6 +155,20 @@ describe('resource connections', () => { client.auth.connections.login( 'id', { + browser_telemetry: { + browser: { + captcha: { enabled: true }, + connection: { enabled: true }, + console: { enabled: true }, + control: { enabled: true }, + interaction: { enabled: true }, + network: { enabled: true }, + page: { enabled: true }, + screenshot: { enabled: true }, + system: { enabled: true }, + }, + enabled: true, + }, proxy: { id: 'id', name: 'name' }, record_session: true, }, From 33501cfdbb7ad44bf5d3a9da0b92889bd633cefe Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 24 Jul 2026 18:05:17 +0000 Subject: [PATCH 516/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index b6d685d1..4a458770 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.82.0" + ".": "0.83.0" } diff --git a/package.json b/package.json index 3beacec0..0e51a899 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.82.0", + "version": "0.83.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 79ea53aa..0c8b7a42 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.82.0'; // x-release-please-version +export const VERSION = '0.83.0'; // x-release-please-version From 091b97773c0732523260cd0294319fa666f7135e Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 27 Jul 2026 20:34:27 +0000 Subject: [PATCH 517/551] feat: Expose telemetry state on managed auth timeline events --- .stats.yml | 4 ++-- src/resources/auth/connections.ts | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index d1ed25e5..748759e3 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 127 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-a4b8f40deaf572d0dab92ebe0cafa865e1357a18f8720c3f003810da89aa4203.yml -openapi_spec_hash: d06e9bf804151f7d9f7fab77f2e1669c +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-904fd6fd50970ea07ec05c51b1ae0819ffb64cbf0921fff9daed6792b64f1dc9.yml +openapi_spec_hash: cbd6626bdac7beaa768abb346e03fb74 config_hash: 77ee715aa17061166f9a02b264a21b8d diff --git a/src/resources/auth/connections.ts b/src/resources/auth/connections.ts index 7a459424..145f9d1d 100644 --- a/src/resources/auth/connections.ts +++ b/src/resources/auth/connections.ts @@ -1028,6 +1028,11 @@ export interface ManagedAuthTimelineEvent { | 'COMPLETED' | 'EXPIRED'; + /** + * Whether browser telemetry capture started for this event's browser session. + */ + telemetry_captured?: boolean; + /** * When the event was last updated. Present for login/reauth events. */ From 54c77c992ab3c52b516d0011f13a5c7a94fc98a4 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 27 Jul 2026 20:47:38 +0000 Subject: [PATCH 518/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 4a458770..969a63da 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.83.0" + ".": "0.84.0" } diff --git a/package.json b/package.json index 0e51a899..f9dfd6e4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.83.0", + "version": "0.84.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 0c8b7a42..622cca17 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.83.0'; // x-release-please-version +export const VERSION = '0.84.0'; // x-release-please-version From 576d604f92371422b169ccd8267486a26e3ebf78 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 28 Jul 2026 21:01:10 +0000 Subject: [PATCH 519/551] feat: Add encrypted per-proxy CA bundle for BYO MITM proxies --- .stats.yml | 4 ++-- src/resources/proxies.ts | 32 ++++++++++++++++++++++++++++++++ yarn.lock | 6 +++--- 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/.stats.yml b/.stats.yml index 748759e3..20e66039 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 127 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-904fd6fd50970ea07ec05c51b1ae0819ffb64cbf0921fff9daed6792b64f1dc9.yml -openapi_spec_hash: cbd6626bdac7beaa768abb346e03fb74 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-32a5ef4f5def9dde3ed7acc2b6159b143194e224ceaad2dbbbcb766cac90602e.yml +openapi_spec_hash: 3f514f770bb352d98bd3dbcf865a077f config_hash: 77ee715aa17061166f9a02b264a21b8d diff --git a/src/resources/proxies.ts b/src/resources/proxies.ts index 28c592cc..0ccef512 100644 --- a/src/resources/proxies.ts +++ b/src/resources/proxies.ts @@ -255,6 +255,11 @@ export namespace ProxyCreateResponse { */ port: number; + /** + * Whether the proxy has a custom CA bundle configured. + */ + has_ca_bundle?: boolean; + /** * Whether the proxy has a password. */ @@ -411,6 +416,11 @@ export namespace ProxyRetrieveResponse { */ port: number; + /** + * Whether the proxy has a custom CA bundle configured. + */ + has_ca_bundle?: boolean; + /** * Whether the proxy has a password. */ @@ -567,6 +577,11 @@ export namespace ProxyUpdateResponse { */ port: number; + /** + * Whether the proxy has a custom CA bundle configured. + */ + has_ca_bundle?: boolean; + /** * Whether the proxy has a password. */ @@ -723,6 +738,11 @@ export namespace ProxyListResponse { */ port: number; + /** + * Whether the proxy has a custom CA bundle configured. + */ + has_ca_bundle?: boolean; + /** * Whether the proxy has a password. */ @@ -879,6 +899,11 @@ export namespace ProxyCheckResponse { */ port: number; + /** + * Whether the proxy has a custom CA bundle configured. + */ + has_ca_bundle?: boolean; + /** * Whether the proxy has a password. */ @@ -1015,6 +1040,13 @@ export namespace ProxyCreateParams { */ port: number; + /** + * PEM-encoded CA certificate bundle the proxy re-signs upstream TLS with. Provide + * when the proxy terminates TLS (MITM) so the browser trusts its certificates. May + * contain multiple concatenated certificates. + */ + ca_bundle?: string; + /** * Password for proxy authentication. */ diff --git a/yarn.lock b/yarn.lock index 443cc054..957aa469 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1228,9 +1228,9 @@ baseline-browser-mapping@^2.9.0: integrity sha512-B0xUquLkiGLgHhpPBqvl7GWegWBUNuujQ6kXd/r1U38ElPT6Ok8KZ8e+FpUGEc2ZoRQUzq/aUnaKFc/svWUGSg== brace-expansion@^2.0.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.1.2.tgz#0bba2271feb7d458b0d31ad13625aaa4754431e2" - integrity sha512-w5JZcKgdhDOgOwm8H+KgbosopHMuGcl6qbulwjtz3SM7I7P3yW1eAjzMPLrIE+NQ9vjgANKHWeMHnrT0OXW1oA== + version "2.1.3" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.1.3.tgz#1bf69aacdf6a4380ca17c284d9f928d4aa6401bc" + integrity sha512-DRdx5neNsG/QXbniLFWi2YmC/68oeOOmKz6zOjVk6ZS1ZLXgLIKqVEc6hWsmkjBbgii0SwaBTcJ5XKj5gzY/4A== dependencies: balanced-match "^1.0.0" From a42ea62a93caee7d2fdde64847ddb0f970d49ef3 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 29 Jul 2026 13:46:44 +0000 Subject: [PATCH 520/551] feat: Stabilize project lifecycle error codes --- .stats.yml | 4 ++-- src/client.ts | 3 +++ src/resources/projects/limits.ts | 2 ++ src/resources/projects/projects.ts | 2 ++ 4 files changed, 9 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 20e66039..e1475cae 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 127 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-32a5ef4f5def9dde3ed7acc2b6159b143194e224ceaad2dbbbcb766cac90602e.yml -openapi_spec_hash: 3f514f770bb352d98bd3dbcf865a077f +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-7b03462454d6fa8390eaebc1b411d3e160501bf96abb93b75d38dfc382d4ce51.yml +openapi_spec_hash: ba55400aafb4759cc06ec139fe528dfc config_hash: 77ee715aa17061166f9a02b264a21b8d diff --git a/src/client.ts b/src/client.ts index b4e96b73..bbcdad40 100644 --- a/src/client.ts +++ b/src/client.ts @@ -981,6 +981,9 @@ export class Kernel { credentials: API.Credentials = new API.Credentials(this); /** * Create and manage projects for resource isolation within an organization. + * When projects are disabled for the organization, project operations return + * `404` with code `projects_disabled`. + * */ projects: API.Projects = new API.Projects(this); organization: API.Organization = new API.Organization(this); diff --git a/src/resources/projects/limits.ts b/src/resources/projects/limits.ts index d1a3e53c..8457373d 100644 --- a/src/resources/projects/limits.ts +++ b/src/resources/projects/limits.ts @@ -7,6 +7,8 @@ import { path } from '../../internal/utils/path'; /** * Create and manage projects for resource isolation within an organization. + * When projects are disabled for the organization, project operations return + * `404` with code `projects_disabled`. */ export class Limits extends APIResource { /** diff --git a/src/resources/projects/projects.ts b/src/resources/projects/projects.ts index 0480b729..a7124204 100644 --- a/src/resources/projects/projects.ts +++ b/src/resources/projects/projects.ts @@ -11,6 +11,8 @@ import { path } from '../../internal/utils/path'; /** * Create and manage projects for resource isolation within an organization. + * When projects are disabled for the organization, project operations return + * `404` with code `projects_disabled`. */ export class Projects extends APIResource { limits: LimitsAPI.Limits = new LimitsAPI.Limits(this._client); From e8855ad129ab12a33b5d6b768902adec9e62eb2c Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 29 Jul 2026 14:05:25 +0000 Subject: [PATCH 521/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 969a63da..b7e1f866 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.84.0" + ".": "0.85.0" } diff --git a/package.json b/package.json index f9dfd6e4..9cfce52e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.84.0", + "version": "0.85.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 622cca17..2e21901d 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.84.0'; // x-release-please-version +export const VERSION = '0.85.0'; // x-release-please-version From baadf5317f651fb69de33aa6d7b1c6c18d0b4a4d Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 31 Jul 2026 02:06:47 +0000 Subject: [PATCH 522/551] fix(stlc): stop hand-edited CI workflows from blocking seals and builds Editing the generated CI/release workflows in an SDK repo is supported: stlc writes them once and then leaves them under the repo's ownership. Two safety checks did not account for that and could refuse to seal custom code, or refuse to build, over workflow edits that were never at risk of being overwritten. The seal refusal could not be cleared by rebuilding. Sealing is also now recorded in place rather than under a new filename each time, so an interrupted build can no longer leave a workspace with no record of its sealed custom code, and sealing one branch no longer discards the record for another. --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 957aa469..f16b683a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1228,9 +1228,9 @@ baseline-browser-mapping@^2.9.0: integrity sha512-B0xUquLkiGLgHhpPBqvl7GWegWBUNuujQ6kXd/r1U38ElPT6Ok8KZ8e+FpUGEc2ZoRQUzq/aUnaKFc/svWUGSg== brace-expansion@^2.0.2: - version "2.1.3" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.1.3.tgz#1bf69aacdf6a4380ca17c284d9f928d4aa6401bc" - integrity sha512-DRdx5neNsG/QXbniLFWi2YmC/68oeOOmKz6zOjVk6ZS1ZLXgLIKqVEc6hWsmkjBbgii0SwaBTcJ5XKj5gzY/4A== + version "2.1.4" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.1.4.tgz#589dab11c0018d0366be64cd8bf12c8dbecc8326" + integrity sha512-hGfVzPxthbf3+2yjg/RBs60cB0FhqBS/zvdV/4wn4/BmN0bNMMHPc4V/BbFieqf1TKAGGAHnY4eSjajCl0f2Xg== dependencies: balanced-match "^1.0.0" From 9f8427310cde33c4c07708bc8be195266fd3f4f6 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 31 Jul 2026 18:06:52 +0000 Subject: [PATCH 523/551] feat: Report the unified concurrency ceiling from the org limits endpoint --- .stats.yml | 4 ++-- src/resources/projects/limits.ts | 9 +++------ 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/.stats.yml b/.stats.yml index e1475cae..0f14b3da 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 127 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-7b03462454d6fa8390eaebc1b411d3e160501bf96abb93b75d38dfc382d4ce51.yml -openapi_spec_hash: ba55400aafb4759cc06ec139fe528dfc +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-7d774918a5bbe0a980a1dca0322e74d2b4e3d3372a2cbc9513e48f4b8b6abfa1.yml +openapi_spec_hash: 8007b5846ff01c221e29d467b1cb8aaf config_hash: 77ee715aa17061166f9a02b264a21b8d diff --git a/src/resources/projects/limits.ts b/src/resources/projects/limits.ts index 8457373d..ae16b9f1 100644 --- a/src/resources/projects/limits.ts +++ b/src/resources/projects/limits.ts @@ -59,8 +59,7 @@ export interface ProjectLimits { /** * @deprecated Deprecated: pooled browsers now count toward - * `max_concurrent_sessions`. Always null once the unified concurrency limit is - * enabled for your organization. + * `max_concurrent_sessions`. Always null. */ max_pooled_sessions?: number | null; } @@ -81,8 +80,7 @@ export interface UpdateProjectLimitsRequest { /** * @deprecated Deprecated: pooled browsers now count toward - * `max_concurrent_sessions`. Requests that set this field are rejected with a 400 - * once the unified concurrency limit is enabled for your organization. + * `max_concurrent_sessions`. Requests that set this field are rejected with a 400. */ max_pooled_sessions?: number | null; } @@ -103,8 +101,7 @@ export interface LimitUpdateParams { /** * @deprecated Deprecated: pooled browsers now count toward - * `max_concurrent_sessions`. Requests that set this field are rejected with a 400 - * once the unified concurrency limit is enabled for your organization. + * `max_concurrent_sessions`. Requests that set this field are rejected with a 400. */ max_pooled_sessions?: number | null; } From 3053655e4144843ae45a1d463a495a34cb70d44a Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 1 Aug 2026 15:21:35 +0000 Subject: [PATCH 524/551] feat: Harden managed auth verification and login recovery --- .stats.yml | 4 ++-- src/resources/auth/connections.ts | 12 ++++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 0f14b3da..f433e790 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 127 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-7d774918a5bbe0a980a1dca0322e74d2b4e3d3372a2cbc9513e48f4b8b6abfa1.yml -openapi_spec_hash: 8007b5846ff01c221e29d467b1cb8aaf +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-3d361d4878b48802a1dc486fa597b6b01ce23099d6627bcf836a849f0080c0c7.yml +openapi_spec_hash: f21df7b9241e2e8b8dc04fdae30a3e27 config_hash: 77ee715aa17061166f9a02b264a21b8d diff --git a/src/resources/auth/connections.ts b/src/resources/auth/connections.ts index 145f9d1d..d444b125 100644 --- a/src/resources/auth/connections.ts +++ b/src/resources/auth/connections.ts @@ -697,6 +697,12 @@ export namespace ManagedAuth { */ observed_selector?: string | null; + /** + * Whether the submitted value must replace an existing credential after explicit + * rejection. + */ + replace_existing?: boolean; + /** * Whether this field is required. */ @@ -1482,6 +1488,12 @@ export namespace ConnectionFollowResponse { */ observed_selector?: string | null; + /** + * Whether the submitted value must replace an existing credential after explicit + * rejection. + */ + replace_existing?: boolean; + /** * Whether this field is required. */ From 5341a3ba4cb17225e12a82468837fd7d62b299da Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 3 Aug 2026 20:54:24 +0000 Subject: [PATCH 525/551] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index f433e790..3068025f 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 127 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-3d361d4878b48802a1dc486fa597b6b01ce23099d6627bcf836a849f0080c0c7.yml -openapi_spec_hash: f21df7b9241e2e8b8dc04fdae30a3e27 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-61255bf30e3e3af67416f691a1a6544324415b986ccfcc5995c55e26f25b89d8.yml +openapi_spec_hash: 4fb35a47c7ef551b00229e47b5aa7bf3 config_hash: 77ee715aa17061166f9a02b264a21b8d From 66c5ef42a343d8b89230ba73b5d6ca29086c6522 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 3 Aug 2026 21:16:24 +0000 Subject: [PATCH 526/551] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 3068025f..fcd634ae 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 127 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-61255bf30e3e3af67416f691a1a6544324415b986ccfcc5995c55e26f25b89d8.yml -openapi_spec_hash: 4fb35a47c7ef551b00229e47b5aa7bf3 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-3fc18876d59a47ed6993892cc5f69d7461fe2ca6a94fad43905677955a5adc55.yml +openapi_spec_hash: 75d990158aeb0dac3d3ef8da476e86b9 config_hash: 77ee715aa17061166f9a02b264a21b8d From 98fbeb3c831fdfd632d411e3166c67fd80cc7da2 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 4 Aug 2026 13:37:29 +0000 Subject: [PATCH 527/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index b7e1f866..1f573a83 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.85.0" + ".": "0.86.0" } diff --git a/package.json b/package.json index 9cfce52e..3342daf3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.85.0", + "version": "0.86.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 2e21901d..aefe2115 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.85.0'; // x-release-please-version +export const VERSION = '0.86.0'; // x-release-please-version From c72ce8e6e697938304132a2f1c3285d271d07bdd Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 6 Aug 2026 14:48:14 +0000 Subject: [PATCH 528/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 1f573a83..e3a1f588 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.86.0" + ".": "0.86.1" } diff --git a/package.json b/package.json index 3342daf3..df7e64be 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.86.0", + "version": "0.86.1", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index aefe2115..04689b81 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.86.0'; // x-release-please-version +export const VERSION = '0.86.1'; // x-release-please-version From a54068d105e25ea81d2c5888c09bd6261ccefee4 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 8 Aug 2026 03:10:32 +0000 Subject: [PATCH 529/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index e3a1f588..eb968c27 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.86.1" + ".": "0.87.0" } diff --git a/package.json b/package.json index df7e64be..1f0f8456 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.86.1", + "version": "0.87.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 04689b81..4f0bd6b6 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.86.1'; // x-release-please-version +export const VERSION = '0.87.0'; // x-release-please-version From de2812257f665d784acdf4f3d351dd927f4067ab Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 10 Aug 2026 19:22:15 +0000 Subject: [PATCH 530/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index eb968c27..25cbcb3c 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.87.0" + ".": "0.87.1" } diff --git a/package.json b/package.json index 1f0f8456..5a340b87 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.87.0", + "version": "0.87.1", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 4f0bd6b6..e501f131 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.87.0'; // x-release-please-version +export const VERSION = '0.87.1'; // x-release-please-version From dc3f825519e13d7d06f0bd67423f4405c9cd3666 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 10 Aug 2026 20:34:33 +0000 Subject: [PATCH 531/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 25cbcb3c..e276945d 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.87.1" + ".": "0.88.0" } diff --git a/package.json b/package.json index 5a340b87..af52ab64 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.87.1", + "version": "0.88.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index e501f131..a03b534b 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.87.1'; // x-release-please-version +export const VERSION = '0.88.0'; // x-release-please-version From 8612bc6ac2527a2dd39b414356812297d23a9aa3 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 12 Aug 2026 17:15:03 +0000 Subject: [PATCH 532/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index e276945d..fd66c340 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.88.0" + ".": "0.89.0" } diff --git a/package.json b/package.json index af52ab64..93d928f8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.88.0", + "version": "0.89.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index a03b534b..2a87eb59 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.88.0'; // x-release-please-version +export const VERSION = '0.89.0'; // x-release-please-version From 022a7f0768e423b49e63f65c189870c9e04407e5 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 13 Aug 2026 14:30:11 +0000 Subject: [PATCH 533/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index fd66c340..d383ae01 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.89.0" + ".": "0.90.0" } diff --git a/package.json b/package.json index 93d928f8..2b414bd3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.89.0", + "version": "0.90.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 2a87eb59..f99c21e4 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.89.0'; // x-release-please-version +export const VERSION = '0.90.0'; // x-release-please-version From 0f0866c1a10c14fc645ff744562ef75a18fd3a82 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 14 Aug 2026 18:19:20 +0000 Subject: [PATCH 534/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index d383ae01..cfbb72c8 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.90.0" + ".": "0.91.0" } diff --git a/package.json b/package.json index 2b414bd3..2cbf0a8b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.90.0", + "version": "0.91.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index f99c21e4..3fe97c6e 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.90.0'; // x-release-please-version +export const VERSION = '0.91.0'; // x-release-please-version From d06095c8b7153f9fdd229be859c2ad3befe2f48f Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 17 Aug 2026 21:05:12 +0000 Subject: [PATCH 535/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index cfbb72c8..247080d3 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.91.0" + ".": "0.92.0" } diff --git a/package.json b/package.json index 2cbf0a8b..6caf4cdc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.91.0", + "version": "0.92.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 3fe97c6e..4457d999 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.91.0'; // x-release-please-version +export const VERSION = '0.92.0'; // x-release-please-version From 306b2f10002607796cba84f13df7e80ef6e9ee0e Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 19 Aug 2026 23:58:36 +0000 Subject: [PATCH 536/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 247080d3..b34659af 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.92.0" + ".": "0.93.0" } diff --git a/package.json b/package.json index 6caf4cdc..f1c7ec8f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.92.0", + "version": "0.93.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 4457d999..37e6f5a8 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.92.0'; // x-release-please-version +export const VERSION = '0.93.0'; // x-release-please-version From 1e9a590bf76b0bfeb9761e78efbf9a2f7d8e4827 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 24 Aug 2026 20:23:11 +0000 Subject: [PATCH 537/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index b34659af..2ad9e208 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.93.0" + ".": "0.94.0" } diff --git a/package.json b/package.json index f1c7ec8f..f806b9e6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.93.0", + "version": "0.94.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 37e6f5a8..a914c676 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.93.0'; // x-release-please-version +export const VERSION = '0.94.0'; // x-release-please-version From f75936a66f7f8a76c1de73b963666526722aa03a Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 26 Aug 2026 18:26:22 +0000 Subject: [PATCH 538/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 2ad9e208..efb7bd94 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.94.0" + ".": "0.95.0" } diff --git a/package.json b/package.json index f806b9e6..47523639 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.94.0", + "version": "0.95.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index a914c676..d1d95222 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.94.0'; // x-release-please-version +export const VERSION = '0.95.0'; // x-release-please-version From 06ea20591f6a50c53b1e178693ebeeb3cbdefd2a Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 27 Aug 2026 00:08:02 +0000 Subject: [PATCH 539/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index efb7bd94..6b5b821b 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.95.0" + ".": "0.96.0" } diff --git a/package.json b/package.json index 47523639..1998f75f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.95.0", + "version": "0.96.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index d1d95222..b75d8d52 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.95.0'; // x-release-please-version +export const VERSION = '0.96.0'; // x-release-please-version From 452757c8a7058c1496ef7ce6508b9e885311350a Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 31 Aug 2026 16:36:59 +0000 Subject: [PATCH 540/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 6b5b821b..29c16586 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.96.0" + ".": "0.97.0" } diff --git a/package.json b/package.json index 1998f75f..f9fe182f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.96.0", + "version": "0.97.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index b75d8d52..1b7c9366 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.96.0'; // x-release-please-version +export const VERSION = '0.97.0'; // x-release-please-version From 00aafe46f9f2b4288c96bf7f4f9c0f64aae29a8d Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 2 Sep 2026 19:41:34 +0000 Subject: [PATCH 541/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 29c16586..3c1df308 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.97.0" + ".": "0.98.0" } diff --git a/package.json b/package.json index f9fe182f..bc28fdb7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.97.0", + "version": "0.98.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 1b7c9366..f94f8b86 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.97.0'; // x-release-please-version +export const VERSION = '0.98.0'; // x-release-please-version From 8ec926a0e4ed99d53c1b7cbb1be5981e2e8e7005 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 4 Sep 2026 18:26:07 +0000 Subject: [PATCH 542/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 3c1df308..7c57a5df 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.98.0" + ".": "0.99.0" } diff --git a/package.json b/package.json index bc28fdb7..3c9c9e6c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.98.0", + "version": "0.99.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index f94f8b86..7b4f2ce4 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.98.0'; // x-release-please-version +export const VERSION = '0.99.0'; // x-release-please-version From 830d82b9d5f1306c567baf73aa6310a531abd5b9 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 4 Sep 2026 19:40:26 +0000 Subject: [PATCH 543/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 7c57a5df..d3f5c73e 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.99.0" + ".": "0.100.0" } diff --git a/package.json b/package.json index 3c9c9e6c..0d768114 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.99.0", + "version": "0.100.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 7b4f2ce4..60f44554 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.99.0'; // x-release-please-version +export const VERSION = '0.100.0'; // x-release-please-version From 5cd787f8d532b3759150f60a750c5ad9270ac548 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 15 Sep 2026 16:55:08 +0000 Subject: [PATCH 544/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- yarn.lock | 6 +++--- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index d3f5c73e..31924972 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.100.0" + ".": "0.103.0" } diff --git a/package.json b/package.json index 0d768114..fd95f6ba 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.100.0", + "version": "0.103.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 60f44554..c6a0c39d 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.100.0'; // x-release-please-version +export const VERSION = '0.103.0'; // x-release-please-version diff --git a/yarn.lock b/yarn.lock index f16b683a..a3d6b14e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1228,9 +1228,9 @@ baseline-browser-mapping@^2.9.0: integrity sha512-B0xUquLkiGLgHhpPBqvl7GWegWBUNuujQ6kXd/r1U38ElPT6Ok8KZ8e+FpUGEc2ZoRQUzq/aUnaKFc/svWUGSg== brace-expansion@^2.0.2: - version "2.1.4" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.1.4.tgz#589dab11c0018d0366be64cd8bf12c8dbecc8326" - integrity sha512-hGfVzPxthbf3+2yjg/RBs60cB0FhqBS/zvdV/4wn4/BmN0bNMMHPc4V/BbFieqf1TKAGGAHnY4eSjajCl0f2Xg== + version "2.1.7" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.1.7.tgz#14ea3836731823bb24740225ea43b941b436f9d1" + integrity sha512-uZbew1NqdmPDTMJ8ah1y+b+9QEJrfkXFk3RcTQw3X0jW/xRUvFKsg1CfQdSYGdTbXZWExtU3J3ccxtnfw1Fi0g== dependencies: balanced-match "^1.0.0" From 959a753b52ff2e50a66523165c02390597debd42 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 15 Sep 2026 18:37:49 +0000 Subject: [PATCH 545/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 31924972..d9c93890 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.103.0" + ".": "0.104.0" } diff --git a/package.json b/package.json index fd95f6ba..5675192d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.103.0", + "version": "0.104.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index c6a0c39d..e50cdd9c 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.103.0'; // x-release-please-version +export const VERSION = '0.104.0'; // x-release-please-version From 074fa2bcd76bdc77dc26b48c32cd3fbf0be153a4 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 16 Sep 2026 17:44:23 +0000 Subject: [PATCH 546/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index d9c93890..4101a550 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.104.0" + ".": "0.106.0" } diff --git a/package.json b/package.json index 5675192d..97cadb2b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.104.0", + "version": "0.106.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index e50cdd9c..013fb8ed 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.104.0'; // x-release-please-version +export const VERSION = '0.106.0'; // x-release-please-version From 733206b5aab5d6f67e475430e936961932a6ab0b Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 16 Sep 2026 19:28:49 +0000 Subject: [PATCH 547/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 4101a550..9eeeeb45 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.106.0" + ".": "0.107.0" } diff --git a/package.json b/package.json index 97cadb2b..87c5c39e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.106.0", + "version": "0.107.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 013fb8ed..94039eb8 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.106.0'; // x-release-please-version +export const VERSION = '0.107.0'; // x-release-please-version From f18607d38a07442f3cd57eb335561f2e21e20968 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 17 Sep 2026 19:36:05 +0000 Subject: [PATCH 548/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 9eeeeb45..d0950c80 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.107.0" + ".": "0.108.0" } diff --git a/package.json b/package.json index 87c5c39e..71bae39c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.107.0", + "version": "0.108.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 94039eb8..dd27ba7d 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.107.0'; // x-release-please-version +export const VERSION = '0.108.0'; // x-release-please-version From 349611e3b54f72c41dfd5c639f4c6cda8a1d72e5 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 17 Sep 2026 21:41:50 +0000 Subject: [PATCH 549/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index d0950c80..6c3e52f1 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.108.0" + ".": "0.109.0" } diff --git a/package.json b/package.json index 71bae39c..3b5ec58c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.108.0", + "version": "0.109.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index dd27ba7d..d80ed29e 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.108.0'; // x-release-please-version +export const VERSION = '0.109.0'; // x-release-please-version From 2a804441b86137930eb27d305c1abe40f600d14c Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 18 Sep 2026 19:53:00 +0000 Subject: [PATCH 550/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 6c3e52f1..d0779411 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.109.0" + ".": "0.110.0" } diff --git a/package.json b/package.json index 3b5ec58c..3878011b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.109.0", + "version": "0.110.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index d80ed29e..cad2f126 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.109.0'; // x-release-please-version +export const VERSION = '0.110.0'; // x-release-please-version From a29bc39402783f975a3ac7914a36bfbc7ac363a1 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 22 Sep 2026 16:44:49 +0000 Subject: [PATCH 551/551] chore(internal): version bump --- .release-please-manifest.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index d0779411..6d4c016b 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.110.0" + ".": "0.111.0" } diff --git a/package.json b/package.json index 3878011b..6e2a8a10 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.110.0", + "version": "0.111.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index cad2f126..36c76795 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.110.0'; // x-release-please-version +export const VERSION = '0.111.0'; // x-release-please-version