diff --git a/fern/docs.yml b/fern/docs.yml
index 490c6132..befe138e 100644
--- a/fern/docs.yml
+++ b/fern/docs.yml
@@ -172,6 +172,8 @@ navigation:
- POST /v1/runs/{run_id}/cancel
- POST /v1/runs/{run_id}/retry_webhook
- POST /v1/run/tasks/login
+ - endpoint: POST /v1/run/tasks/download_files
+ hidden: true
- GET /v1/runs/{run_id}/timeline
- section: Workflows
contents:
diff --git a/pyproject.toml b/pyproject.toml
index 935d1902..bec37630 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "skyvern"
-version = "1.0.3"
+version = "1.0.6"
description = ""
authors = [{ name = "Skyvern AI", email = "info@skyvern.com" }]
requires-python = ">=3.11,<3.14"
diff --git a/skyvern-ts/client/README.md b/skyvern-ts/client/README.md
index f92dee52..7fad6695 100644
--- a/skyvern-ts/client/README.md
+++ b/skyvern-ts/client/README.md
@@ -12,6 +12,7 @@ The Skyvern TypeScript library provides convenient access to the Skyvern APIs fr
- [Usage](#usage)
- [Request and Response Types](#request-and-response-types)
- [Exception Handling](#exception-handling)
+- [File Uploads](#file-uploads)
- [Advanced](#advanced)
- [Additional Headers](#additional-headers)
- [Additional Query String Parameters](#additional-query-string-parameters)
@@ -56,7 +57,7 @@ following namespace:
```typescript
import { Skyvern } from "@skyvern/client";
-const request: Skyvern.SetWorkflowTemplateStatusV1WorkflowsWorkflowPermanentIdTemplatePutRequest = {
+const request: Skyvern.RunTaskRequest = {
...
};
```
@@ -81,6 +82,50 @@ try {
}
```
+## File Uploads
+
+You can upload files using the client:
+
+```typescript
+import { createReadStream } from "fs";
+import { SkyvernClient } from "@skyvern/client";
+import * as fs from "fs";
+
+const client = new SkyvernClient({ apiKey: "YOUR_API_KEY" });
+await client.uploadFile({
+ file: fs.createReadStream("/path/to/your/file")
+});
+```
+The client accepts a variety of types for file upload parameters:
+* Stream types: `fs.ReadStream`, `stream.Readable`, and `ReadableStream`
+* Buffered types: `Buffer`, `Blob`, `File`, `ArrayBuffer`, `ArrayBufferView`, and `Uint8Array`
+
+### Metadata
+
+You can configure metadata when uploading a file:
+```typescript
+const file: Uploadable.WithMetadata = {
+ data: createReadStream("path/to/file"),
+ filename: "my-file", // optional
+ contentType: "audio/mpeg", // optional
+ contentLength: 1949, // optional
+};
+```
+
+Alternatively, you can upload a file directly from a file path:
+```typescript
+const file : Uploadable.FromPath = {
+ path: "path/to/file",
+ filename: "my-file", // optional
+ contentType: "audio/mpeg", // optional
+ contentLength: 1949, // optional
+};
+```
+
+The metadata is used to set the `Content-Length`, `Content-Type`, and `Content-Disposition` headers. If not provided, the client will attempt to determine them automatically.
+For example, `fs.ReadStream` has a `path` property which the SDK uses to retrieve the file size from the filesystem without loading it into memory.
+
+
## Advanced
### Additional Headers
diff --git a/skyvern-ts/client/package-lock.json b/skyvern-ts/client/package-lock.json
index 7cf36d76..e1950806 100644
--- a/skyvern-ts/client/package-lock.json
+++ b/skyvern-ts/client/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "@skyvern/client",
- "version": "1.0.3",
+ "version": "1.0.6",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@skyvern/client",
- "version": "1.0.3",
+ "version": "1.0.6",
"dependencies": {
"playwright": "^1.48.0"
},
@@ -28,7 +28,6 @@
"resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-2.2.5.tgz",
"integrity": "sha512-zcIi+163Rc3HtyHbEO7CjeHq8DjQRs40HsGbW6vx2WI0tg8mYQOPouhvHSyEnCBAorfYNnKdR64/IxO7xQ5faw==",
"dev": true,
- "license": "MIT OR Apache-2.0",
"bin": {
"biome": "bin/biome"
},
@@ -58,7 +57,6 @@
"arm64"
],
"dev": true,
- "license": "MIT OR Apache-2.0",
"optional": true,
"os": [
"darwin"
@@ -75,7 +73,6 @@
"x64"
],
"dev": true,
- "license": "MIT OR Apache-2.0",
"optional": true,
"os": [
"darwin"
@@ -92,7 +89,6 @@
"arm64"
],
"dev": true,
- "license": "MIT OR Apache-2.0",
"optional": true,
"os": [
"linux"
@@ -109,7 +105,6 @@
"arm64"
],
"dev": true,
- "license": "MIT OR Apache-2.0",
"optional": true,
"os": [
"linux"
@@ -126,7 +121,6 @@
"x64"
],
"dev": true,
- "license": "MIT OR Apache-2.0",
"optional": true,
"os": [
"linux"
@@ -143,7 +137,6 @@
"x64"
],
"dev": true,
- "license": "MIT OR Apache-2.0",
"optional": true,
"os": [
"linux"
@@ -160,7 +153,6 @@
"arm64"
],
"dev": true,
- "license": "MIT OR Apache-2.0",
"optional": true,
"os": [
"win32"
@@ -177,7 +169,6 @@
"x64"
],
"dev": true,
- "license": "MIT OR Apache-2.0",
"optional": true,
"os": [
"win32"
@@ -191,7 +182,6 @@
"resolved": "https://registry.npmjs.org/@bundled-es-modules/cookie/-/cookie-2.0.1.tgz",
"integrity": "sha512-8o+5fRPLNbjbdGRRmJj3h6Hh1AQJf2dk3qQ/5ZFb+PXkRNiSoMGGUKlsgLfrxneb72axVJyIYji64E2+nNfYyw==",
"dev": true,
- "license": "ISC",
"dependencies": {
"cookie": "^0.7.2"
}
@@ -201,7 +191,6 @@
"resolved": "https://registry.npmjs.org/@bundled-es-modules/statuses/-/statuses-1.0.1.tgz",
"integrity": "sha512-yn7BklA5acgcBr+7w064fGV+SGIFySjCKpqjcWgBAIfrAkY+4GQTJJHQMeT3V/sgz23VTEVV8TtOmkvJAhFVfg==",
"dev": true,
- "license": "ISC",
"dependencies": {
"statuses": "^2.0.1"
}
@@ -214,7 +203,6 @@
"ppc64"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"aix"
@@ -231,7 +219,6 @@
"arm"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"android"
@@ -248,7 +235,6 @@
"arm64"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"android"
@@ -265,7 +251,6 @@
"x64"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"android"
@@ -282,7 +267,6 @@
"arm64"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"darwin"
@@ -299,7 +283,6 @@
"x64"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"darwin"
@@ -316,7 +299,6 @@
"arm64"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"freebsd"
@@ -333,7 +315,6 @@
"x64"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"freebsd"
@@ -350,7 +331,6 @@
"arm"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"linux"
@@ -367,7 +347,6 @@
"arm64"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"linux"
@@ -384,7 +363,6 @@
"ia32"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"linux"
@@ -401,7 +379,6 @@
"loong64"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"linux"
@@ -418,7 +395,6 @@
"mips64el"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"linux"
@@ -435,7 +411,6 @@
"ppc64"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"linux"
@@ -452,7 +427,6 @@
"riscv64"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"linux"
@@ -469,7 +443,6 @@
"s390x"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"linux"
@@ -486,7 +459,6 @@
"x64"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"linux"
@@ -503,7 +475,6 @@
"arm64"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"netbsd"
@@ -520,7 +491,6 @@
"x64"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"netbsd"
@@ -537,7 +507,6 @@
"arm64"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"openbsd"
@@ -554,7 +523,6 @@
"x64"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"openbsd"
@@ -571,7 +539,6 @@
"arm64"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"openharmony"
@@ -588,7 +555,6 @@
"x64"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"sunos"
@@ -605,7 +571,6 @@
"arm64"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"win32"
@@ -622,7 +587,6 @@
"ia32"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"win32"
@@ -639,7 +603,6 @@
"x64"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"win32"
@@ -653,7 +616,6 @@
"resolved": "https://registry.npmjs.org/@inquirer/ansi/-/ansi-1.0.2.tgz",
"integrity": "sha512-S8qNSZiYzFd0wAcyG5AXCvUHC5Sr7xpZ9wZ2py9XR88jUz8wooStVx5M6dRzczbBWjic9NP7+rY0Xi7qqK/aMQ==",
"dev": true,
- "license": "MIT",
"engines": {
"node": ">=18"
}
@@ -663,7 +625,6 @@
"resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-5.1.21.tgz",
"integrity": "sha512-KR8edRkIsUayMXV+o3Gv+q4jlhENF9nMYUZs9PA2HzrXeHI8M5uDag70U7RJn9yyiMZSbtF5/UexBtAVtZGSbQ==",
"dev": true,
- "license": "MIT",
"dependencies": {
"@inquirer/core": "^10.3.2",
"@inquirer/type": "^3.0.10"
@@ -685,7 +646,6 @@
"resolved": "https://registry.npmjs.org/@inquirer/core/-/core-10.3.2.tgz",
"integrity": "sha512-43RTuEbfP8MbKzedNqBrlhhNKVwoK//vUFNW3Q3vZ88BLcrs4kYpGg+B2mm5p2K/HfygoCxuKwJJiv8PbGmE0A==",
"dev": true,
- "license": "MIT",
"dependencies": {
"@inquirer/ansi": "^1.0.2",
"@inquirer/figures": "^1.0.15",
@@ -713,7 +673,6 @@
"resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.15.tgz",
"integrity": "sha512-t2IEY+unGHOzAaVM5Xx6DEWKeXlDDcNPeDyUpsRc6CUhBfU3VQOEl+Vssh7VNp1dR8MdUJBWhuObjXCsVpjN5g==",
"dev": true,
- "license": "MIT",
"engines": {
"node": ">=18"
}
@@ -723,7 +682,6 @@
"resolved": "https://registry.npmjs.org/@inquirer/type/-/type-3.0.10.tgz",
"integrity": "sha512-BvziSRxfz5Ov8ch0z/n3oijRSEcEsHnhggm4xFZe93DHcUCTlutlq9Ox4SVENAfcRD22UQq7T/atg9Wr3k09eA==",
"dev": true,
- "license": "MIT",
"engines": {
"node": ">=18"
},
@@ -741,7 +699,6 @@
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
"integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==",
"dev": true,
- "license": "MIT",
"dependencies": {
"@jridgewell/sourcemap-codec": "^1.5.0",
"@jridgewell/trace-mapping": "^0.3.24"
@@ -752,7 +709,6 @@
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
"integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
"dev": true,
- "license": "MIT",
"engines": {
"node": ">=6.0.0"
}
@@ -762,7 +718,6 @@
"resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.11.tgz",
"integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==",
"dev": true,
- "license": "MIT",
"dependencies": {
"@jridgewell/gen-mapping": "^0.3.5",
"@jridgewell/trace-mapping": "^0.3.25"
@@ -772,15 +727,13 @@
"version": "1.5.5",
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
"integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
- "dev": true,
- "license": "MIT"
+ "dev": true
},
"node_modules/@jridgewell/trace-mapping": {
"version": "0.3.31",
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz",
"integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==",
"dev": true,
- "license": "MIT",
"dependencies": {
"@jridgewell/resolve-uri": "^3.1.0",
"@jridgewell/sourcemap-codec": "^1.4.14"
@@ -791,7 +744,6 @@
"resolved": "https://registry.npmjs.org/@mswjs/interceptors/-/interceptors-0.39.8.tgz",
"integrity": "sha512-2+BzZbjRO7Ct61k8fMNHEtoKjeWI9pIlHFTqBwZ5icHpqszIgEZbjb1MW5Z0+bITTCTl3gk4PDBxs9tA/csXvA==",
"dev": true,
- "license": "MIT",
"dependencies": {
"@open-draft/deferred-promise": "^2.2.0",
"@open-draft/logger": "^0.3.0",
@@ -808,15 +760,13 @@
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/@open-draft/deferred-promise/-/deferred-promise-2.2.0.tgz",
"integrity": "sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA==",
- "dev": true,
- "license": "MIT"
+ "dev": true
},
"node_modules/@open-draft/logger": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/@open-draft/logger/-/logger-0.3.0.tgz",
"integrity": "sha512-X2g45fzhxH238HKO4xbSr7+wBS8Fvw6ixhTDuvLd5mqh6bJJCFAPwU9mPDxbcrRtfxv4u5IHCEH77BmxvXmmxQ==",
"dev": true,
- "license": "MIT",
"dependencies": {
"is-node-process": "^1.2.0",
"outvariant": "^1.4.0"
@@ -826,8 +776,7 @@
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/@open-draft/until/-/until-2.1.0.tgz",
"integrity": "sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg==",
- "dev": true,
- "license": "MIT"
+ "dev": true
},
"node_modules/@rollup/rollup-android-arm-eabi": {
"version": "4.53.5",
@@ -837,7 +786,6 @@
"arm"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"android"
@@ -851,7 +799,6 @@
"arm64"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"android"
@@ -865,7 +812,6 @@
"arm64"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"darwin"
@@ -879,7 +825,6 @@
"x64"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"darwin"
@@ -893,7 +838,6 @@
"arm64"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"freebsd"
@@ -907,7 +851,6 @@
"x64"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"freebsd"
@@ -921,7 +864,6 @@
"arm"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"linux"
@@ -935,7 +877,6 @@
"arm"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"linux"
@@ -949,7 +890,6 @@
"arm64"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"linux"
@@ -963,7 +903,6 @@
"arm64"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"linux"
@@ -977,7 +916,6 @@
"loong64"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"linux"
@@ -991,7 +929,6 @@
"ppc64"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"linux"
@@ -1005,7 +942,6 @@
"riscv64"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"linux"
@@ -1019,7 +955,6 @@
"riscv64"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"linux"
@@ -1033,7 +968,6 @@
"s390x"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"linux"
@@ -1047,7 +981,6 @@
"x64"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"linux"
@@ -1061,7 +994,6 @@
"x64"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"linux"
@@ -1075,7 +1007,6 @@
"arm64"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"openharmony"
@@ -1089,7 +1020,6 @@
"arm64"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"win32"
@@ -1103,7 +1033,6 @@
"ia32"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"win32"
@@ -1117,7 +1046,6 @@
"x64"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"win32"
@@ -1131,7 +1059,6 @@
"x64"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
"win32"
@@ -1142,7 +1069,6 @@
"resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz",
"integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==",
"dev": true,
- "license": "MIT",
"dependencies": {
"@types/deep-eql": "*",
"assertion-error": "^2.0.1"
@@ -1152,22 +1078,19 @@
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz",
"integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==",
- "dev": true,
- "license": "MIT"
+ "dev": true
},
"node_modules/@types/deep-eql": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz",
"integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==",
- "dev": true,
- "license": "MIT"
+ "dev": true
},
"node_modules/@types/eslint": {
"version": "9.6.1",
"resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz",
"integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==",
"dev": true,
- "license": "MIT",
"dependencies": {
"@types/estree": "*",
"@types/json-schema": "*"
@@ -1178,7 +1101,6 @@
"resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz",
"integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==",
"dev": true,
- "license": "MIT",
"dependencies": {
"@types/eslint": "*",
"@types/estree": "*"
@@ -1188,22 +1110,19 @@
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
"integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
- "dev": true,
- "license": "MIT"
+ "dev": true
},
"node_modules/@types/json-schema": {
"version": "7.0.15",
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
"integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
- "dev": true,
- "license": "MIT"
+ "dev": true
},
"node_modules/@types/node": {
"version": "18.19.130",
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.130.tgz",
"integrity": "sha512-GRaXQx6jGfL8sKfaIDD6OupbIHBr9jv7Jnaml9tB7l4v068PAOXqfcujMMo5PhbIs6ggR1XODELqahT2R8v0fg==",
"dev": true,
- "license": "MIT",
"dependencies": {
"undici-types": "~5.26.4"
}
@@ -1212,15 +1131,13 @@
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/@types/statuses/-/statuses-2.0.6.tgz",
"integrity": "sha512-xMAgYwceFhRA2zY+XbEA7mxYbA093wdiW8Vu6gZPGWy9cmOyU9XesH1tNcEWsKFd5Vzrqx5T3D38PWx1FIIXkA==",
- "dev": true,
- "license": "MIT"
+ "dev": true
},
"node_modules/@vitest/expect": {
"version": "3.2.4",
"resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.2.4.tgz",
"integrity": "sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==",
"dev": true,
- "license": "MIT",
"dependencies": {
"@types/chai": "^5.2.2",
"@vitest/spy": "3.2.4",
@@ -1237,7 +1154,6 @@
"resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.2.4.tgz",
"integrity": "sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==",
"dev": true,
- "license": "MIT",
"dependencies": {
"tinyrainbow": "^2.0.0"
},
@@ -1250,7 +1166,6 @@
"resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.2.4.tgz",
"integrity": "sha512-oukfKT9Mk41LreEW09vt45f8wx7DordoWUZMYdY/cyAk7w5TWkTRCNZYF7sX7n2wB7jyGAl74OxgwhPgKaqDMQ==",
"dev": true,
- "license": "MIT",
"dependencies": {
"@vitest/utils": "3.2.4",
"pathe": "^2.0.3",
@@ -1265,7 +1180,6 @@
"resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.2.4.tgz",
"integrity": "sha512-dEYtS7qQP2CjU27QBC5oUOxLE/v5eLkGqPE0ZKEIDGMs4vKWe7IjgLOeauHsR0D5YuuycGRO5oSRXnwnmA78fQ==",
"dev": true,
- "license": "MIT",
"dependencies": {
"@vitest/pretty-format": "3.2.4",
"magic-string": "^0.30.17",
@@ -1280,7 +1194,6 @@
"resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.2.4.tgz",
"integrity": "sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==",
"dev": true,
- "license": "MIT",
"dependencies": {
"tinyspy": "^4.0.3"
},
@@ -1293,7 +1206,6 @@
"resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.2.4.tgz",
"integrity": "sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==",
"dev": true,
- "license": "MIT",
"dependencies": {
"@vitest/pretty-format": "3.2.4",
"loupe": "^3.1.4",
@@ -1308,7 +1220,6 @@
"resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz",
"integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==",
"dev": true,
- "license": "MIT",
"dependencies": {
"@webassemblyjs/helper-numbers": "1.13.2",
"@webassemblyjs/helper-wasm-bytecode": "1.13.2"
@@ -1318,29 +1229,25 @@
"version": "1.13.2",
"resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz",
"integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==",
- "dev": true,
- "license": "MIT"
+ "dev": true
},
"node_modules/@webassemblyjs/helper-api-error": {
"version": "1.13.2",
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz",
"integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==",
- "dev": true,
- "license": "MIT"
+ "dev": true
},
"node_modules/@webassemblyjs/helper-buffer": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz",
"integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==",
- "dev": true,
- "license": "MIT"
+ "dev": true
},
"node_modules/@webassemblyjs/helper-numbers": {
"version": "1.13.2",
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz",
"integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==",
"dev": true,
- "license": "MIT",
"dependencies": {
"@webassemblyjs/floating-point-hex-parser": "1.13.2",
"@webassemblyjs/helper-api-error": "1.13.2",
@@ -1351,15 +1258,13 @@
"version": "1.13.2",
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz",
"integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==",
- "dev": true,
- "license": "MIT"
+ "dev": true
},
"node_modules/@webassemblyjs/helper-wasm-section": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz",
"integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==",
"dev": true,
- "license": "MIT",
"dependencies": {
"@webassemblyjs/ast": "1.14.1",
"@webassemblyjs/helper-buffer": "1.14.1",
@@ -1372,7 +1277,6 @@
"resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz",
"integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==",
"dev": true,
- "license": "MIT",
"dependencies": {
"@xtuc/ieee754": "^1.2.0"
}
@@ -1382,7 +1286,6 @@
"resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.13.2.tgz",
"integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==",
"dev": true,
- "license": "Apache-2.0",
"dependencies": {
"@xtuc/long": "4.2.2"
}
@@ -1391,15 +1294,13 @@
"version": "1.13.2",
"resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz",
"integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==",
- "dev": true,
- "license": "MIT"
+ "dev": true
},
"node_modules/@webassemblyjs/wasm-edit": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz",
"integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==",
"dev": true,
- "license": "MIT",
"dependencies": {
"@webassemblyjs/ast": "1.14.1",
"@webassemblyjs/helper-buffer": "1.14.1",
@@ -1416,7 +1317,6 @@
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz",
"integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==",
"dev": true,
- "license": "MIT",
"dependencies": {
"@webassemblyjs/ast": "1.14.1",
"@webassemblyjs/helper-wasm-bytecode": "1.13.2",
@@ -1430,7 +1330,6 @@
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz",
"integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==",
"dev": true,
- "license": "MIT",
"dependencies": {
"@webassemblyjs/ast": "1.14.1",
"@webassemblyjs/helper-buffer": "1.14.1",
@@ -1443,7 +1342,6 @@
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz",
"integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==",
"dev": true,
- "license": "MIT",
"dependencies": {
"@webassemblyjs/ast": "1.14.1",
"@webassemblyjs/helper-api-error": "1.13.2",
@@ -1458,7 +1356,6 @@
"resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz",
"integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==",
"dev": true,
- "license": "MIT",
"dependencies": {
"@webassemblyjs/ast": "1.14.1",
"@xtuc/long": "4.2.2"
@@ -1468,22 +1365,19 @@
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz",
"integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==",
- "dev": true,
- "license": "BSD-3-Clause"
+ "dev": true
},
"node_modules/@xtuc/long": {
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz",
"integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==",
- "dev": true,
- "license": "Apache-2.0"
+ "dev": true
},
"node_modules/acorn": {
"version": "8.15.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
"dev": true,
- "license": "MIT",
"bin": {
"acorn": "bin/acorn"
},
@@ -1496,7 +1390,6 @@
"resolved": "https://registry.npmjs.org/acorn-import-phases/-/acorn-import-phases-1.0.4.tgz",
"integrity": "sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==",
"dev": true,
- "license": "MIT",
"engines": {
"node": ">=10.13.0"
},
@@ -1509,7 +1402,6 @@
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz",
"integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
"dev": true,
- "license": "MIT",
"dependencies": {
"fast-deep-equal": "^3.1.3",
"fast-uri": "^3.0.1",
@@ -1526,7 +1418,6 @@
"resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz",
"integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==",
"dev": true,
- "license": "MIT",
"dependencies": {
"ajv": "^8.0.0"
},
@@ -1544,7 +1435,6 @@
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz",
"integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==",
"dev": true,
- "license": "MIT",
"dependencies": {
"fast-deep-equal": "^3.1.3"
},
@@ -1557,7 +1447,6 @@
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
"dev": true,
- "license": "MIT",
"engines": {
"node": ">=8"
}
@@ -1567,7 +1456,6 @@
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dev": true,
- "license": "MIT",
"dependencies": {
"color-convert": "^2.0.1"
},
@@ -1583,17 +1471,15 @@
"resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz",
"integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==",
"dev": true,
- "license": "MIT",
"engines": {
"node": ">=12"
}
},
"node_modules/baseline-browser-mapping": {
- "version": "2.9.8",
- "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.8.tgz",
- "integrity": "sha512-Y1fOuNDowLfgKOypdc9SPABfoWXuZHBOyCS4cD52IeZBhr4Md6CLLs6atcxVrzRmQ06E7hSlm5bHHApPKR/byA==",
+ "version": "2.9.11",
+ "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.11.tgz",
+ "integrity": "sha512-Sg0xJUNDU1sJNGdfGWhVHX0kkZ+HWcvmVymJbj6NSgZZmW/8S9Y2HQ5euytnIgakgxN6papOAWiwDo1ctFDcoQ==",
"dev": true,
- "license": "Apache-2.0",
"bin": {
"baseline-browser-mapping": "dist/cli.js"
}
@@ -1603,7 +1489,6 @@
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
"integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
"dev": true,
- "license": "MIT",
"dependencies": {
"fill-range": "^7.1.1"
},
@@ -1630,7 +1515,6 @@
"url": "https://github.com/sponsors/ai"
}
],
- "license": "MIT",
"dependencies": {
"baseline-browser-mapping": "^2.9.0",
"caniuse-lite": "^1.0.30001759",
@@ -1649,23 +1533,21 @@
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
- "dev": true,
- "license": "MIT"
+ "dev": true
},
"node_modules/cac": {
"version": "6.7.14",
"resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz",
"integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==",
"dev": true,
- "license": "MIT",
"engines": {
"node": ">=8"
}
},
"node_modules/caniuse-lite": {
- "version": "1.0.30001760",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001760.tgz",
- "integrity": "sha512-7AAMPcueWELt1p3mi13HR/LHH0TJLT11cnwDJEs3xA4+CK/PLKeO9Kl1oru24htkyUKtkGCvAx4ohB0Ttry8Dw==",
+ "version": "1.0.30001761",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001761.tgz",
+ "integrity": "sha512-JF9ptu1vP2coz98+5051jZ4PwQgd2ni8A+gYSN7EA7dPKIMf0pDlSUxhdmVOaV3/fYK5uWBkgSXJaRLr4+3A6g==",
"dev": true,
"funding": [
{
@@ -1680,15 +1562,13 @@
"type": "github",
"url": "https://github.com/sponsors/ai"
}
- ],
- "license": "CC-BY-4.0"
+ ]
},
"node_modules/chai": {
"version": "5.3.3",
"resolved": "https://registry.npmjs.org/chai/-/chai-5.3.3.tgz",
"integrity": "sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==",
"dev": true,
- "license": "MIT",
"dependencies": {
"assertion-error": "^2.0.1",
"check-error": "^2.1.1",
@@ -1705,7 +1585,6 @@
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
"dev": true,
- "license": "MIT",
"dependencies": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
@@ -1722,7 +1601,6 @@
"resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz",
"integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==",
"dev": true,
- "license": "MIT",
"engines": {
"node": ">= 16"
}
@@ -1732,7 +1610,6 @@
"resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz",
"integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==",
"dev": true,
- "license": "MIT",
"engines": {
"node": ">=6.0"
}
@@ -1742,7 +1619,6 @@
"resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz",
"integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==",
"dev": true,
- "license": "ISC",
"engines": {
"node": ">= 12"
}
@@ -1752,7 +1628,6 @@
"resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
"integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
"dev": true,
- "license": "ISC",
"dependencies": {
"string-width": "^4.2.0",
"strip-ansi": "^6.0.1",
@@ -1767,7 +1642,6 @@
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
"dev": true,
- "license": "MIT",
"dependencies": {
"ansi-styles": "^4.0.0",
"string-width": "^4.1.0",
@@ -1785,7 +1659,6 @@
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dev": true,
- "license": "MIT",
"dependencies": {
"color-name": "~1.1.4"
},
@@ -1797,22 +1670,19 @@
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
- "dev": true,
- "license": "MIT"
+ "dev": true
},
"node_modules/commander": {
"version": "2.20.3",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
- "dev": true,
- "license": "MIT"
+ "dev": true
},
"node_modules/cookie": {
"version": "0.7.2",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz",
"integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==",
"dev": true,
- "license": "MIT",
"engines": {
"node": ">= 0.6"
}
@@ -1822,7 +1692,6 @@
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
"integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
"dev": true,
- "license": "MIT",
"dependencies": {
"ms": "^2.1.3"
},
@@ -1840,7 +1709,6 @@
"resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz",
"integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==",
"dev": true,
- "license": "MIT",
"engines": {
"node": ">=6"
}
@@ -1849,22 +1717,19 @@
"version": "1.5.267",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.267.tgz",
"integrity": "sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw==",
- "dev": true,
- "license": "ISC"
+ "dev": true
},
"node_modules/emoji-regex": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
- "dev": true,
- "license": "MIT"
+ "dev": true
},
"node_modules/enhanced-resolve": {
"version": "5.18.4",
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.4.tgz",
"integrity": "sha512-LgQMM4WXU3QI+SYgEc2liRgznaD5ojbmY3sb8LxyguVkIg5FxdpTkvk72te2R38/TGKxH634oLxXRGY6d7AP+Q==",
"dev": true,
- "license": "MIT",
"dependencies": {
"graceful-fs": "^4.2.4",
"tapable": "^2.2.0"
@@ -1877,8 +1742,7 @@
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz",
"integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==",
- "dev": true,
- "license": "MIT"
+ "dev": true
},
"node_modules/esbuild": {
"version": "0.27.2",
@@ -1886,7 +1750,6 @@
"integrity": "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==",
"dev": true,
"hasInstallScript": true,
- "license": "MIT",
"bin": {
"esbuild": "bin/esbuild"
},
@@ -1927,7 +1790,6 @@
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
"integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
"dev": true,
- "license": "MIT",
"engines": {
"node": ">=6"
}
@@ -1937,7 +1799,6 @@
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
"integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
"dev": true,
- "license": "BSD-2-Clause",
"dependencies": {
"esrecurse": "^4.3.0",
"estraverse": "^4.1.1"
@@ -1951,7 +1812,6 @@
"resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
"integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
"dev": true,
- "license": "BSD-2-Clause",
"dependencies": {
"estraverse": "^5.2.0"
},
@@ -1964,7 +1824,6 @@
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
"integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
"dev": true,
- "license": "BSD-2-Clause",
"engines": {
"node": ">=4.0"
}
@@ -1974,7 +1833,6 @@
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
"integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
"dev": true,
- "license": "BSD-2-Clause",
"engines": {
"node": ">=4.0"
}
@@ -1984,7 +1842,6 @@
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz",
"integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==",
"dev": true,
- "license": "MIT",
"dependencies": {
"@types/estree": "^1.0.0"
}
@@ -1994,7 +1851,6 @@
"resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
"integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==",
"dev": true,
- "license": "MIT",
"engines": {
"node": ">=0.8.x"
}
@@ -2004,7 +1860,6 @@
"resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.3.0.tgz",
"integrity": "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==",
"dev": true,
- "license": "Apache-2.0",
"engines": {
"node": ">=12.0.0"
}
@@ -2013,8 +1868,7 @@
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
- "dev": true,
- "license": "MIT"
+ "dev": true
},
"node_modules/fast-uri": {
"version": "3.1.0",
@@ -2030,15 +1884,13 @@
"type": "opencollective",
"url": "https://opencollective.com/fastify"
}
- ],
- "license": "BSD-3-Clause"
+ ]
},
"node_modules/fill-range": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
"integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
"dev": true,
- "license": "MIT",
"dependencies": {
"to-regex-range": "^5.0.1"
},
@@ -2051,7 +1903,6 @@
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
"hasInstallScript": true,
- "license": "MIT",
"optional": true,
"os": [
"darwin"
@@ -2065,7 +1916,6 @@
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
"dev": true,
- "license": "ISC",
"engines": {
"node": "6.* || 8.* || >= 10.*"
}
@@ -2074,22 +1924,19 @@
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz",
"integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==",
- "dev": true,
- "license": "BSD-2-Clause"
+ "dev": true
},
"node_modules/graceful-fs": {
"version": "4.2.11",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
- "dev": true,
- "license": "ISC"
+ "dev": true
},
"node_modules/graphql": {
"version": "16.12.0",
"resolved": "https://registry.npmjs.org/graphql/-/graphql-16.12.0.tgz",
"integrity": "sha512-DKKrynuQRne0PNpEbzuEdHlYOMksHSUI8Zc9Unei5gTsMNA2/vMpoMz/yKba50pejK56qj98qM0SjYxAKi13gQ==",
"dev": true,
- "license": "MIT",
"engines": {
"node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0"
}
@@ -2099,7 +1946,6 @@
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
"dev": true,
- "license": "MIT",
"engines": {
"node": ">=8"
}
@@ -2108,15 +1954,13 @@
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/headers-polyfill/-/headers-polyfill-4.0.3.tgz",
"integrity": "sha512-IScLbePpkvO846sIwOtOTDjutRMWdXdJmXdMvk6gCBHxFO8d+QKOQedyZSxFTTFYRSmlgSTDtXqqq4pcenBXLQ==",
- "dev": true,
- "license": "MIT"
+ "dev": true
},
"node_modules/is-fullwidth-code-point": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
"dev": true,
- "license": "MIT",
"engines": {
"node": ">=8"
}
@@ -2125,15 +1969,13 @@
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/is-node-process/-/is-node-process-1.2.0.tgz",
"integrity": "sha512-Vg4o6/fqPxIjtxgUH5QLJhwZ7gW5diGCVlXpuUfELC62CuxM1iHcRe51f2W1FDy04Ai4KJkagKjx3XaqyfRKXw==",
- "dev": true,
- "license": "MIT"
+ "dev": true
},
"node_modules/is-number": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
"dev": true,
- "license": "MIT",
"engines": {
"node": ">=0.12.0"
}
@@ -2143,7 +1985,6 @@
"resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz",
"integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==",
"dev": true,
- "license": "MIT",
"dependencies": {
"@types/node": "*",
"merge-stream": "^2.0.0",
@@ -2158,7 +1999,6 @@
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
"integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
"dev": true,
- "license": "MIT",
"dependencies": {
"has-flag": "^4.0.0"
},
@@ -2173,29 +2013,25 @@
"version": "9.0.1",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.1.tgz",
"integrity": "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==",
- "dev": true,
- "license": "MIT"
+ "dev": true
},
"node_modules/json-parse-even-better-errors": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
"integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==",
- "dev": true,
- "license": "MIT"
+ "dev": true
},
"node_modules/json-schema-traverse": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
- "dev": true,
- "license": "MIT"
+ "dev": true
},
"node_modules/loader-runner": {
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.1.tgz",
"integrity": "sha512-IWqP2SCPhyVFTBtRcgMHdzlf9ul25NwaFx4wCEH/KjAXuuHY4yNjvPXsBokp8jCB936PyWRaPKUNh8NvylLp2Q==",
"dev": true,
- "license": "MIT",
"engines": {
"node": ">=6.11.5"
},
@@ -2208,15 +2044,13 @@
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/loupe/-/loupe-3.2.1.tgz",
"integrity": "sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==",
- "dev": true,
- "license": "MIT"
+ "dev": true
},
"node_modules/magic-string": {
"version": "0.30.21",
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz",
"integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==",
"dev": true,
- "license": "MIT",
"dependencies": {
"@jridgewell/sourcemap-codec": "^1.5.5"
}
@@ -2225,15 +2059,13 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
"integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
- "dev": true,
- "license": "MIT"
+ "dev": true
},
"node_modules/micromatch": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
"integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
"dev": true,
- "license": "MIT",
"dependencies": {
"braces": "^3.0.3",
"picomatch": "^2.3.1"
@@ -2247,7 +2079,6 @@
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
"dev": true,
- "license": "MIT",
"engines": {
"node": ">= 0.6"
}
@@ -2257,7 +2088,6 @@
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
"dev": true,
- "license": "MIT",
"dependencies": {
"mime-db": "1.52.0"
},
@@ -2269,8 +2099,7 @@
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
- "dev": true,
- "license": "MIT"
+ "dev": true
},
"node_modules/msw": {
"version": "2.11.2",
@@ -2278,7 +2107,6 @@
"integrity": "sha512-MI54hLCsrMwiflkcqlgYYNJJddY5/+S0SnONvhv1owOplvqohKSQyGejpNdUGyCwgs4IH7PqaNbPw/sKOEze9Q==",
"dev": true,
"hasInstallScript": true,
- "license": "MIT",
"dependencies": {
"@bundled-es-modules/cookie": "^2.0.1",
"@bundled-es-modules/statuses": "^1.0.1",
@@ -2323,7 +2151,6 @@
"resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-2.0.0.tgz",
"integrity": "sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==",
"dev": true,
- "license": "ISC",
"engines": {
"node": "^18.17.0 || >=20.5.0"
}
@@ -2339,7 +2166,6 @@
"url": "https://github.com/sponsors/ai"
}
],
- "license": "MIT",
"bin": {
"nanoid": "bin/nanoid.cjs"
},
@@ -2351,43 +2177,37 @@
"version": "2.6.2",
"resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
"integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
- "dev": true,
- "license": "MIT"
+ "dev": true
},
"node_modules/node-releases": {
"version": "2.0.27",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz",
"integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==",
- "dev": true,
- "license": "MIT"
+ "dev": true
},
"node_modules/outvariant": {
"version": "1.4.3",
"resolved": "https://registry.npmjs.org/outvariant/-/outvariant-1.4.3.tgz",
"integrity": "sha512-+Sl2UErvtsoajRDKCE5/dBz4DIvHXQQnAxtQTF04OJxY0+DyZXSo5P5Bb7XYWOh81syohlYL24hbDwxedPUJCA==",
- "dev": true,
- "license": "MIT"
+ "dev": true
},
"node_modules/path-to-regexp": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz",
"integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==",
- "dev": true,
- "license": "MIT"
+ "dev": true
},
"node_modules/pathe": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz",
"integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==",
- "dev": true,
- "license": "MIT"
+ "dev": true
},
"node_modules/pathval": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.1.tgz",
"integrity": "sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==",
"dev": true,
- "license": "MIT",
"engines": {
"node": ">= 14.16"
}
@@ -2396,15 +2216,13 @@
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
"integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
- "dev": true,
- "license": "ISC"
+ "dev": true
},
"node_modules/picomatch": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
"dev": true,
- "license": "MIT",
"engines": {
"node": ">=8.6"
},
@@ -2416,7 +2234,6 @@
"version": "1.57.0",
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.57.0.tgz",
"integrity": "sha512-ilYQj1s8sr2ppEJ2YVadYBN0Mb3mdo9J0wQ+UuDhzYqURwSoW4n1Xs5vs7ORwgDGmyEh33tRMeS8KhdkMoLXQw==",
- "license": "Apache-2.0",
"dependencies": {
"playwright-core": "1.57.0"
},
@@ -2434,7 +2251,6 @@
"version": "1.57.0",
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.57.0.tgz",
"integrity": "sha512-agTcKlMw/mjBWOnD6kFZttAAGHgi/Nw0CZ2o6JqWSbMlI219lAFLZZCyqByTsvVAJq5XA5H8cA6PrvBRpBWEuQ==",
- "license": "Apache-2.0",
"bin": {
"playwright-core": "cli.js"
},
@@ -2461,7 +2277,6 @@
"url": "https://github.com/sponsors/ai"
}
],
- "license": "MIT",
"dependencies": {
"nanoid": "^3.3.11",
"picocolors": "^1.1.1",
@@ -2476,7 +2291,6 @@
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
"integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
"dev": true,
- "license": "MIT",
"dependencies": {
"safe-buffer": "^5.1.0"
}
@@ -2486,7 +2300,6 @@
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
"integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
"dev": true,
- "license": "MIT",
"engines": {
"node": ">=0.10.0"
}
@@ -2496,7 +2309,6 @@
"resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
"integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
"dev": true,
- "license": "MIT",
"engines": {
"node": ">=0.10.0"
}
@@ -2505,15 +2317,13 @@
"version": "0.7.0",
"resolved": "https://registry.npmjs.org/rettime/-/rettime-0.7.0.tgz",
"integrity": "sha512-LPRKoHnLKd/r3dVxcwO7vhCW+orkOGj9ViueosEBK6ie89CijnfRlhaDhHq/3Hxu4CkWQtxwlBG0mzTQY6uQjw==",
- "dev": true,
- "license": "MIT"
+ "dev": true
},
"node_modules/rollup": {
"version": "4.53.5",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.53.5.tgz",
"integrity": "sha512-iTNAbFSlRpcHeeWu73ywU/8KuU/LZmNCSxp6fjQkJBD3ivUb8tpDrXhIxEzA05HlYMEwmtaUnb3RP+YNv162OQ==",
"dev": true,
- "license": "MIT",
"dependencies": {
"@types/estree": "1.0.8"
},
@@ -2568,15 +2378,13 @@
"type": "consulting",
"url": "https://feross.org/support"
}
- ],
- "license": "MIT"
+ ]
},
"node_modules/schema-utils": {
"version": "4.3.3",
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.3.tgz",
"integrity": "sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==",
"dev": true,
- "license": "MIT",
"dependencies": {
"@types/json-schema": "^7.0.9",
"ajv": "^8.9.0",
@@ -2596,7 +2404,6 @@
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz",
"integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==",
"dev": true,
- "license": "ISC",
"bin": {
"semver": "bin/semver.js"
},
@@ -2609,7 +2416,6 @@
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz",
"integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==",
"dev": true,
- "license": "BSD-3-Clause",
"dependencies": {
"randombytes": "^2.1.0"
}
@@ -2618,15 +2424,13 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz",
"integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==",
- "dev": true,
- "license": "ISC"
+ "dev": true
},
"node_modules/signal-exit": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
"integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
"dev": true,
- "license": "ISC",
"engines": {
"node": ">=14"
},
@@ -2639,7 +2443,6 @@
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz",
"integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==",
"dev": true,
- "license": "BSD-3-Clause",
"engines": {
"node": ">= 12"
}
@@ -2649,7 +2452,6 @@
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
"integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
"dev": true,
- "license": "BSD-3-Clause",
"engines": {
"node": ">=0.10.0"
}
@@ -2659,7 +2461,6 @@
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
"integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
"dev": true,
- "license": "MIT",
"dependencies": {
"buffer-from": "^1.0.0",
"source-map": "^0.6.0"
@@ -2670,7 +2471,6 @@
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
"dev": true,
- "license": "BSD-3-Clause",
"engines": {
"node": ">=0.10.0"
}
@@ -2679,15 +2479,13 @@
"version": "0.0.2",
"resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz",
"integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==",
- "dev": true,
- "license": "MIT"
+ "dev": true
},
"node_modules/statuses": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz",
"integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==",
"dev": true,
- "license": "MIT",
"engines": {
"node": ">= 0.8"
}
@@ -2696,22 +2494,19 @@
"version": "3.10.0",
"resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz",
"integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==",
- "dev": true,
- "license": "MIT"
+ "dev": true
},
"node_modules/strict-event-emitter": {
"version": "0.5.1",
"resolved": "https://registry.npmjs.org/strict-event-emitter/-/strict-event-emitter-0.5.1.tgz",
"integrity": "sha512-vMgjE/GGEPEFnhFub6pa4FmJBRBVOLpIII2hvCZ8Kzb7K0hlHo7mQv6xYrBvCL2LtAIBwFUK8wvuJgTVSQ5MFQ==",
- "dev": true,
- "license": "MIT"
+ "dev": true
},
"node_modules/string-width": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
"dev": true,
- "license": "MIT",
"dependencies": {
"emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0",
@@ -2726,7 +2521,6 @@
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
"dev": true,
- "license": "MIT",
"dependencies": {
"ansi-regex": "^5.0.1"
},
@@ -2739,7 +2533,6 @@
"resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-3.1.0.tgz",
"integrity": "sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg==",
"dev": true,
- "license": "MIT",
"dependencies": {
"js-tokens": "^9.0.1"
},
@@ -2752,7 +2545,6 @@
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"dev": true,
- "license": "MIT",
"dependencies": {
"has-flag": "^4.0.0"
},
@@ -2765,7 +2557,6 @@
"resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz",
"integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==",
"dev": true,
- "license": "MIT",
"engines": {
"node": ">=6"
},
@@ -2779,7 +2570,6 @@
"resolved": "https://registry.npmjs.org/terser/-/terser-5.44.1.tgz",
"integrity": "sha512-t/R3R/n0MSwnnazuPpPNVO60LX0SKL45pyl9YlvxIdkH0Of7D5qM2EVe+yASRIlY5pZ73nclYJfNANGWPwFDZw==",
"dev": true,
- "license": "BSD-2-Clause",
"dependencies": {
"@jridgewell/source-map": "^0.3.3",
"acorn": "^8.15.0",
@@ -2798,7 +2588,6 @@
"resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.16.tgz",
"integrity": "sha512-h9oBFCWrq78NyWWVcSwZarJkZ01c2AyGrzs1crmHZO3QUg9D61Wu4NPjBy69n7JqylFF5y+CsUZYmYEIZ3mR+Q==",
"dev": true,
- "license": "MIT",
"dependencies": {
"@jridgewell/trace-mapping": "^0.3.25",
"jest-worker": "^27.4.5",
@@ -2832,22 +2621,19 @@
"version": "2.9.0",
"resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz",
"integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==",
- "dev": true,
- "license": "MIT"
+ "dev": true
},
"node_modules/tinyexec": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz",
"integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==",
- "dev": true,
- "license": "MIT"
+ "dev": true
},
"node_modules/tinyglobby": {
"version": "0.2.15",
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz",
"integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==",
"dev": true,
- "license": "MIT",
"dependencies": {
"fdir": "^6.5.0",
"picomatch": "^4.0.3"
@@ -2864,7 +2650,6 @@
"resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
"integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
"dev": true,
- "license": "MIT",
"engines": {
"node": ">=12.0.0"
},
@@ -2882,7 +2667,6 @@
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
"dev": true,
- "license": "MIT",
"engines": {
"node": ">=12"
},
@@ -2895,7 +2679,6 @@
"resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.1.1.tgz",
"integrity": "sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==",
"dev": true,
- "license": "MIT",
"engines": {
"node": "^18.0.0 || >=20.0.0"
}
@@ -2905,7 +2688,6 @@
"resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-2.0.0.tgz",
"integrity": "sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==",
"dev": true,
- "license": "MIT",
"engines": {
"node": ">=14.0.0"
}
@@ -2915,7 +2697,6 @@
"resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-4.0.4.tgz",
"integrity": "sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q==",
"dev": true,
- "license": "MIT",
"engines": {
"node": ">=14.0.0"
}
@@ -2925,7 +2706,6 @@
"resolved": "https://registry.npmjs.org/tldts/-/tldts-7.0.19.tgz",
"integrity": "sha512-8PWx8tvC4jDB39BQw1m4x8y5MH1BcQ5xHeL2n7UVFulMPH/3Q0uiamahFJ3lXA0zO2SUyRXuVVbWSDmstlt9YA==",
"dev": true,
- "license": "MIT",
"dependencies": {
"tldts-core": "^7.0.19"
},
@@ -2937,15 +2717,13 @@
"version": "7.0.19",
"resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-7.0.19.tgz",
"integrity": "sha512-lJX2dEWx0SGH4O6p+7FPwYmJ/bu1JbcGJ8RLaG9b7liIgZ85itUVEPbMtWRVrde/0fnDPEPHW10ZsKW3kVsE9A==",
- "dev": true,
- "license": "MIT"
+ "dev": true
},
"node_modules/to-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
"dev": true,
- "license": "MIT",
"dependencies": {
"is-number": "^7.0.0"
},
@@ -2958,7 +2736,6 @@
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-6.0.0.tgz",
"integrity": "sha512-kXuRi1mtaKMrsLUxz3sQYvVl37B0Ns6MzfrtV5DvJceE9bPyspOqk9xxv7XbZWcfLWbFmm997vl83qUWVJA64w==",
"dev": true,
- "license": "BSD-3-Clause",
"dependencies": {
"tldts": "^7.0.5"
},
@@ -2971,7 +2748,6 @@
"resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.5.4.tgz",
"integrity": "sha512-nCz0rEwunlTZiy6rXFByQU1kVVpCIgUpc/psFiKVrUwrizdnIbRFu8w7bxhUF0X613DYwT4XzrZHpVyMe758hQ==",
"dev": true,
- "license": "MIT",
"dependencies": {
"chalk": "^4.1.0",
"enhanced-resolve": "^5.0.0",
@@ -2992,7 +2768,6 @@
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz",
"integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==",
"dev": true,
- "license": "(MIT OR CC0-1.0)",
"engines": {
"node": ">=16"
},
@@ -3005,7 +2780,6 @@
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz",
"integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==",
"dev": true,
- "license": "Apache-2.0",
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
@@ -3018,8 +2792,7 @@
"version": "5.26.5",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
- "dev": true,
- "license": "MIT"
+ "dev": true
},
"node_modules/update-browserslist-db": {
"version": "1.2.3",
@@ -3040,7 +2813,6 @@
"url": "https://github.com/sponsors/ai"
}
],
- "license": "MIT",
"dependencies": {
"escalade": "^3.2.0",
"picocolors": "^1.1.1"
@@ -3057,7 +2829,6 @@
"resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.2.4.tgz",
"integrity": "sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==",
"dev": true,
- "license": "MIT",
"dependencies": {
"cac": "^6.7.14",
"debug": "^4.4.1",
@@ -3080,7 +2851,6 @@
"resolved": "https://registry.npmjs.org/@types/node/-/node-25.0.3.tgz",
"integrity": "sha512-W609buLVRVmeW693xKfzHeIV6nJGGz98uCPfeXI1ELMLXVeKYZ9m15fAMSaUPBHYLGFsVRcMmSCksQOrZV9BYA==",
"dev": true,
- "license": "MIT",
"optional": true,
"peer": true,
"dependencies": {
@@ -3092,7 +2862,6 @@
"resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
"integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
"dev": true,
- "license": "MIT",
"engines": {
"node": ">=12.0.0"
},
@@ -3111,7 +2880,6 @@
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
"dev": true,
"hasInstallScript": true,
- "license": "MIT",
"optional": true,
"os": [
"darwin"
@@ -3125,7 +2893,6 @@
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
"dev": true,
- "license": "MIT",
"engines": {
"node": ">=12"
},
@@ -3138,7 +2905,6 @@
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz",
"integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==",
"dev": true,
- "license": "MIT",
"optional": true,
"peer": true
},
@@ -3147,7 +2913,6 @@
"resolved": "https://registry.npmjs.org/vite/-/vite-7.3.0.tgz",
"integrity": "sha512-dZwN5L1VlUBewiP6H9s2+B3e3Jg96D0vzN+Ry73sOefebhYr9f94wwkMNN/9ouoU8pV1BqA1d1zGk8928cx0rg==",
"dev": true,
- "license": "MIT",
"dependencies": {
"esbuild": "^0.27.0",
"fdir": "^6.5.0",
@@ -3222,7 +2987,6 @@
"resolved": "https://registry.npmjs.org/vitest/-/vitest-3.2.4.tgz",
"integrity": "sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==",
"dev": true,
- "license": "MIT",
"dependencies": {
"@types/chai": "^5.2.2",
"@vitest/expect": "3.2.4",
@@ -3295,7 +3059,6 @@
"resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.2.4.tgz",
"integrity": "sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ==",
"dev": true,
- "license": "MIT",
"dependencies": {
"@vitest/spy": "3.2.4",
"estree-walker": "^3.0.3",
@@ -3322,7 +3085,6 @@
"resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
"integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
"dev": true,
- "license": "MIT",
"engines": {
"node": ">=12.0.0"
},
@@ -3341,7 +3103,6 @@
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
"dev": true,
"hasInstallScript": true,
- "license": "MIT",
"optional": true,
"os": [
"darwin"
@@ -3355,7 +3116,6 @@
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
"dev": true,
- "license": "MIT",
"engines": {
"node": ">=12"
},
@@ -3368,7 +3128,6 @@
"resolved": "https://registry.npmjs.org/vite/-/vite-7.3.0.tgz",
"integrity": "sha512-dZwN5L1VlUBewiP6H9s2+B3e3Jg96D0vzN+Ry73sOefebhYr9f94wwkMNN/9ouoU8pV1BqA1d1zGk8928cx0rg==",
"dev": true,
- "license": "MIT",
"dependencies": {
"esbuild": "^0.27.0",
"fdir": "^6.5.0",
@@ -3443,7 +3202,6 @@
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.4.tgz",
"integrity": "sha512-c5EGNOiyxxV5qmTtAB7rbiXxi1ooX1pQKMLX/MIabJjRA0SJBQOjKF+KSVfHkr9U1cADPon0mRiVe/riyaiDUA==",
"dev": true,
- "license": "MIT",
"dependencies": {
"glob-to-regexp": "^0.4.1",
"graceful-fs": "^4.1.2"
@@ -3453,11 +3211,10 @@
}
},
"node_modules/webpack": {
- "version": "5.104.0",
- "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.104.0.tgz",
- "integrity": "sha512-5DeICTX8BVgNp6afSPYXAFjskIgWGlygQH58bcozPOXgo2r/6xx39Y1+cULZ3gTxUYQP88jmwLj2anu4Xaq84g==",
+ "version": "5.104.1",
+ "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.104.1.tgz",
+ "integrity": "sha512-Qphch25abbMNtekmEGJmeRUhLDbe+QfiWTiqpKYkpCOWY64v9eyl+KRRLmqOFA2AvKPpc9DC6+u2n76tQLBoaA==",
"dev": true,
- "license": "MIT",
"dependencies": {
"@types/eslint-scope": "^3.7.7",
"@types/estree": "^1.0.8",
@@ -3506,7 +3263,6 @@
"resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.3.3.tgz",
"integrity": "sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg==",
"dev": true,
- "license": "MIT",
"engines": {
"node": ">=10.13.0"
}
@@ -3515,15 +3271,13 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.0.0.tgz",
"integrity": "sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==",
- "dev": true,
- "license": "MIT"
+ "dev": true
},
"node_modules/why-is-node-running": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz",
"integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==",
"dev": true,
- "license": "MIT",
"dependencies": {
"siginfo": "^2.0.0",
"stackback": "0.0.2"
@@ -3540,7 +3294,6 @@
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
"integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
"dev": true,
- "license": "MIT",
"dependencies": {
"ansi-styles": "^4.0.0",
"string-width": "^4.1.0",
@@ -3555,7 +3308,6 @@
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
"integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
"dev": true,
- "license": "ISC",
"engines": {
"node": ">=10"
}
@@ -3565,7 +3317,6 @@
"resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
"integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
"dev": true,
- "license": "MIT",
"dependencies": {
"cliui": "^8.0.1",
"escalade": "^3.1.1",
@@ -3584,7 +3335,6 @@
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
"integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
"dev": true,
- "license": "ISC",
"engines": {
"node": ">=12"
}
@@ -3594,7 +3344,6 @@
"resolved": "https://registry.npmjs.org/yoctocolors-cjs/-/yoctocolors-cjs-2.1.3.tgz",
"integrity": "sha512-U/PBtDf35ff0D8X8D0jfdzHYEPFxAI7jJlxZXwCSez5M3190m+QobIfh+sWDWSHMCWWJN2AWamkegn6vr6YBTw==",
"dev": true,
- "license": "MIT",
"engines": {
"node": ">=18"
},
diff --git a/skyvern-ts/client/package.json b/skyvern-ts/client/package.json
index e0b94a25..27f0dca5 100644
--- a/skyvern-ts/client/package.json
+++ b/skyvern-ts/client/package.json
@@ -1,6 +1,6 @@
{
"name": "@skyvern/client",
- "version": "1.0.3",
+ "version": "1.0.6",
"private": false,
"repository": {
"type": "git",
diff --git a/skyvern-ts/client/reference.md b/skyvern-ts/client/reference.md
index 8129a6a9..133f9410 100644
--- a/skyvern-ts/client/reference.md
+++ b/skyvern-ts/client/reference.md
@@ -68,83 +68,6 @@ await client.runSdkAction({
##
-## Workflows
-client.workflows.setWorkflowTemplateStatus(workflowPermanentId, { ...params }) -> Record
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-Set or unset a workflow as a template.
-
-Template status is stored at the workflow_permanent_id level (not per-version),
-meaning all versions of a workflow share the same template status.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```typescript
-await client.workflows.setWorkflowTemplateStatus("workflow_permanent_id", {
- is_template: true
-});
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**workflowPermanentId:** `string`
-
-
-
-
-
--
-
-**request:** `Skyvern.SetWorkflowTemplateStatusV1WorkflowsWorkflowPermanentIdTemplatePutRequest`
-
-
-
-
-
--
-
-**requestOptions:** `Workflows.RequestOptions`
-
-
-
-
-
-
-
-
-
-
-
## Scripts
client.scripts.runScript(scriptId) -> unknown
diff --git a/skyvern-ts/client/src/Client.ts b/skyvern-ts/client/src/Client.ts
index e1cb84e0..83ab354d 100644
--- a/skyvern-ts/client/src/Client.ts
+++ b/skyvern-ts/client/src/Client.ts
@@ -2,7 +2,6 @@
import * as Skyvern from "./api/index.js";
import { Scripts } from "./api/resources/scripts/client/Client.js";
-import { Workflows } from "./api/resources/workflows/client/Client.js";
import type { BaseClientOptions, BaseRequestOptions } from "./BaseClient.js";
import { mergeHeaders, mergeOnlyDefinedHeaders } from "./core/headers.js";
import * as core from "./core/index.js";
@@ -17,7 +16,6 @@ export declare namespace SkyvernClient {
export class SkyvernClient {
protected readonly _options: SkyvernClient.Options;
- protected _workflows: Workflows | undefined;
protected _scripts: Scripts | undefined;
constructor(_options: SkyvernClient.Options = {}) {
@@ -28,8 +26,8 @@ export class SkyvernClient {
"x-api-key": _options?.apiKey,
"X-Fern-Language": "JavaScript",
"X-Fern-SDK-Name": "@skyvern/client",
- "X-Fern-SDK-Version": "1.0.3",
- "User-Agent": "@skyvern/client/1.0.3",
+ "X-Fern-SDK-Version": "1.0.6",
+ "User-Agent": "@skyvern/client/1.0.6",
"X-Fern-Runtime": core.RUNTIME.type,
"X-Fern-Runtime-Version": core.RUNTIME.version,
},
@@ -38,10 +36,6 @@ export class SkyvernClient {
};
}
- public get workflows(): Workflows {
- return (this._workflows ??= new Workflows(this._options));
- }
-
public get scripts(): Scripts {
return (this._scripts ??= new Scripts(this._options));
}
@@ -948,6 +942,7 @@ export class SkyvernClient {
* Retry sending the webhook for a run
*
* @param {string} runId - The id of the task run or the workflow run.
+ * @param {Skyvern.RetryRunWebhookRequest} request
* @param {SkyvernClient.RequestOptions} requestOptions - Request-specific configuration.
*
* @throws {@link Skyvern.UnprocessableEntityError}
@@ -957,13 +952,15 @@ export class SkyvernClient {
*/
public retryRunWebhook(
runId: string,
+ request?: Skyvern.RetryRunWebhookRequest,
requestOptions?: SkyvernClient.RequestOptions,
): core.HttpResponsePromise {
- return core.HttpResponsePromise.fromPromise(this.__retryRunWebhook(runId, requestOptions));
+ return core.HttpResponsePromise.fromPromise(this.__retryRunWebhook(runId, request, requestOptions));
}
private async __retryRunWebhook(
runId: string,
+ request?: Skyvern.RetryRunWebhookRequest,
requestOptions?: SkyvernClient.RequestOptions,
): Promise> {
const _headers: core.Fetcher.Args["headers"] = mergeHeaders(
@@ -980,7 +977,10 @@ export class SkyvernClient {
),
method: "POST",
headers: _headers,
+ contentType: "application/json",
queryParameters: requestOptions?.queryParams,
+ requestType: "json",
+ body: request != null ? request : undefined,
timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 60) * 1000,
maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries,
abortSignal: requestOptions?.abortSignal,
@@ -1102,6 +1102,91 @@ export class SkyvernClient {
}
}
+ /**
+ * @param {Skyvern.BodyUploadFileV1UploadFilePost} request
+ * @param {SkyvernClient.RequestOptions} requestOptions - Request-specific configuration.
+ *
+ * @throws {@link Skyvern.UnprocessableEntityError}
+ *
+ * @example
+ * import { createReadStream } from "fs";
+ * await client.uploadFile({
+ * file: fs.createReadStream("/path/to/your/file")
+ * })
+ */
+ public uploadFile(
+ request: Skyvern.BodyUploadFileV1UploadFilePost,
+ requestOptions?: SkyvernClient.RequestOptions,
+ ): core.HttpResponsePromise {
+ return core.HttpResponsePromise.fromPromise(this.__uploadFile(request, requestOptions));
+ }
+
+ private async __uploadFile(
+ request: Skyvern.BodyUploadFileV1UploadFilePost,
+ requestOptions?: SkyvernClient.RequestOptions,
+ ): Promise> {
+ const _request = await core.newFormData();
+ await _request.appendFile("file", request.file);
+ const _maybeEncodedRequest = await _request.getRequest();
+ const _headers: core.Fetcher.Args["headers"] = mergeHeaders(
+ this._options?.headers,
+ mergeOnlyDefinedHeaders({
+ "x-api-key": requestOptions?.apiKey ?? this._options?.apiKey,
+ ..._maybeEncodedRequest.headers,
+ }),
+ requestOptions?.headers,
+ );
+ const _response = await core.fetcher({
+ url: core.url.join(
+ (await core.Supplier.get(this._options.baseUrl)) ??
+ (await core.Supplier.get(this._options.environment)) ??
+ environments.SkyvernEnvironment.Cloud,
+ "v1/upload_file",
+ ),
+ method: "POST",
+ headers: _headers,
+ queryParameters: requestOptions?.queryParams,
+ requestType: "file",
+ duplex: _maybeEncodedRequest.duplex,
+ body: _maybeEncodedRequest.body,
+ timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 60) * 1000,
+ maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries,
+ abortSignal: requestOptions?.abortSignal,
+ });
+ if (_response.ok) {
+ return { data: _response.body as Skyvern.UploadFileResponse, rawResponse: _response.rawResponse };
+ }
+
+ if (_response.error.reason === "status-code") {
+ switch (_response.error.statusCode) {
+ case 422:
+ throw new Skyvern.UnprocessableEntityError(_response.error.body as unknown, _response.rawResponse);
+ default:
+ throw new errors.SkyvernError({
+ statusCode: _response.error.statusCode,
+ body: _response.error.body,
+ rawResponse: _response.rawResponse,
+ });
+ }
+ }
+
+ switch (_response.error.reason) {
+ case "non-json":
+ throw new errors.SkyvernError({
+ statusCode: _response.error.statusCode,
+ body: _response.error.rawBody,
+ rawResponse: _response.rawResponse,
+ });
+ case "timeout":
+ throw new errors.SkyvernTimeoutError("Timeout exceeded when calling POST /v1/upload_file.");
+ case "unknown":
+ throw new errors.SkyvernError({
+ message: _response.error.errorMessage,
+ rawResponse: _response.rawResponse,
+ });
+ }
+ }
+
/**
* Get all browser profiles for the organization
*
diff --git a/skyvern-ts/client/src/api/client/requests/BodyUploadFileV1UploadFilePost.ts b/skyvern-ts/client/src/api/client/requests/BodyUploadFileV1UploadFilePost.ts
new file mode 100644
index 00000000..8264af6c
--- /dev/null
+++ b/skyvern-ts/client/src/api/client/requests/BodyUploadFileV1UploadFilePost.ts
@@ -0,0 +1,13 @@
+// This file was auto-generated by Fern from our API Definition.
+
+import type * as core from "../../../core/index.js";
+
+/**
+ * @example
+ * {
+ * file: fs.createReadStream("/path/to/your/file")
+ * }
+ */
+export interface BodyUploadFileV1UploadFilePost {
+ file: core.file.Uploadable;
+}
diff --git a/skyvern-ts/client/src/api/client/requests/index.ts b/skyvern-ts/client/src/api/client/requests/index.ts
index 0e1cb35d..5215a6e3 100644
--- a/skyvern-ts/client/src/api/client/requests/index.ts
+++ b/skyvern-ts/client/src/api/client/requests/index.ts
@@ -1,3 +1,4 @@
+export type { BodyUploadFileV1UploadFilePost } from "./BodyUploadFileV1UploadFilePost.js";
export type { CreateBrowserProfileRequest } from "./CreateBrowserProfileRequest.js";
export type { CreateBrowserSessionRequest } from "./CreateBrowserSessionRequest.js";
export type { CreateCredentialRequest } from "./CreateCredentialRequest.js";
diff --git a/skyvern-ts/client/src/api/resources/index.ts b/skyvern-ts/client/src/api/resources/index.ts
index 9852fa96..7c69f0c4 100644
--- a/skyvern-ts/client/src/api/resources/index.ts
+++ b/skyvern-ts/client/src/api/resources/index.ts
@@ -1,3 +1 @@
export * as scripts from "./scripts/index.js";
-export * from "./workflows/client/requests/index.js";
-export * as workflows from "./workflows/index.js";
diff --git a/skyvern-ts/client/src/api/resources/workflows/client/Client.ts b/skyvern-ts/client/src/api/resources/workflows/client/Client.ts
deleted file mode 100644
index 7b14e6da..00000000
--- a/skyvern-ts/client/src/api/resources/workflows/client/Client.ts
+++ /dev/null
@@ -1,112 +0,0 @@
-// This file was auto-generated by Fern from our API Definition.
-
-import type { BaseClientOptions, BaseRequestOptions } from "../../../../BaseClient.js";
-import { mergeHeaders, mergeOnlyDefinedHeaders } from "../../../../core/headers.js";
-import * as core from "../../../../core/index.js";
-import * as environments from "../../../../environments.js";
-import * as errors from "../../../../errors/index.js";
-import * as Skyvern from "../../../index.js";
-
-export declare namespace Workflows {
- export interface Options extends BaseClientOptions {}
-
- export interface RequestOptions extends BaseRequestOptions {}
-}
-
-export class Workflows {
- protected readonly _options: Workflows.Options;
-
- constructor(_options: Workflows.Options = {}) {
- this._options = _options;
- }
-
- /**
- * Set or unset a workflow as a template.
- *
- * Template status is stored at the workflow_permanent_id level (not per-version),
- * meaning all versions of a workflow share the same template status.
- *
- * @param {string} workflowPermanentId
- * @param {Skyvern.SetWorkflowTemplateStatusV1WorkflowsWorkflowPermanentIdTemplatePutRequest} request
- * @param {Workflows.RequestOptions} requestOptions - Request-specific configuration.
- *
- * @throws {@link Skyvern.UnprocessableEntityError}
- *
- * @example
- * await client.workflows.setWorkflowTemplateStatus("workflow_permanent_id", {
- * is_template: true
- * })
- */
- public setWorkflowTemplateStatus(
- workflowPermanentId: string,
- request: Skyvern.SetWorkflowTemplateStatusV1WorkflowsWorkflowPermanentIdTemplatePutRequest,
- requestOptions?: Workflows.RequestOptions,
- ): core.HttpResponsePromise> {
- return core.HttpResponsePromise.fromPromise(
- this.__setWorkflowTemplateStatus(workflowPermanentId, request, requestOptions),
- );
- }
-
- private async __setWorkflowTemplateStatus(
- workflowPermanentId: string,
- request: Skyvern.SetWorkflowTemplateStatusV1WorkflowsWorkflowPermanentIdTemplatePutRequest,
- requestOptions?: Workflows.RequestOptions,
- ): Promise>> {
- const { is_template: isTemplate } = request;
- const _queryParams: Record = {};
- _queryParams.is_template = isTemplate.toString();
- const _headers: core.Fetcher.Args["headers"] = mergeHeaders(
- this._options?.headers,
- mergeOnlyDefinedHeaders({ "x-api-key": requestOptions?.apiKey ?? this._options?.apiKey }),
- requestOptions?.headers,
- );
- const _response = await core.fetcher({
- url: core.url.join(
- (await core.Supplier.get(this._options.baseUrl)) ??
- (await core.Supplier.get(this._options.environment)) ??
- environments.SkyvernEnvironment.Cloud,
- `v1/workflows/${core.url.encodePathParam(workflowPermanentId)}/template`,
- ),
- method: "PUT",
- headers: _headers,
- queryParameters: { ..._queryParams, ...requestOptions?.queryParams },
- timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 60) * 1000,
- maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries,
- abortSignal: requestOptions?.abortSignal,
- });
- if (_response.ok) {
- return { data: _response.body as Record, rawResponse: _response.rawResponse };
- }
-
- if (_response.error.reason === "status-code") {
- switch (_response.error.statusCode) {
- case 422:
- throw new Skyvern.UnprocessableEntityError(_response.error.body as unknown, _response.rawResponse);
- default:
- throw new errors.SkyvernError({
- statusCode: _response.error.statusCode,
- body: _response.error.body,
- rawResponse: _response.rawResponse,
- });
- }
- }
-
- switch (_response.error.reason) {
- case "non-json":
- throw new errors.SkyvernError({
- statusCode: _response.error.statusCode,
- body: _response.error.rawBody,
- rawResponse: _response.rawResponse,
- });
- case "timeout":
- throw new errors.SkyvernTimeoutError(
- "Timeout exceeded when calling PUT /v1/workflows/{workflow_permanent_id}/template.",
- );
- case "unknown":
- throw new errors.SkyvernError({
- message: _response.error.errorMessage,
- rawResponse: _response.rawResponse,
- });
- }
- }
-}
diff --git a/skyvern-ts/client/src/api/resources/workflows/client/index.ts b/skyvern-ts/client/src/api/resources/workflows/client/index.ts
deleted file mode 100644
index 195f9aa8..00000000
--- a/skyvern-ts/client/src/api/resources/workflows/client/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export * from "./requests/index.js";
diff --git a/skyvern-ts/client/src/api/resources/workflows/client/requests/SetWorkflowTemplateStatusV1WorkflowsWorkflowPermanentIdTemplatePutRequest.ts b/skyvern-ts/client/src/api/resources/workflows/client/requests/SetWorkflowTemplateStatusV1WorkflowsWorkflowPermanentIdTemplatePutRequest.ts
deleted file mode 100644
index 768d68a3..00000000
--- a/skyvern-ts/client/src/api/resources/workflows/client/requests/SetWorkflowTemplateStatusV1WorkflowsWorkflowPermanentIdTemplatePutRequest.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-// This file was auto-generated by Fern from our API Definition.
-
-/**
- * @example
- * {
- * is_template: true
- * }
- */
-export interface SetWorkflowTemplateStatusV1WorkflowsWorkflowPermanentIdTemplatePutRequest {
- is_template: boolean;
-}
diff --git a/skyvern-ts/client/src/api/resources/workflows/client/requests/index.ts b/skyvern-ts/client/src/api/resources/workflows/client/requests/index.ts
deleted file mode 100644
index c5fa001f..00000000
--- a/skyvern-ts/client/src/api/resources/workflows/client/requests/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export type { SetWorkflowTemplateStatusV1WorkflowsWorkflowPermanentIdTemplatePutRequest } from "./SetWorkflowTemplateStatusV1WorkflowsWorkflowPermanentIdTemplatePutRequest.js";
diff --git a/skyvern-ts/client/src/api/resources/workflows/index.ts b/skyvern-ts/client/src/api/resources/workflows/index.ts
deleted file mode 100644
index 914b8c3c..00000000
--- a/skyvern-ts/client/src/api/resources/workflows/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export * from "./client/index.js";
diff --git a/skyvern-ts/client/src/api/types/PromptAction.ts b/skyvern-ts/client/src/api/types/PromptAction.ts
index 4fe303ed..934fc9de 100644
--- a/skyvern-ts/client/src/api/types/PromptAction.ts
+++ b/skyvern-ts/client/src/api/types/PromptAction.ts
@@ -7,7 +7,7 @@ export interface PromptAction {
/** The prompt to send to the LLM */
prompt: string;
/** Optional JSON schema to structure the response */
- schema?: Record;
+ response_schema?: Record;
/** Optional model configuration */
model?: Record;
}
diff --git a/skyvern-ts/client/src/api/types/RetryRunWebhookRequest.ts b/skyvern-ts/client/src/api/types/RetryRunWebhookRequest.ts
new file mode 100644
index 00000000..7dc9a0da
--- /dev/null
+++ b/skyvern-ts/client/src/api/types/RetryRunWebhookRequest.ts
@@ -0,0 +1,6 @@
+// This file was auto-generated by Fern from our API Definition.
+
+export interface RetryRunWebhookRequest {
+ /** Optional webhook URL to send the payload to instead of the stored configuration */
+ webhook_url?: string;
+}
diff --git a/skyvern-ts/client/src/api/types/UploadFileResponse.ts b/skyvern-ts/client/src/api/types/UploadFileResponse.ts
new file mode 100644
index 00000000..ec36687c
--- /dev/null
+++ b/skyvern-ts/client/src/api/types/UploadFileResponse.ts
@@ -0,0 +1,8 @@
+// This file was auto-generated by Fern from our API Definition.
+
+export interface UploadFileResponse {
+ /** S3 URI where the file was uploaded */
+ s3_uri: string;
+ /** Presigned URL to access the uploaded file */
+ presigned_url: string;
+}
diff --git a/skyvern-ts/client/src/api/types/index.ts b/skyvern-ts/client/src/api/types/index.ts
index 45bf40eb..dad9059b 100644
--- a/skyvern-ts/client/src/api/types/index.ts
+++ b/skyvern-ts/client/src/api/types/index.ts
@@ -96,6 +96,7 @@ export * from "./PdfParserBlockYaml.js";
export * from "./PromptAction.js";
export * from "./PromptBranchCriteria.js";
export * from "./ProxyLocation.js";
+export * from "./RetryRunWebhookRequest.js";
export * from "./RunEngine.js";
export * from "./RunSdkActionRequestAction.js";
export * from "./RunSdkActionResponse.js";
@@ -127,6 +128,7 @@ export * from "./ThoughtType.js";
export * from "./TotpCode.js";
export * from "./TotpType.js";
export * from "./UploadFileAction.js";
+export * from "./UploadFileResponse.js";
export * from "./UploadToS3Block.js";
export * from "./UploadToS3BlockYaml.js";
export * from "./UrlBlock.js";
diff --git a/skyvern-ts/client/src/core/exports.ts b/skyvern-ts/client/src/core/exports.ts
new file mode 100644
index 00000000..e415a8f6
--- /dev/null
+++ b/skyvern-ts/client/src/core/exports.ts
@@ -0,0 +1 @@
+export * from "./file/exports.js";
diff --git a/skyvern-ts/client/src/core/file/exports.ts b/skyvern-ts/client/src/core/file/exports.ts
new file mode 100644
index 00000000..3b0b3967
--- /dev/null
+++ b/skyvern-ts/client/src/core/file/exports.ts
@@ -0,0 +1 @@
+export type { Uploadable } from "./types.js";
diff --git a/skyvern-ts/client/src/core/file/file.ts b/skyvern-ts/client/src/core/file/file.ts
new file mode 100644
index 00000000..0bacc484
--- /dev/null
+++ b/skyvern-ts/client/src/core/file/file.ts
@@ -0,0 +1,217 @@
+import type { Uploadable } from "./types.js";
+
+export async function toBinaryUploadRequest(
+ file: Uploadable,
+): Promise<{ body: Uploadable.FileLike; headers?: Record }> {
+ const { data, filename, contentLength, contentType } = await getFileWithMetadata(file);
+ const request = {
+ body: data,
+ headers: {} as Record,
+ };
+ if (filename) {
+ request.headers["Content-Disposition"] = `attachment; filename="${filename}"`;
+ }
+ if (contentType) {
+ request.headers["Content-Type"] = contentType;
+ }
+ if (contentLength != null) {
+ request.headers["Content-Length"] = contentLength.toString();
+ }
+ return request;
+}
+
+export async function toMultipartDataPart(
+ file: Uploadable,
+): Promise<{ data: Uploadable.FileLike; filename?: string; contentType?: string }> {
+ const { data, filename, contentType } = await getFileWithMetadata(file, {
+ noSniffFileSize: true,
+ });
+ return {
+ data,
+ filename,
+ contentType,
+ };
+}
+
+async function getFileWithMetadata(
+ file: Uploadable,
+ { noSniffFileSize }: { noSniffFileSize?: boolean } = {},
+): Promise {
+ if (isFileLike(file)) {
+ return getFileWithMetadata(
+ {
+ data: file,
+ },
+ { noSniffFileSize },
+ );
+ }
+
+ if ("path" in file) {
+ const fs = await import("fs");
+ if (!fs || !fs.createReadStream) {
+ throw new Error("File path uploads are not supported in this environment.");
+ }
+ const data = fs.createReadStream(file.path);
+ const contentLength =
+ file.contentLength ?? (noSniffFileSize === true ? undefined : await tryGetFileSizeFromPath(file.path));
+ const filename = file.filename ?? getNameFromPath(file.path);
+ return {
+ data,
+ filename,
+ contentType: file.contentType,
+ contentLength,
+ };
+ }
+ if ("data" in file) {
+ const data = file.data;
+ const contentLength =
+ file.contentLength ??
+ (await tryGetContentLengthFromFileLike(data, {
+ noSniffFileSize,
+ }));
+ const filename = file.filename ?? tryGetNameFromFileLike(data);
+ return {
+ data,
+ filename,
+ contentType: file.contentType ?? tryGetContentTypeFromFileLike(data),
+ contentLength,
+ };
+ }
+
+ throw new Error(`Invalid FileUpload of type ${typeof file}: ${JSON.stringify(file)}`);
+}
+
+function isFileLike(value: unknown): value is Uploadable.FileLike {
+ return (
+ isBuffer(value) ||
+ isArrayBufferView(value) ||
+ isArrayBuffer(value) ||
+ isUint8Array(value) ||
+ isBlob(value) ||
+ isFile(value) ||
+ isStreamLike(value) ||
+ isReadableStream(value)
+ );
+}
+
+async function tryGetFileSizeFromPath(path: string): Promise {
+ try {
+ const fs = await import("fs");
+ if (!fs || !fs.promises || !fs.promises.stat) {
+ return undefined;
+ }
+ const fileStat = await fs.promises.stat(path);
+ return fileStat.size;
+ } catch (_fallbackError) {
+ return undefined;
+ }
+}
+
+function tryGetNameFromFileLike(data: Uploadable.FileLike): string | undefined {
+ if (isNamedValue(data)) {
+ return data.name;
+ }
+ if (isPathedValue(data)) {
+ return getNameFromPath(data.path.toString());
+ }
+ return undefined;
+}
+
+async function tryGetContentLengthFromFileLike(
+ data: Uploadable.FileLike,
+ { noSniffFileSize }: { noSniffFileSize?: boolean } = {},
+): Promise {
+ if (isBuffer(data)) {
+ return data.length;
+ }
+ if (isArrayBufferView(data)) {
+ return data.byteLength;
+ }
+ if (isArrayBuffer(data)) {
+ return data.byteLength;
+ }
+ if (isBlob(data)) {
+ return data.size;
+ }
+ if (isFile(data)) {
+ return data.size;
+ }
+ if (noSniffFileSize === true) {
+ return undefined;
+ }
+ if (isPathedValue(data)) {
+ return await tryGetFileSizeFromPath(data.path.toString());
+ }
+ return undefined;
+}
+
+function tryGetContentTypeFromFileLike(data: Uploadable.FileLike): string | undefined {
+ if (isBlob(data)) {
+ return data.type;
+ }
+ if (isFile(data)) {
+ return data.type;
+ }
+
+ return undefined;
+}
+
+function getNameFromPath(path: string): string | undefined {
+ const lastForwardSlash = path.lastIndexOf("/");
+ const lastBackSlash = path.lastIndexOf("\\");
+ const lastSlashIndex = Math.max(lastForwardSlash, lastBackSlash);
+ return lastSlashIndex >= 0 ? path.substring(lastSlashIndex + 1) : path;
+}
+
+type NamedValue = {
+ name: string;
+} & unknown;
+
+type PathedValue = {
+ path: string | { toString(): string };
+} & unknown;
+
+type StreamLike = {
+ read?: () => unknown;
+ pipe?: (dest: unknown) => unknown;
+} & unknown;
+
+function isNamedValue(value: unknown): value is NamedValue {
+ return typeof value === "object" && value != null && "name" in value;
+}
+
+function isPathedValue(value: unknown): value is PathedValue {
+ return typeof value === "object" && value != null && "path" in value;
+}
+
+function isStreamLike(value: unknown): value is StreamLike {
+ return typeof value === "object" && value != null && ("read" in value || "pipe" in value);
+}
+
+function isReadableStream(value: unknown): value is ReadableStream {
+ return typeof value === "object" && value != null && "getReader" in value;
+}
+
+function isBuffer(value: unknown): value is Buffer {
+ return typeof Buffer !== "undefined" && Buffer.isBuffer && Buffer.isBuffer(value);
+}
+
+function isArrayBufferView(value: unknown): value is ArrayBufferView {
+ return typeof ArrayBuffer !== "undefined" && ArrayBuffer.isView(value);
+}
+
+function isArrayBuffer(value: unknown): value is ArrayBuffer {
+ return typeof ArrayBuffer !== "undefined" && value instanceof ArrayBuffer;
+}
+
+function isUint8Array(value: unknown): value is Uint8Array {
+ return typeof Uint8Array !== "undefined" && value instanceof Uint8Array;
+}
+
+function isBlob(value: unknown): value is Blob {
+ return typeof Blob !== "undefined" && value instanceof Blob;
+}
+
+function isFile(value: unknown): value is File {
+ return typeof File !== "undefined" && value instanceof File;
+}
diff --git a/skyvern-ts/client/src/core/file/index.ts b/skyvern-ts/client/src/core/file/index.ts
new file mode 100644
index 00000000..fc16dd52
--- /dev/null
+++ b/skyvern-ts/client/src/core/file/index.ts
@@ -0,0 +1,2 @@
+export * from "./file.js";
+export * from "./types.js";
diff --git a/skyvern-ts/client/src/core/file/types.ts b/skyvern-ts/client/src/core/file/types.ts
new file mode 100644
index 00000000..531b6927
--- /dev/null
+++ b/skyvern-ts/client/src/core/file/types.ts
@@ -0,0 +1,81 @@
+/**
+ * A file that can be uploaded. Can be a file-like object (stream, buffer, blob, etc.),
+ * a path to a file, or an object with a file-like object and metadata.
+ */
+export type Uploadable = Uploadable.FileLike | Uploadable.FromPath | Uploadable.WithMetadata;
+
+export namespace Uploadable {
+ /**
+ * Various file-like objects that can be used to upload a file.
+ */
+ export type FileLike =
+ | ArrayBuffer
+ | ArrayBufferLike
+ | ArrayBufferView
+ | Uint8Array
+ | import("buffer").Buffer
+ | import("buffer").Blob
+ | import("buffer").File
+ | import("stream").Readable
+ | import("stream/web").ReadableStream
+ | globalThis.Blob
+ | globalThis.File
+ | ReadableStream;
+
+ /**
+ * A file path with optional metadata, used for uploading a file from the file system.
+ */
+ export type FromPath = {
+ /** The path to the file to upload */
+ path: string;
+ /**
+ * Optional override for the file name (defaults to basename of path).
+ * This is used to set the `Content-Disposition` header in upload requests.
+ */
+ filename?: string;
+ /**
+ * Optional MIME type of the file (e.g., 'image/jpeg', 'text/plain').
+ * This is used to set the `Content-Type` header in upload requests.
+ */
+ contentType?: string;
+ /**
+ * Optional file size in bytes.
+ * If not provided, the file size will be determined from the file system.
+ * The content length is used to set the `Content-Length` header in upload requests.
+ */
+ contentLength?: number;
+ };
+
+ /**
+ * A file-like object with metadata, used for uploading files.
+ */
+ export type WithMetadata = {
+ /** The file data */
+ data: FileLike;
+ /**
+ * Optional override for the file name (defaults to basename of path).
+ * This is used to set the `Content-Disposition` header in upload requests.
+ */
+ filename?: string;
+ /**
+ * Optional MIME type of the file (e.g., 'image/jpeg', 'text/plain').
+ * This is used to set the `Content-Type` header in upload requests.
+ *
+ * If not provided, the content type may be determined from the data itself.
+ * * If the data is a `File`, `Blob`, or similar, the content type will be determined from the file itself, if the type is set.
+ * * Any other data type will not have a content type set, and the upload request will use `Content-Type: application/octet-stream` instead.
+ */
+ contentType?: string;
+ /**
+ * Optional file size in bytes.
+ * The content length is used to set the `Content-Length` header in upload requests.
+ * If the content length is not provided and cannot be determined, the upload request will not include the `Content-Length` header, but will use `Transfer-Encoding: chunked` instead.
+ *
+ * If not provided, the file size will be determined depending on the data type.
+ * * If the data is of type `fs.ReadStream` (`createReadStream`), the size will be determined from the file system.
+ * * If the data is a `Buffer`, `ArrayBuffer`, `Uint8Array`, `Blob`, `File`, or similar, the size will be determined from the data itself.
+ * * If the data is a `Readable` or `ReadableStream`, the size will not be determined.
+ */
+ contentLength?: number;
+ };
+}
diff --git a/skyvern-ts/client/src/core/form-data-utils/FormDataWrapper.ts b/skyvern-ts/client/src/core/form-data-utils/FormDataWrapper.ts
new file mode 100644
index 00000000..bea0cf82
--- /dev/null
+++ b/skyvern-ts/client/src/core/form-data-utils/FormDataWrapper.ts
@@ -0,0 +1,140 @@
+import { toMultipartDataPart, type Uploadable } from "../../core/file/index.js";
+import { toJson } from "../../core/json.js";
+import { RUNTIME } from "../runtime/index.js";
+
+interface FormDataRequest {
+ body: Body;
+ headers: Record;
+ duplex?: "half";
+}
+
+export async function newFormData(): Promise {
+ return new FormDataWrapper();
+}
+
+export class FormDataWrapper {
+ private fd: FormData = new FormData();
+
+ public async setup(): Promise {
+ // noop
+ }
+
+ public append(key: string, value: unknown): void {
+ this.fd.append(key, String(value));
+ }
+
+ public async appendFile(key: string, value: Uploadable): Promise {
+ const { data, filename, contentType } = await toMultipartDataPart(value);
+ const blob = await convertToBlob(data, contentType);
+ if (filename) {
+ this.fd.append(key, blob, filename);
+ } else {
+ this.fd.append(key, blob);
+ }
+ }
+
+ public getRequest(): FormDataRequest {
+ return {
+ body: this.fd,
+ headers: {},
+ duplex: "half" as const,
+ };
+ }
+}
+
+type StreamLike = {
+ read?: () => unknown;
+ pipe?: (dest: unknown) => unknown;
+} & unknown;
+
+function isStreamLike(value: unknown): value is StreamLike {
+ return typeof value === "object" && value != null && ("read" in value || "pipe" in value);
+}
+
+function isReadableStream(value: unknown): value is ReadableStream {
+ return typeof value === "object" && value != null && "getReader" in value;
+}
+
+function isBuffer(value: unknown): value is Buffer {
+ return typeof Buffer !== "undefined" && Buffer.isBuffer && Buffer.isBuffer(value);
+}
+
+function isArrayBufferView(value: unknown): value is ArrayBufferView {
+ return ArrayBuffer.isView(value);
+}
+
+async function streamToBuffer(stream: unknown): Promise {
+ if (RUNTIME.type === "node") {
+ const { Readable } = await import("stream");
+
+ if (stream instanceof Readable) {
+ const chunks: Buffer[] = [];
+ for await (const chunk of stream) {
+ chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
+ }
+ return Buffer.concat(chunks);
+ }
+ }
+
+ if (isReadableStream(stream)) {
+ const reader = stream.getReader();
+ const chunks: Uint8Array[] = [];
+
+ try {
+ while (true) {
+ const { done, value } = await reader.read();
+ if (done) break;
+ chunks.push(value);
+ }
+ } finally {
+ reader.releaseLock();
+ }
+
+ const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);
+ const result = new Uint8Array(totalLength);
+ let offset = 0;
+ for (const chunk of chunks) {
+ result.set(chunk, offset);
+ offset += chunk.length;
+ }
+
+ return Buffer.from(result);
+ }
+
+ throw new Error(
+ `Unsupported stream type: ${typeof stream}. Expected Node.js Readable stream or Web ReadableStream.`,
+ );
+}
+
+async function convertToBlob(value: unknown, contentType?: string): Promise {
+ if (isStreamLike(value) || isReadableStream(value)) {
+ const buffer = await streamToBuffer(value);
+ return new Blob([buffer], { type: contentType });
+ }
+
+ if (value instanceof Blob) {
+ return value;
+ }
+
+ if (isBuffer(value)) {
+ return new Blob([value], { type: contentType });
+ }
+
+ if (value instanceof ArrayBuffer) {
+ return new Blob([value], { type: contentType });
+ }
+
+ if (isArrayBufferView(value)) {
+ return new Blob([value], { type: contentType });
+ }
+
+ if (typeof value === "string") {
+ return new Blob([value], { type: contentType });
+ }
+
+ if (typeof value === "object" && value !== null) {
+ return new Blob([toJson(value)], { type: contentType ?? "application/json" });
+ }
+
+ return new Blob([String(value)], { type: contentType });
+}
diff --git a/skyvern-ts/client/src/core/form-data-utils/encodeAsFormParameter.ts b/skyvern-ts/client/src/core/form-data-utils/encodeAsFormParameter.ts
new file mode 100644
index 00000000..cfc67413
--- /dev/null
+++ b/skyvern-ts/client/src/core/form-data-utils/encodeAsFormParameter.ts
@@ -0,0 +1,12 @@
+import { toQueryString } from "../url/qs.js";
+
+export function encodeAsFormParameter(value: unknown): Record {
+ const stringified = toQueryString(value, { encode: false });
+
+ const keyValuePairs = stringified.split("&").map((pair) => {
+ const [key, value] = pair.split("=");
+ return [key, value] as const;
+ });
+
+ return Object.fromEntries(keyValuePairs);
+}
diff --git a/skyvern-ts/client/src/core/form-data-utils/index.ts b/skyvern-ts/client/src/core/form-data-utils/index.ts
new file mode 100644
index 00000000..1188f80c
--- /dev/null
+++ b/skyvern-ts/client/src/core/form-data-utils/index.ts
@@ -0,0 +1,2 @@
+export { encodeAsFormParameter } from "./encodeAsFormParameter.js";
+export * from "./FormDataWrapper.js";
diff --git a/skyvern-ts/client/src/core/index.ts b/skyvern-ts/client/src/core/index.ts
index bbb640d1..ad2bf501 100644
--- a/skyvern-ts/client/src/core/index.ts
+++ b/skyvern-ts/client/src/core/index.ts
@@ -1,3 +1,5 @@
export * from "./fetcher/index.js";
+export * as file from "./file/index.js";
+export * from "./form-data-utils/index.js";
export * from "./runtime/index.js";
export * as url from "./url/index.js";
diff --git a/skyvern-ts/client/src/exports.ts b/skyvern-ts/client/src/exports.ts
new file mode 100644
index 00000000..7b70ee14
--- /dev/null
+++ b/skyvern-ts/client/src/exports.ts
@@ -0,0 +1 @@
+export * from "./core/exports.js";
diff --git a/skyvern-ts/client/src/index.ts b/skyvern-ts/client/src/index.ts
index a923e77d..0910dfd3 100644
--- a/skyvern-ts/client/src/index.ts
+++ b/skyvern-ts/client/src/index.ts
@@ -3,5 +3,6 @@ export type { BaseClientOptions, BaseRequestOptions } from "./BaseClient.js";
export { SkyvernClient } from "./Client.js";
export { SkyvernEnvironment } from "./environments.js";
export { SkyvernError, SkyvernTimeoutError } from "./errors/index.js";
+export * from "./exports.js";
export { Skyvern, SkyvernBrowser, SkyvernBrowserPageAgent, SkyvernBrowserPageAi } from "./library/index.js";
export type { SkyvernOptions, SkyvernBrowserPage } from "./library/index.js";
diff --git a/skyvern-ts/client/src/version.ts b/skyvern-ts/client/src/version.ts
index 9add6892..b09139cf 100644
--- a/skyvern-ts/client/src/version.ts
+++ b/skyvern-ts/client/src/version.ts
@@ -1 +1 @@
-export const SDK_VERSION = "1.0.3";
+export const SDK_VERSION = "1.0.6";
diff --git a/skyvern-ts/client/tests/unit/file/file.test.ts b/skyvern-ts/client/tests/unit/file/file.test.ts
new file mode 100644
index 00000000..d7c4570b
--- /dev/null
+++ b/skyvern-ts/client/tests/unit/file/file.test.ts
@@ -0,0 +1,498 @@
+import fs from "fs";
+import { join } from "path";
+import { Readable } from "stream";
+import { toBinaryUploadRequest, type Uploadable } from "../../../src/core/file/index";
+
+describe("toBinaryUploadRequest", () => {
+ const TEST_FILE_PATH = join(__dirname, "..", "test-file.txt");
+
+ beforeEach(() => {
+ vi.clearAllMocks();
+ });
+
+ describe("Buffer input", () => {
+ it("should handle Buffer with all metadata", async () => {
+ const buffer = Buffer.from("test data");
+ const input: Uploadable.WithMetadata = {
+ data: buffer,
+ filename: "test.txt",
+ contentType: "text/plain",
+ contentLength: 42,
+ };
+
+ const result = await toBinaryUploadRequest(input);
+
+ expect(result.body).toBe(buffer);
+ expect(result.headers).toEqual({
+ "Content-Disposition": 'attachment; filename="test.txt"',
+ "Content-Type": "text/plain",
+ "Content-Length": "42",
+ });
+ });
+
+ it("should handle Buffer without metadata", async () => {
+ const buffer = Buffer.from("test data");
+ const input: Uploadable.WithMetadata = {
+ data: buffer,
+ };
+
+ const result = await toBinaryUploadRequest(input);
+
+ expect(result.body).toBe(buffer);
+ expect(result.headers).toEqual({
+ "Content-Length": "9", // buffer.length
+ });
+ });
+
+ it("should handle Buffer passed directly", async () => {
+ const buffer = Buffer.from("test data");
+
+ const result = await toBinaryUploadRequest(buffer);
+
+ expect(result.body).toBe(buffer);
+ expect(result.headers).toEqual({
+ "Content-Length": "9", // buffer.length
+ });
+ });
+ });
+
+ describe("ArrayBuffer input", () => {
+ it("should handle ArrayBuffer with metadata", async () => {
+ const arrayBuffer = new ArrayBuffer(10);
+ const input: Uploadable.WithMetadata = {
+ data: arrayBuffer,
+ filename: "data.bin",
+ contentType: "application/octet-stream",
+ };
+
+ const result = await toBinaryUploadRequest(input);
+
+ expect(result.body).toBe(arrayBuffer);
+ expect(result.headers).toEqual({
+ "Content-Disposition": 'attachment; filename="data.bin"',
+ "Content-Type": "application/octet-stream",
+ "Content-Length": "10", // arrayBuffer.byteLength
+ });
+ });
+
+ it("should handle ArrayBuffer passed directly", async () => {
+ const arrayBuffer = new ArrayBuffer(10);
+
+ const result = await toBinaryUploadRequest(arrayBuffer);
+
+ expect(result.body).toBe(arrayBuffer);
+ expect(result.headers).toEqual({
+ "Content-Length": "10", // arrayBuffer.byteLength
+ });
+ });
+ });
+
+ describe("Uint8Array input", () => {
+ it("should handle Uint8Array with metadata", async () => {
+ const uint8Array = new Uint8Array([1, 2, 3, 4, 5]);
+ const input: Uploadable.WithMetadata = {
+ data: uint8Array,
+ filename: "bytes.bin",
+ contentType: "application/octet-stream",
+ };
+
+ const result = await toBinaryUploadRequest(input);
+
+ expect(result.body).toBe(uint8Array);
+ expect(result.headers).toEqual({
+ "Content-Disposition": 'attachment; filename="bytes.bin"',
+ "Content-Type": "application/octet-stream",
+ "Content-Length": "5", // uint8Array.byteLength
+ });
+ });
+
+ it("should handle Uint8Array passed directly", async () => {
+ const uint8Array = new Uint8Array([1, 2, 3, 4, 5]);
+
+ const result = await toBinaryUploadRequest(uint8Array);
+
+ expect(result.body).toBe(uint8Array);
+ expect(result.headers).toEqual({
+ "Content-Length": "5", // uint8Array.byteLength
+ });
+ });
+ });
+
+ describe("Blob input", () => {
+ it("should handle Blob with metadata", async () => {
+ const blob = new Blob(["test content"], { type: "text/plain" });
+ const input: Uploadable.WithMetadata = {
+ data: blob,
+ filename: "override.txt",
+ contentType: "text/html", // Override blob's type
+ };
+
+ const result = await toBinaryUploadRequest(input);
+
+ expect(result.body).toBe(blob);
+ expect(result.headers).toEqual({
+ "Content-Disposition": 'attachment; filename="override.txt"',
+ "Content-Type": "text/html", // Should use provided contentType
+ "Content-Length": "12", // blob.size
+ });
+ });
+
+ it("should handle Blob with intrinsic type", async () => {
+ const blob = new Blob(["test content"], { type: "application/json" });
+ const input: Uploadable.WithMetadata = {
+ data: blob,
+ filename: "data.json",
+ };
+
+ const result = await toBinaryUploadRequest(input);
+
+ expect(result.body).toBe(blob);
+ expect(result.headers).toEqual({
+ "Content-Disposition": 'attachment; filename="data.json"',
+ "Content-Type": "application/json", // Should use blob's type
+ "Content-Length": "12", // blob.size
+ });
+ });
+
+ it("should handle Blob passed directly", async () => {
+ const blob = new Blob(["test content"], { type: "text/plain" });
+
+ const result = await toBinaryUploadRequest(blob);
+
+ expect(result.body).toBe(blob);
+ expect(result.headers).toEqual({
+ "Content-Type": "text/plain", // Should use blob's type
+ "Content-Length": "12", // blob.size
+ });
+ });
+ });
+
+ describe("File input", () => {
+ it("should handle File with metadata", async () => {
+ const file = new File(["file content"], "original.txt", { type: "text/plain" });
+ const input: Uploadable.WithMetadata = {
+ data: file,
+ filename: "renamed.txt",
+ contentType: "text/html", // Override file's type
+ };
+
+ const result = await toBinaryUploadRequest(input);
+
+ expect(result.body).toBe(file);
+ expect(result.headers).toEqual({
+ "Content-Disposition": 'attachment; filename="renamed.txt"',
+ "Content-Type": "text/html", // Should use provided contentType
+ "Content-Length": "12", // file.size
+ });
+ });
+
+ it("should handle File with intrinsic properties", async () => {
+ const file = new File(["file content"], "test.json", { type: "application/json" });
+ const input: Uploadable.WithMetadata = {
+ data: file,
+ };
+
+ const result = await toBinaryUploadRequest(input);
+
+ expect(result.body).toBe(file);
+ expect(result.headers).toEqual({
+ "Content-Disposition": 'attachment; filename="test.json"', // Should use file's name
+ "Content-Type": "application/json", // Should use file's type
+ "Content-Length": "12", // file.size
+ });
+ });
+
+ it("should handle File passed directly", async () => {
+ const file = new File(["file content"], "direct.txt", { type: "text/plain" });
+
+ const result = await toBinaryUploadRequest(file);
+
+ expect(result.body).toBe(file);
+ expect(result.headers).toEqual({
+ "Content-Disposition": 'attachment; filename="direct.txt"',
+ "Content-Type": "text/plain",
+ "Content-Length": "12", // file.size
+ });
+ });
+ });
+
+ describe("ReadableStream input", () => {
+ it("should handle ReadableStream with metadata", async () => {
+ const stream = new ReadableStream({
+ start(controller) {
+ controller.enqueue(new TextEncoder().encode("stream data"));
+ controller.close();
+ },
+ });
+ const input: Uploadable.WithMetadata = {
+ data: stream,
+ filename: "stream.txt",
+ contentType: "text/plain",
+ contentLength: 100,
+ };
+
+ const result = await toBinaryUploadRequest(input);
+
+ expect(result.body).toBe(stream);
+ expect(result.headers).toEqual({
+ "Content-Disposition": 'attachment; filename="stream.txt"',
+ "Content-Type": "text/plain",
+ "Content-Length": "100", // Should use provided contentLength
+ });
+ });
+
+ it("should handle ReadableStream without size", async () => {
+ const stream = new ReadableStream({
+ start(controller) {
+ controller.enqueue(new TextEncoder().encode("stream data"));
+ controller.close();
+ },
+ });
+ const input: Uploadable.WithMetadata = {
+ data: stream,
+ filename: "stream.txt",
+ contentType: "text/plain",
+ };
+
+ const result = await toBinaryUploadRequest(input);
+
+ expect(result.body).toBe(stream);
+ expect(result.headers).toEqual({
+ "Content-Disposition": 'attachment; filename="stream.txt"',
+ "Content-Type": "text/plain",
+ // No Content-Length header since it cannot be determined from ReadableStream
+ });
+ });
+
+ it("should handle ReadableStream passed directly", async () => {
+ const stream = new ReadableStream({
+ start(controller) {
+ controller.enqueue(new TextEncoder().encode("stream data"));
+ controller.close();
+ },
+ });
+
+ const result = await toBinaryUploadRequest(stream);
+
+ expect(result.body).toBe(stream);
+ expect(result.headers).toEqual({
+ // No headers since no metadata provided and cannot be determined
+ });
+ });
+ });
+
+ describe("Node.js Readable stream input", () => {
+ it("should handle Readable stream with metadata", async () => {
+ const readable = new Readable({
+ read() {
+ this.push("readable data");
+ this.push(null);
+ },
+ });
+ const input: Uploadable.WithMetadata = {
+ data: readable,
+ filename: "readable.txt",
+ contentType: "text/plain",
+ contentLength: 50,
+ };
+
+ const result = await toBinaryUploadRequest(input);
+
+ expect(result.body).toBe(readable);
+ expect(result.headers).toEqual({
+ "Content-Disposition": 'attachment; filename="readable.txt"',
+ "Content-Type": "text/plain",
+ "Content-Length": "50", // Should use provided contentLength
+ });
+ });
+
+ it("should handle Readable stream without size", async () => {
+ const readable = new Readable({
+ read() {
+ this.push("readable data");
+ this.push(null);
+ },
+ });
+ const input: Uploadable.WithMetadata = {
+ data: readable,
+ filename: "readable.txt",
+ contentType: "text/plain",
+ };
+
+ const result = await toBinaryUploadRequest(input);
+
+ expect(result.body).toBe(readable);
+ expect(result.headers).toEqual({
+ "Content-Disposition": 'attachment; filename="readable.txt"',
+ "Content-Type": "text/plain",
+ // No Content-Length header since it cannot be determined from Readable
+ });
+ });
+
+ it("should handle Readable stream passed directly", async () => {
+ const readable = new Readable({
+ read() {
+ this.push("readable data");
+ this.push(null);
+ },
+ });
+
+ const result = await toBinaryUploadRequest(readable);
+
+ expect(result.body).toBe(readable);
+ expect(result.headers).toEqual({
+ // No headers since no metadata provided and cannot be determined
+ });
+ });
+ });
+
+ describe("File path input (FromPath type)", () => {
+ it("should handle file path with all metadata", async () => {
+ const input: Uploadable.FromPath = {
+ path: TEST_FILE_PATH,
+ filename: "custom.txt",
+ contentType: "text/html",
+ contentLength: 42,
+ };
+
+ const result = await toBinaryUploadRequest(input);
+
+ expect(result.body).toBeInstanceOf(fs.ReadStream);
+ expect(result.headers).toEqual({
+ "Content-Disposition": 'attachment; filename="custom.txt"',
+ "Content-Type": "text/html",
+ "Content-Length": "42", // Should use provided contentLength
+ });
+ });
+
+ it("should handle file path with minimal metadata", async () => {
+ const input: Uploadable.FromPath = {
+ path: TEST_FILE_PATH,
+ contentType: "text/plain",
+ };
+
+ const result = await toBinaryUploadRequest(input);
+
+ expect(result.body).toBeInstanceOf(fs.ReadStream);
+ expect(result.headers).toEqual({
+ "Content-Disposition": 'attachment; filename="test-file.txt"', // Should extract from path
+ "Content-Type": "text/plain",
+ "Content-Length": "21", // Should determine from file system (test file is 21 bytes)
+ });
+ });
+
+ it("should handle file path with no metadata", async () => {
+ const input: Uploadable.FromPath = {
+ path: TEST_FILE_PATH,
+ };
+
+ const result = await toBinaryUploadRequest(input);
+
+ expect(result.body).toBeInstanceOf(fs.ReadStream);
+ expect(result.headers).toEqual({
+ "Content-Disposition": 'attachment; filename="test-file.txt"', // Should extract from path
+ "Content-Length": "21", // Should determine from file system (test file is 21 bytes)
+ });
+ });
+ });
+
+ describe("ArrayBufferView input", () => {
+ it("should handle ArrayBufferView with metadata", async () => {
+ const arrayBuffer = new ArrayBuffer(10);
+ const arrayBufferView = new Int8Array(arrayBuffer);
+ const input: Uploadable.WithMetadata = {
+ data: arrayBufferView,
+ filename: "view.bin",
+ contentType: "application/octet-stream",
+ };
+
+ const result = await toBinaryUploadRequest(input);
+
+ expect(result.body).toBe(arrayBufferView);
+ expect(result.headers).toEqual({
+ "Content-Disposition": 'attachment; filename="view.bin"',
+ "Content-Type": "application/octet-stream",
+ "Content-Length": "10", // arrayBufferView.byteLength
+ });
+ });
+
+ it("should handle ArrayBufferView passed directly", async () => {
+ const arrayBuffer = new ArrayBuffer(10);
+ const arrayBufferView = new Int8Array(arrayBuffer);
+
+ const result = await toBinaryUploadRequest(arrayBufferView);
+
+ expect(result.body).toBe(arrayBufferView);
+ expect(result.headers).toEqual({
+ "Content-Length": "10", // arrayBufferView.byteLength
+ });
+ });
+ });
+
+ describe("Edge cases", () => {
+ it("should handle empty headers when no metadata is available", async () => {
+ const buffer = Buffer.from("");
+ const input: Uploadable.WithMetadata = {
+ data: buffer,
+ };
+
+ const result = await toBinaryUploadRequest(input);
+
+ expect(result.body).toBe(buffer);
+ expect(result.headers).toEqual({
+ "Content-Length": "0",
+ });
+ });
+
+ it("should handle zero contentLength", async () => {
+ const buffer = Buffer.from("test");
+ const input: Uploadable.WithMetadata = {
+ data: buffer,
+ contentLength: 0,
+ };
+
+ const result = await toBinaryUploadRequest(input);
+
+ expect(result.body).toBe(buffer);
+ expect(result.headers).toEqual({
+ "Content-Length": "0", // Should use provided 0
+ });
+ });
+
+ it("should handle null filename", async () => {
+ const buffer = Buffer.from("test");
+ const input: Uploadable.WithMetadata = {
+ data: buffer,
+ filename: undefined,
+ contentType: "text/plain",
+ };
+
+ const result = await toBinaryUploadRequest(input);
+
+ expect(result.body).toBe(buffer);
+ expect(result.headers).toEqual({
+ "Content-Type": "text/plain",
+ "Content-Length": "4",
+ // No Content-Disposition since filename is undefined
+ });
+ });
+
+ it("should handle null contentType", async () => {
+ const buffer = Buffer.from("test");
+ const input: Uploadable.WithMetadata = {
+ data: buffer,
+ filename: "test.txt",
+ contentType: undefined,
+ };
+
+ const result = await toBinaryUploadRequest(input);
+
+ expect(result.body).toBe(buffer);
+ expect(result.headers).toEqual({
+ "Content-Disposition": 'attachment; filename="test.txt"',
+ "Content-Length": "4",
+ // No Content-Type since contentType is undefined
+ });
+ });
+ });
+});
diff --git a/skyvern-ts/client/tests/unit/form-data-utils/encodeAsFormParameter.test.ts b/skyvern-ts/client/tests/unit/form-data-utils/encodeAsFormParameter.test.ts
new file mode 100644
index 00000000..d4b0c450
--- /dev/null
+++ b/skyvern-ts/client/tests/unit/form-data-utils/encodeAsFormParameter.test.ts
@@ -0,0 +1,344 @@
+import { encodeAsFormParameter } from "../../../src/core/form-data-utils/encodeAsFormParameter";
+
+describe("encodeAsFormParameter", () => {
+ describe("Basic functionality", () => {
+ it("should return empty object for null/undefined", () => {
+ expect(encodeAsFormParameter(null)).toEqual({});
+ expect(encodeAsFormParameter(undefined)).toEqual({});
+ });
+
+ it("should return empty object for primitive values", () => {
+ expect(encodeAsFormParameter("hello")).toEqual({});
+ expect(encodeAsFormParameter(42)).toEqual({});
+ expect(encodeAsFormParameter(true)).toEqual({});
+ });
+
+ it("should handle simple key-value pairs", () => {
+ const obj = { name: "John", age: 30 };
+ expect(encodeAsFormParameter(obj)).toEqual({
+ name: "John",
+ age: "30",
+ });
+ });
+
+ it("should handle empty objects", () => {
+ expect(encodeAsFormParameter({})).toEqual({});
+ });
+ });
+
+ describe("Array handling", () => {
+ it("should handle arrays with indices format (default)", () => {
+ const obj = { items: ["a", "b", "c"] };
+ expect(encodeAsFormParameter(obj)).toEqual({
+ "items[0]": "a",
+ "items[1]": "b",
+ "items[2]": "c",
+ });
+ });
+
+ it("should handle empty arrays", () => {
+ const obj = { items: [] };
+ expect(encodeAsFormParameter(obj)).toEqual({});
+ });
+
+ it("should handle arrays with mixed types", () => {
+ const obj = { mixed: ["string", 42, true, false] };
+ expect(encodeAsFormParameter(obj)).toEqual({
+ "mixed[0]": "string",
+ "mixed[1]": "42",
+ "mixed[2]": "true",
+ "mixed[3]": "false",
+ });
+ });
+
+ it("should handle arrays with objects", () => {
+ const obj = { users: [{ name: "John" }, { name: "Jane" }] };
+ expect(encodeAsFormParameter(obj)).toEqual({
+ "users[0][name]": "John",
+ "users[1][name]": "Jane",
+ });
+ });
+
+ it("should handle arrays with null/undefined values", () => {
+ const obj = { items: ["a", null, "c", undefined, "e"] };
+ expect(encodeAsFormParameter(obj)).toEqual({
+ "items[0]": "a",
+ "items[1]": "",
+ "items[2]": "c",
+ "items[4]": "e",
+ });
+ });
+ });
+
+ describe("Nested objects", () => {
+ it("should handle nested objects", () => {
+ const obj = { user: { name: "John", age: 30 } };
+ expect(encodeAsFormParameter(obj)).toEqual({
+ "user[name]": "John",
+ "user[age]": "30",
+ });
+ });
+
+ it("should handle deeply nested objects", () => {
+ const obj = { user: { profile: { name: "John", settings: { theme: "dark" } } } };
+ expect(encodeAsFormParameter(obj)).toEqual({
+ "user[profile][name]": "John",
+ "user[profile][settings][theme]": "dark",
+ });
+ });
+
+ it("should handle empty nested objects", () => {
+ const obj = { user: {} };
+ expect(encodeAsFormParameter(obj)).toEqual({});
+ });
+ });
+
+ describe("Special characters and encoding", () => {
+ it("should not encode values (encode: false is used)", () => {
+ const obj = { name: "John Doe", email: "john@example.com" };
+ expect(encodeAsFormParameter(obj)).toEqual({
+ name: "John Doe",
+ email: "john@example.com",
+ });
+ });
+
+ it("should not encode special characters in keys", () => {
+ const obj = { "user name": "John", "email[primary]": "john@example.com" };
+ expect(encodeAsFormParameter(obj)).toEqual({
+ "user name": "John",
+ "email[primary]": "john@example.com",
+ });
+ });
+
+ it("should handle values that contain special characters", () => {
+ const obj = {
+ query: "search term with spaces",
+ filter: "category:electronics",
+ };
+ expect(encodeAsFormParameter(obj)).toEqual({
+ query: "search term with spaces",
+ filter: "category:electronics",
+ });
+ });
+
+ it("should handle ampersand and equals characters (edge case)", () => {
+ // Note: Values containing & and = may be problematic because
+ // encodeAsFormParameter splits on these characters when parsing the stringified result
+ const obj = {
+ message: "Hello & welcome",
+ equation: "x = y + z",
+ };
+ // This demonstrates the limitation - ampersands and equals signs in values
+ // will cause the parameter to be split incorrectly
+ const result = encodeAsFormParameter(obj);
+
+ // We expect this to be parsed incorrectly due to the implementation
+ expect(result.message).toBe("Hello ");
+ expect(result[" welcome"]).toBeUndefined();
+ expect(result.equation).toBe("x ");
+ expect(result[" y + z"]).toBeUndefined();
+ });
+ });
+
+ describe("Form data specific scenarios", () => {
+ it("should handle file upload metadata", () => {
+ const metadata = {
+ file: {
+ name: "document.pdf",
+ size: 1024,
+ type: "application/pdf",
+ },
+ options: {
+ compress: true,
+ quality: 0.8,
+ },
+ };
+ expect(encodeAsFormParameter(metadata)).toEqual({
+ "file[name]": "document.pdf",
+ "file[size]": "1024",
+ "file[type]": "application/pdf",
+ "options[compress]": "true",
+ "options[quality]": "0.8",
+ });
+ });
+
+ it("should handle form validation data", () => {
+ const formData = {
+ fields: ["name", "email", "phone"],
+ validation: {
+ required: ["name", "email"],
+ patterns: {
+ email: "^[^@]+@[^@]+\\.[^@]+$",
+ phone: "^\\+?[1-9]\\d{1,14}$",
+ },
+ },
+ };
+ expect(encodeAsFormParameter(formData)).toEqual({
+ "fields[0]": "name",
+ "fields[1]": "email",
+ "fields[2]": "phone",
+ "validation[required][0]": "name",
+ "validation[required][1]": "email",
+ "validation[patterns][email]": "^[^@]+@[^@]+\\.[^@]+$",
+ "validation[patterns][phone]": "^\\+?[1-9]\\d{1,14}$",
+ });
+ });
+
+ it("should handle search/filter parameters", () => {
+ const searchParams = {
+ filters: {
+ status: ["active", "pending"],
+ category: {
+ type: "electronics",
+ subcategories: ["phones", "laptops"],
+ },
+ },
+ sort: { field: "name", direction: "asc" },
+ pagination: { page: 1, limit: 20 },
+ };
+ expect(encodeAsFormParameter(searchParams)).toEqual({
+ "filters[status][0]": "active",
+ "filters[status][1]": "pending",
+ "filters[category][type]": "electronics",
+ "filters[category][subcategories][0]": "phones",
+ "filters[category][subcategories][1]": "laptops",
+ "sort[field]": "name",
+ "sort[direction]": "asc",
+ "pagination[page]": "1",
+ "pagination[limit]": "20",
+ });
+ });
+ });
+
+ describe("Edge cases", () => {
+ it("should handle boolean values", () => {
+ const obj = { enabled: true, disabled: false };
+ expect(encodeAsFormParameter(obj)).toEqual({
+ enabled: "true",
+ disabled: "false",
+ });
+ });
+
+ it("should handle empty strings", () => {
+ const obj = { name: "", description: "test" };
+ expect(encodeAsFormParameter(obj)).toEqual({
+ name: "",
+ description: "test",
+ });
+ });
+
+ it("should handle zero values", () => {
+ const obj = { count: 0, price: 0.0 };
+ expect(encodeAsFormParameter(obj)).toEqual({
+ count: "0",
+ price: "0",
+ });
+ });
+
+ it("should handle numeric keys", () => {
+ const obj = { "0": "zero", "1": "one" };
+ expect(encodeAsFormParameter(obj)).toEqual({
+ "0": "zero",
+ "1": "one",
+ });
+ });
+
+ it("should handle objects with null/undefined values", () => {
+ const obj = { name: "John", age: null, email: undefined, active: true };
+ expect(encodeAsFormParameter(obj)).toEqual({
+ name: "John",
+ age: "",
+ active: "true",
+ });
+ });
+ });
+
+ describe("Integration with form submission", () => {
+ it("should produce form-compatible key-value pairs", () => {
+ const formObject = {
+ username: "john_doe",
+ preferences: {
+ theme: "dark",
+ notifications: ["email", "push"],
+ settings: {
+ autoSave: true,
+ timeout: 300,
+ },
+ },
+ };
+
+ const result = encodeAsFormParameter(formObject);
+
+ // Verify all values are strings (as required for form data)
+ Object.values(result).forEach((value) => {
+ expect(typeof value).toBe("string");
+ });
+
+ // Verify the structure can be reconstructed
+ expect(result).toEqual({
+ username: "john_doe",
+ "preferences[theme]": "dark",
+ "preferences[notifications][0]": "email",
+ "preferences[notifications][1]": "push",
+ "preferences[settings][autoSave]": "true",
+ "preferences[settings][timeout]": "300",
+ });
+ });
+
+ it("should handle complex nested arrays for API parameters", () => {
+ const apiParams = {
+ query: {
+ filters: [
+ { field: "status", operator: "eq", value: "active" },
+ { field: "created", operator: "gte", value: "2023-01-01" },
+ ],
+ sort: [
+ { field: "name", direction: "asc" },
+ { field: "created", direction: "desc" },
+ ],
+ },
+ };
+
+ const result = encodeAsFormParameter(apiParams);
+ expect(result).toEqual({
+ "query[filters][0][field]": "status",
+ "query[filters][0][operator]": "eq",
+ "query[filters][0][value]": "active",
+ "query[filters][1][field]": "created",
+ "query[filters][1][operator]": "gte",
+ "query[filters][1][value]": "2023-01-01",
+ "query[sort][0][field]": "name",
+ "query[sort][0][direction]": "asc",
+ "query[sort][1][field]": "created",
+ "query[sort][1][direction]": "desc",
+ });
+ });
+ });
+
+ describe("Error cases and malformed input", () => {
+ it("should handle circular references gracefully", () => {
+ const obj: any = { name: "test" };
+ obj.self = obj;
+
+ // This will throw a RangeError due to stack overflow - this is expected behavior
+ expect(() => encodeAsFormParameter(obj)).toThrow("Maximum call stack size exceeded");
+ });
+
+ it("should handle very deeply nested objects", () => {
+ let deepObj: any = { value: "deep" };
+ for (let i = 0; i < 100; i++) {
+ deepObj = { level: deepObj };
+ }
+
+ expect(() => encodeAsFormParameter(deepObj)).not.toThrow();
+ const result = encodeAsFormParameter(deepObj);
+ expect(Object.keys(result).length).toBeGreaterThan(0);
+ });
+
+ it("should handle empty string splitting edge case", () => {
+ // Test what happens when qs returns an empty string
+ const result = encodeAsFormParameter({});
+ expect(result).toEqual({});
+ });
+ });
+});
diff --git a/skyvern-ts/client/tests/unit/form-data-utils/formDataWrapper.test.ts b/skyvern-ts/client/tests/unit/form-data-utils/formDataWrapper.test.ts
new file mode 100644
index 00000000..47705084
--- /dev/null
+++ b/skyvern-ts/client/tests/unit/form-data-utils/formDataWrapper.test.ts
@@ -0,0 +1,346 @@
+import { Blob, File } from "buffer";
+import { join } from "path";
+/* eslint-disable @typescript-eslint/ban-ts-comment */
+import { Readable } from "stream";
+import { FormDataWrapper, newFormData } from "../../../src/core/form-data-utils/FormDataWrapper";
+
+// Helper function to serialize FormData to string for inspection
+async function serializeFormData(formData: FormData): Promise {
+ const request = new Request("http://localhost", {
+ method: "POST",
+ body: formData,
+ });
+
+ const buffer = await request.arrayBuffer();
+ return new TextDecoder().decode(buffer);
+}
+
+describe("FormDataWrapper", () => {
+ let formData: FormDataWrapper;
+
+ beforeEach(async () => {
+ formData = new FormDataWrapper();
+ await formData.setup();
+ });
+
+ it("Upload file by path", async () => {
+ await formData.appendFile("file", {
+ path: join(__dirname, "..", "test-file.txt"),
+ });
+
+ const serialized = await serializeFormData(formData.getRequest().body);
+
+ expect(serialized).toContain('Content-Disposition: form-data; name="file"');
+ expect(serialized).toContain('filename="test-file.txt"');
+ expect(serialized).toContain("This is a test file!");
+ });
+
+ it("Upload file by path with filename", async () => {
+ await formData.appendFile("file", {
+ path: join(__dirname, "..", "test-file.txt"),
+ filename: "custom-file.txt",
+ });
+
+ const serialized = await serializeFormData(formData.getRequest().body);
+
+ expect(serialized).toContain('Content-Disposition: form-data; name="file"');
+ expect(serialized).toContain('filename="custom-file.txt"');
+ expect(serialized).toContain("This is a test file!");
+ });
+
+ describe("Stream handling", () => {
+ it("serializes Node.js Readable stream with filename", async () => {
+ const stream = Readable.from(["file content"]);
+ await formData.appendFile("file", {
+ data: stream,
+ filename: "testfile.txt",
+ });
+
+ const serialized = await serializeFormData(formData.getRequest().body);
+
+ expect(serialized).toContain('Content-Disposition: form-data; name="file"');
+ expect(serialized).toContain('filename="testfile.txt"');
+ expect(serialized).toContain("file content");
+ });
+
+ it("auto-detects filename from stream path property", async () => {
+ const stream = Readable.from(["file content"]);
+ (stream as { path?: string }).path = "/test/path/testfile.txt";
+
+ await formData.appendFile("file", stream);
+
+ const serialized = await serializeFormData(formData.getRequest().body);
+ expect(serialized).toContain('filename="testfile.txt"');
+ });
+
+ it("handles Windows-style paths", async () => {
+ const stream = Readable.from(["file content"]);
+ (stream as { path?: string }).path = "C:\\test\\path\\testfile.txt";
+
+ await formData.appendFile("file", stream);
+
+ const serialized = await serializeFormData(formData.getRequest().body);
+ expect(serialized).toContain('filename="testfile.txt"');
+ });
+
+ it("handles empty streams", async () => {
+ const stream = Readable.from([]);
+ await formData.appendFile("file", {
+ data: stream,
+ filename: "empty.txt",
+ });
+
+ const serialized = await serializeFormData(formData.getRequest().body);
+ expect(serialized).toContain('filename="empty.txt"');
+ expect(serialized).toMatch(/------formdata-undici-\w+|------WebKitFormBoundary\w+/);
+ });
+
+ it("serializes Web ReadableStream with filename", async () => {
+ const stream = new ReadableStream({
+ start(controller) {
+ controller.enqueue(new TextEncoder().encode("web stream content"));
+ controller.close();
+ },
+ });
+
+ await formData.appendFile("file", {
+ data: stream,
+ filename: "webstream.txt",
+ });
+
+ const serialized = await serializeFormData(formData.getRequest().body);
+ expect(serialized).toContain('filename="webstream.txt"');
+ expect(serialized).toContain("web stream content");
+ });
+
+ it("handles empty Web ReadableStream", async () => {
+ const stream = new ReadableStream({
+ start(controller) {
+ controller.close();
+ },
+ });
+
+ await formData.appendFile("file", {
+ data: stream,
+ filename: "empty.txt",
+ });
+
+ const serialized = await serializeFormData(formData.getRequest().body);
+ expect(serialized).toContain('filename="empty.txt"');
+ expect(serialized).toMatch(/------formdata-undici-\w+|------WebKitFormBoundary\w+/);
+ });
+ });
+
+ describe("Blob and File types", () => {
+ it("serializes Blob with specified filename", async () => {
+ const blob = new Blob(["file content"], { type: "text/plain" });
+ await formData.appendFile("file", {
+ data: blob,
+ filename: "testfile.txt",
+ });
+
+ const serialized = await serializeFormData(formData.getRequest().body);
+ expect(serialized).toContain('filename="testfile.txt"');
+ expect(serialized).toContain("Content-Type: text/plain");
+ expect(serialized).toContain("file content");
+ });
+
+ it("uses default filename for Blob without explicit filename", async () => {
+ const blob = new Blob(["file content"], { type: "text/plain" });
+ await formData.appendFile("file", blob);
+
+ const serialized = await serializeFormData(formData.getRequest().body);
+ expect(serialized).toContain('filename="blob"');
+ });
+
+ it("preserves File object filename", async () => {
+ if (typeof File !== "undefined") {
+ const file = new File(["file content"], "original.txt", { type: "text/plain" });
+ await formData.appendFile("file", file);
+
+ const serialized = await serializeFormData(formData.getRequest().body);
+ expect(serialized).toContain('filename="original.txt"');
+ expect(serialized).toContain("file content");
+ }
+ });
+
+ it("allows filename override for File objects", async () => {
+ if (typeof File !== "undefined") {
+ const file = new File(["file content"], "original.txt", { type: "text/plain" });
+ await formData.appendFile("file", {
+ data: file,
+ filename: "override.txt",
+ });
+
+ const serialized = await serializeFormData(formData.getRequest().body);
+ expect(serialized).toContain('filename="override.txt"');
+ expect(serialized).not.toContain('filename="original.txt"');
+ }
+ });
+ });
+
+ describe("Binary data types", () => {
+ it("serializes ArrayBuffer with filename", async () => {
+ const arrayBuffer = new ArrayBuffer(8);
+ new Uint8Array(arrayBuffer).set([1, 2, 3, 4, 5, 6, 7, 8]);
+
+ await formData.appendFile("file", {
+ data: arrayBuffer,
+ filename: "binary.bin",
+ });
+
+ const serialized = await serializeFormData(formData.getRequest().body);
+ expect(serialized).toContain('filename="binary.bin"');
+ expect(serialized).toMatch(/------formdata-undici-\w+|------WebKitFormBoundary\w+/);
+ });
+
+ it("serializes Uint8Array with filename", async () => {
+ const uint8Array = new Uint8Array([72, 101, 108, 108, 111]); // "Hello"
+ await formData.appendFile("file", {
+ data: uint8Array,
+ filename: "binary.bin",
+ });
+
+ const serialized = await serializeFormData(formData.getRequest().body);
+ expect(serialized).toContain('filename="binary.bin"');
+ expect(serialized).toContain("Hello");
+ });
+
+ it("serializes other typed arrays", async () => {
+ const int16Array = new Int16Array([1000, 2000, 3000]);
+ await formData.appendFile("file", {
+ data: int16Array,
+ filename: "numbers.bin",
+ });
+
+ const serialized = await serializeFormData(formData.getRequest().body);
+ expect(serialized).toContain('filename="numbers.bin"');
+ });
+
+ it("serializes Buffer data with filename", async () => {
+ if (typeof Buffer !== "undefined" && typeof Buffer.isBuffer === "function") {
+ const buffer = Buffer.from("test content");
+ await formData.appendFile("file", {
+ data: buffer,
+ filename: "test.txt",
+ });
+
+ const serialized = await serializeFormData(formData.getRequest().body);
+ expect(serialized).toContain('filename="test.txt"');
+ expect(serialized).toContain("test content");
+ }
+ });
+ });
+
+ describe("Text and primitive types", () => {
+ it("serializes string as regular form field", async () => {
+ formData.append("text", "test string");
+
+ const serialized = await serializeFormData(formData.getRequest().body);
+ expect(serialized).toContain('name="text"');
+ expect(serialized).not.toContain("filename=");
+ expect(serialized).toContain("test string");
+ });
+
+ it("serializes numbers and booleans as strings", async () => {
+ formData.append("number", 12345);
+ formData.append("flag", true);
+
+ const serialized = await serializeFormData(formData.getRequest().body);
+ expect(serialized).toContain("12345");
+ expect(serialized).toContain("true");
+ });
+ });
+
+ describe("Edge cases and error handling", () => {
+ it("handles empty filename gracefully", async () => {
+ await formData.appendFile("file", {
+ data: new Blob(["content"], { type: "text/plain" }),
+ filename: "",
+ });
+
+ const serialized = await serializeFormData(formData.getRequest().body);
+ expect(serialized).toContain('filename="blob"'); // Default fallback
+ });
+
+ it("handles multiple files in single form", async () => {
+ await formData.appendFile("file1", {
+ data: new Blob(["content1"], { type: "text/plain" }),
+ filename: "file1.txt",
+ });
+ await formData.appendFile("file2", {
+ data: new Blob(["content2"], { type: "text/plain" }),
+ filename: "file2.txt",
+ });
+ formData.append("text", "regular field");
+
+ const serialized = await serializeFormData(formData.getRequest().body);
+
+ expect(serialized).toContain('filename="file1.txt"');
+ expect(serialized).toContain('filename="file2.txt"');
+ expect(serialized).toContain('name="text"');
+ expect(serialized).not.toContain('filename="text"');
+ });
+ });
+
+ describe("Request structure", () => {
+ it("returns correct request structure", async () => {
+ await formData.appendFile("file", {
+ data: new Blob(["content"], { type: "text/plain" }),
+ filename: "test.txt",
+ });
+
+ const request = formData.getRequest();
+
+ expect(request).toHaveProperty("body");
+ expect(request).toHaveProperty("headers");
+ expect(request).toHaveProperty("duplex");
+ expect(request.body).toBeInstanceOf(FormData);
+ expect(request.headers).toEqual({});
+ expect(request.duplex).toBe("half");
+ });
+
+ it("generates proper multipart boundary structure", async () => {
+ await formData.appendFile("file", {
+ data: new Blob(["test content"], { type: "text/plain" }),
+ filename: "test.txt",
+ });
+ formData.append("field", "value");
+
+ const serialized = await serializeFormData(formData.getRequest().body);
+
+ expect(serialized).toMatch(/------formdata-undici-\w+|------WebKitFormBoundary\w+/);
+ expect(serialized).toContain("Content-Disposition: form-data;");
+ expect(serialized).toMatch(/------formdata-undici-\w+--|------WebKitFormBoundary\w+--/);
+ });
+ });
+
+ describe("Factory function", () => {
+ it("returns FormDataWrapper instance", async () => {
+ const formData = await newFormData();
+ expect(formData).toBeInstanceOf(FormDataWrapper);
+ });
+
+ it("creates independent instances", async () => {
+ const formData1 = await newFormData();
+ const formData2 = await newFormData();
+
+ await formData1.setup();
+ await formData2.setup();
+
+ formData1.append("test1", "value1");
+ formData2.append("test2", "value2");
+
+ const request1 = formData1.getRequest() as { body: FormData };
+ const request2 = formData2.getRequest() as { body: FormData };
+
+ const entries1 = Array.from(request1.body.entries());
+ const entries2 = Array.from(request2.body.entries());
+
+ expect(entries1).toHaveLength(1);
+ expect(entries2).toHaveLength(1);
+ expect(entries1[0][0]).toBe("test1");
+ expect(entries2[0][0]).toBe("test2");
+ });
+ });
+});
diff --git a/skyvern-ts/client/tests/unit/test-file.txt b/skyvern-ts/client/tests/unit/test-file.txt
new file mode 100644
index 00000000..c66d471e
--- /dev/null
+++ b/skyvern-ts/client/tests/unit/test-file.txt
@@ -0,0 +1 @@
+This is a test file!
diff --git a/skyvern-ts/client/tests/wire/main.test.ts b/skyvern-ts/client/tests/wire/main.test.ts
index c8405105..9a8c48bd 100644
--- a/skyvern-ts/client/tests/wire/main.test.ts
+++ b/skyvern-ts/client/tests/wire/main.test.ts
@@ -1207,7 +1207,7 @@ describe("SkyvernClient", () => {
.build();
await expect(async () => {
- return await client.retryRunWebhook("run_id");
+ return await client.retryRunWebhook("run_id", undefined);
}).rejects.toThrow(Skyvern.UnprocessableEntityError);
});
diff --git a/skyvern-ts/client/tests/wire/workflows.test.ts b/skyvern-ts/client/tests/wire/workflows.test.ts
deleted file mode 100644
index 8cc25256..00000000
--- a/skyvern-ts/client/tests/wire/workflows.test.ts
+++ /dev/null
@@ -1,48 +0,0 @@
-// This file was auto-generated by Fern from our API Definition.
-
-import * as Skyvern from "../../src/api/index";
-import { SkyvernClient } from "../../src/Client";
-import { mockServerPool } from "../mock-server/MockServerPool";
-
-describe("Workflows", () => {
- test("setWorkflowTemplateStatus (1)", async () => {
- const server = mockServerPool.createServer();
- const client = new SkyvernClient({ apiKey: "test", environment: server.baseUrl });
-
- const rawResponseBody = { key: "value" };
- server
- .mockEndpoint()
- .put("/v1/workflows/workflow_permanent_id/template")
- .respondWith()
- .statusCode(200)
- .jsonBody(rawResponseBody)
- .build();
-
- const response = await client.workflows.setWorkflowTemplateStatus("workflow_permanent_id", {
- is_template: true,
- });
- expect(response).toEqual({
- key: "value",
- });
- });
-
- test("setWorkflowTemplateStatus (2)", async () => {
- const server = mockServerPool.createServer();
- const client = new SkyvernClient({ apiKey: "test", environment: server.baseUrl });
-
- const rawResponseBody = { key: "value" };
- server
- .mockEndpoint()
- .put("/v1/workflows/workflow_permanent_id/template")
- .respondWith()
- .statusCode(422)
- .jsonBody(rawResponseBody)
- .build();
-
- await expect(async () => {
- return await client.workflows.setWorkflowTemplateStatus("workflow_permanent_id", {
- is_template: true,
- });
- }).rejects.toThrow(Skyvern.UnprocessableEntityError);
- });
-});
diff --git a/skyvern/client/__init__.py b/skyvern/client/__init__.py
index 2fdb2b0a..6b25f479 100644
--- a/skyvern/client/__init__.py
+++ b/skyvern/client/__init__.py
@@ -283,6 +283,7 @@ if typing.TYPE_CHECKING:
PromptAction,
PromptBranchCriteria,
ProxyLocation,
+ RetryRunWebhookRequest,
RunEngine,
RunSdkActionRequestAction,
RunSdkActionRequestAction_AiAct,
@@ -352,6 +353,7 @@ if typing.TYPE_CHECKING:
TotpType,
UploadFileAction,
UploadFileActionData,
+ UploadFileResponse,
UploadToS3Block,
UploadToS3BlockYaml,
UrlBlock,
@@ -496,7 +498,7 @@ if typing.TYPE_CHECKING:
WorkflowStatus,
)
from .errors import BadRequestError, ConflictError, ForbiddenError, NotFoundError, UnprocessableEntityError
- from . import scripts, workflows
+ from . import scripts
from .client import AsyncSkyvern, Skyvern
from .environment import SkyvernEnvironment
from .version import __version__
@@ -782,6 +784,7 @@ _dynamic_imports: typing.Dict[str, str] = {
"PromptAction": ".types",
"PromptBranchCriteria": ".types",
"ProxyLocation": ".types",
+ "RetryRunWebhookRequest": ".types",
"RunEngine": ".types",
"RunSdkActionRequestAction": ".types",
"RunSdkActionRequestAction_AiAct": ".types",
@@ -854,6 +857,7 @@ _dynamic_imports: typing.Dict[str, str] = {
"UnprocessableEntityError": ".errors",
"UploadFileAction": ".types",
"UploadFileActionData": ".types",
+ "UploadFileResponse": ".types",
"UploadToS3Block": ".types",
"UploadToS3BlockYaml": ".types",
"UrlBlock": ".types",
@@ -998,7 +1002,6 @@ _dynamic_imports: typing.Dict[str, str] = {
"WorkflowStatus": ".types",
"__version__": ".version",
"scripts": ".scripts",
- "workflows": ".workflows",
}
@@ -1305,6 +1308,7 @@ __all__ = [
"PromptAction",
"PromptBranchCriteria",
"ProxyLocation",
+ "RetryRunWebhookRequest",
"RunEngine",
"RunSdkActionRequestAction",
"RunSdkActionRequestAction_AiAct",
@@ -1377,6 +1381,7 @@ __all__ = [
"UnprocessableEntityError",
"UploadFileAction",
"UploadFileActionData",
+ "UploadFileResponse",
"UploadToS3Block",
"UploadToS3BlockYaml",
"UrlBlock",
@@ -1521,5 +1526,4 @@ __all__ = [
"WorkflowStatus",
"__version__",
"scripts",
- "workflows",
]
diff --git a/skyvern/client/client.py b/skyvern/client/client.py
index 79c895a9..cfed952d 100644
--- a/skyvern/client/client.py
+++ b/skyvern/client/client.py
@@ -6,6 +6,7 @@ import datetime as dt
import typing
import httpx
+from . import core
from .core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
from .core.request_options import RequestOptions
from .environment import SkyvernEnvironment
@@ -19,6 +20,7 @@ from .types.create_script_response import CreateScriptResponse
from .types.credential_response import CredentialResponse
from .types.get_run_response import GetRunResponse
from .types.proxy_location import ProxyLocation
+from .types.retry_run_webhook_request import RetryRunWebhookRequest
from .types.run_engine import RunEngine
from .types.run_sdk_action_request_action import RunSdkActionRequestAction
from .types.run_sdk_action_response import RunSdkActionResponse
@@ -30,6 +32,7 @@ from .types.task_run_request_data_extraction_schema import TaskRunRequestDataExt
from .types.task_run_request_proxy_location import TaskRunRequestProxyLocation
from .types.task_run_response import TaskRunResponse
from .types.totp_code import TotpCode
+from .types.upload_file_response import UploadFileResponse
from .types.workflow import Workflow
from .types.workflow_create_yaml_request import WorkflowCreateYamlRequest
from .types.workflow_run_request_proxy_location import WorkflowRunRequestProxyLocation
@@ -39,7 +42,6 @@ from .types.workflow_status import WorkflowStatus
if typing.TYPE_CHECKING:
from .scripts.client import AsyncScriptsClient, ScriptsClient
- from .workflows.client import AsyncWorkflowsClient, WorkflowsClient
# this is used as the default value for optional parameters
OMIT = typing.cast(typing.Any, ...)
@@ -110,7 +112,6 @@ class Skyvern:
timeout=_defaulted_timeout,
)
self._raw_client = RawSkyvern(client_wrapper=self._client_wrapper)
- self._workflows: typing.Optional[WorkflowsClient] = None
self._scripts: typing.Optional[ScriptsClient] = None
@property
@@ -793,7 +794,7 @@ class Skyvern:
self,
run_id: str,
*,
- webhook_url: typing.Optional[str] = None,
+ request: typing.Optional[RetryRunWebhookRequest] = None,
request_options: typing.Optional[RequestOptions] = None,
) -> typing.Optional[typing.Any]:
"""
@@ -804,6 +805,8 @@ class Skyvern:
run_id : str
The id of the task run or the workflow run.
+ request : typing.Optional[RetryRunWebhookRequest]
+
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
@@ -814,16 +817,17 @@ class Skyvern:
Examples
--------
- from skyvern import Skyvern
+ from skyvern import RetryRunWebhookRequest, Skyvern
client = Skyvern(
api_key="YOUR_API_KEY",
)
client.retry_run_webhook(
run_id="tsk_123",
+ request=RetryRunWebhookRequest(),
)
"""
- _response = self._raw_client.retry_run_webhook(run_id, webhook_url=webhook_url, request_options=request_options)
+ _response = self._raw_client.retry_run_webhook(run_id, request=request, request_options=request_options)
return _response.data
def get_run_timeline(
@@ -859,6 +863,35 @@ class Skyvern:
_response = self._raw_client.get_run_timeline(run_id, request_options=request_options)
return _response.data
+ def upload_file(
+ self, *, file: core.File, request_options: typing.Optional[RequestOptions] = None
+ ) -> UploadFileResponse:
+ """
+ Parameters
+ ----------
+ file : core.File
+ See core.File for more documentation
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ UploadFileResponse
+ Successful Response
+
+ Examples
+ --------
+ from skyvern import Skyvern
+
+ client = Skyvern(
+ api_key="YOUR_API_KEY",
+ )
+ client.upload_file()
+ """
+ _response = self._raw_client.upload_file(file=file, request_options=request_options)
+ return _response.data
+
def list_browser_profiles(
self, *, include_deleted: typing.Optional[bool] = None, request_options: typing.Optional[RequestOptions] = None
) -> typing.List[BrowserProfile]:
@@ -1860,14 +1893,6 @@ class Skyvern:
)
return _response.data
- @property
- def workflows(self):
- if self._workflows is None:
- from .workflows.client import WorkflowsClient # noqa: E402
-
- self._workflows = WorkflowsClient(client_wrapper=self._client_wrapper)
- return self._workflows
-
@property
def scripts(self):
if self._scripts is None:
@@ -1943,7 +1968,6 @@ class AsyncSkyvern:
timeout=_defaulted_timeout,
)
self._raw_client = AsyncRawSkyvern(client_wrapper=self._client_wrapper)
- self._workflows: typing.Optional[AsyncWorkflowsClient] = None
self._scripts: typing.Optional[AsyncScriptsClient] = None
@property
@@ -2708,7 +2732,7 @@ class AsyncSkyvern:
self,
run_id: str,
*,
- webhook_url: typing.Optional[str] = None,
+ request: typing.Optional[RetryRunWebhookRequest] = None,
request_options: typing.Optional[RequestOptions] = None,
) -> typing.Optional[typing.Any]:
"""
@@ -2719,6 +2743,8 @@ class AsyncSkyvern:
run_id : str
The id of the task run or the workflow run.
+ request : typing.Optional[RetryRunWebhookRequest]
+
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
@@ -2731,7 +2757,7 @@ class AsyncSkyvern:
--------
import asyncio
- from skyvern import AsyncSkyvern
+ from skyvern import AsyncSkyvern, RetryRunWebhookRequest
client = AsyncSkyvern(
api_key="YOUR_API_KEY",
@@ -2741,14 +2767,13 @@ class AsyncSkyvern:
async def main() -> None:
await client.retry_run_webhook(
run_id="tsk_123",
+ request=RetryRunWebhookRequest(),
)
asyncio.run(main())
"""
- _response = await self._raw_client.retry_run_webhook(
- run_id, webhook_url=webhook_url, request_options=request_options
- )
+ _response = await self._raw_client.retry_run_webhook(run_id, request=request, request_options=request_options)
return _response.data
async def get_run_timeline(
@@ -2792,6 +2817,43 @@ class AsyncSkyvern:
_response = await self._raw_client.get_run_timeline(run_id, request_options=request_options)
return _response.data
+ async def upload_file(
+ self, *, file: core.File, request_options: typing.Optional[RequestOptions] = None
+ ) -> UploadFileResponse:
+ """
+ Parameters
+ ----------
+ file : core.File
+ See core.File for more documentation
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ UploadFileResponse
+ Successful Response
+
+ Examples
+ --------
+ import asyncio
+
+ from skyvern import AsyncSkyvern
+
+ client = AsyncSkyvern(
+ api_key="YOUR_API_KEY",
+ )
+
+
+ async def main() -> None:
+ await client.upload_file()
+
+
+ asyncio.run(main())
+ """
+ _response = await self._raw_client.upload_file(file=file, request_options=request_options)
+ return _response.data
+
async def list_browser_profiles(
self, *, include_deleted: typing.Optional[bool] = None, request_options: typing.Optional[RequestOptions] = None
) -> typing.List[BrowserProfile]:
@@ -3957,14 +4019,6 @@ class AsyncSkyvern:
)
return _response.data
- @property
- def workflows(self):
- if self._workflows is None:
- from .workflows.client import AsyncWorkflowsClient # noqa: E402
-
- self._workflows = AsyncWorkflowsClient(client_wrapper=self._client_wrapper)
- return self._workflows
-
@property
def scripts(self):
if self._scripts is None:
diff --git a/skyvern/client/core/client_wrapper.py b/skyvern/client/core/client_wrapper.py
index 7513f68e..50605e7b 100644
--- a/skyvern/client/core/client_wrapper.py
+++ b/skyvern/client/core/client_wrapper.py
@@ -22,10 +22,10 @@ class BaseClientWrapper:
def get_headers(self) -> typing.Dict[str, str]:
headers: typing.Dict[str, str] = {
- "User-Agent": "skyvern/1.0.3",
+ "User-Agent": "skyvern/1.0.6",
"X-Fern-Language": "Python",
"X-Fern-SDK-Name": "skyvern",
- "X-Fern-SDK-Version": "1.0.3",
+ "X-Fern-SDK-Version": "1.0.6",
**(self.get_custom_headers() or {}),
}
if self._api_key is not None:
diff --git a/skyvern/client/raw_client.py b/skyvern/client/raw_client.py
index 79827801..692c7172 100644
--- a/skyvern/client/raw_client.py
+++ b/skyvern/client/raw_client.py
@@ -4,6 +4,7 @@ import datetime as dt
import typing
from json.decoder import JSONDecodeError
+from . import core
from .core.api_error import ApiError
from .core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
from .core.http_response import AsyncHttpResponse, HttpResponse
@@ -25,6 +26,7 @@ from .types.create_script_response import CreateScriptResponse
from .types.credential_response import CredentialResponse
from .types.get_run_response import GetRunResponse
from .types.proxy_location import ProxyLocation
+from .types.retry_run_webhook_request import RetryRunWebhookRequest
from .types.run_engine import RunEngine
from .types.run_sdk_action_request_action import RunSdkActionRequestAction
from .types.run_sdk_action_response import RunSdkActionResponse
@@ -36,6 +38,7 @@ from .types.task_run_request_data_extraction_schema import TaskRunRequestDataExt
from .types.task_run_request_proxy_location import TaskRunRequestProxyLocation
from .types.task_run_response import TaskRunResponse
from .types.totp_code import TotpCode
+from .types.upload_file_response import UploadFileResponse
from .types.workflow import Workflow
from .types.workflow_create_yaml_request import WorkflowCreateYamlRequest
from .types.workflow_run_request_proxy_location import WorkflowRunRequestProxyLocation
@@ -960,7 +963,7 @@ class RawSkyvern:
self,
run_id: str,
*,
- webhook_url: typing.Optional[str] = None,
+ request: typing.Optional[RetryRunWebhookRequest] = None,
request_options: typing.Optional[RequestOptions] = None,
) -> HttpResponse[typing.Optional[typing.Any]]:
"""
@@ -971,6 +974,8 @@ class RawSkyvern:
run_id : str
The id of the task run or the workflow run.
+ request : typing.Optional[RetryRunWebhookRequest]
+
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
@@ -979,18 +984,17 @@ class RawSkyvern:
HttpResponse[typing.Optional[typing.Any]]
Successful Response
"""
- request_kwargs: dict[str, typing.Any] = {}
- if webhook_url is not None:
- request_kwargs = {
- "json": {"webhook_url": webhook_url},
- "headers": {"content-type": "application/json"},
- "omit": OMIT,
- }
_response = self._client_wrapper.httpx_client.request(
f"v1/runs/{jsonable_encoder(run_id)}/retry_webhook",
method="POST",
+ json=convert_and_respect_annotation_metadata(
+ object_=request, annotation=RetryRunWebhookRequest, direction="write"
+ ),
+ headers={
+ "content-type": "application/json",
+ },
request_options=request_options,
- **request_kwargs,
+ omit=OMIT,
)
try:
if _response is None or not _response.text.strip():
@@ -1092,6 +1096,60 @@ class RawSkyvern:
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+ def upload_file(
+ self, *, file: core.File, request_options: typing.Optional[RequestOptions] = None
+ ) -> HttpResponse[UploadFileResponse]:
+ """
+ Parameters
+ ----------
+ file : core.File
+ See core.File for more documentation
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ HttpResponse[UploadFileResponse]
+ Successful Response
+ """
+ _response = self._client_wrapper.httpx_client.request(
+ "v1/upload_file",
+ method="POST",
+ data={},
+ files={
+ "file": file,
+ },
+ request_options=request_options,
+ omit=OMIT,
+ force_multipart=True,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ UploadFileResponse,
+ parse_obj_as(
+ type_=UploadFileResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return HttpResponse(response=_response, data=_data)
+ if _response.status_code == 422:
+ raise UnprocessableEntityError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ typing.Optional[typing.Any],
+ parse_obj_as(
+ type_=typing.Optional[typing.Any], # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
def list_browser_profiles(
self, *, include_deleted: typing.Optional[bool] = None, request_options: typing.Optional[RequestOptions] = None
) -> HttpResponse[typing.List[BrowserProfile]]:
@@ -3492,7 +3550,7 @@ class AsyncRawSkyvern:
self,
run_id: str,
*,
- webhook_url: typing.Optional[str] = None,
+ request: typing.Optional[RetryRunWebhookRequest] = None,
request_options: typing.Optional[RequestOptions] = None,
) -> AsyncHttpResponse[typing.Optional[typing.Any]]:
"""
@@ -3503,6 +3561,8 @@ class AsyncRawSkyvern:
run_id : str
The id of the task run or the workflow run.
+ request : typing.Optional[RetryRunWebhookRequest]
+
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
@@ -3511,18 +3571,17 @@ class AsyncRawSkyvern:
AsyncHttpResponse[typing.Optional[typing.Any]]
Successful Response
"""
- request_kwargs: dict[str, typing.Any] = {}
- if webhook_url is not None:
- request_kwargs = {
- "json": {"webhook_url": webhook_url},
- "headers": {"content-type": "application/json"},
- "omit": OMIT,
- }
_response = await self._client_wrapper.httpx_client.request(
f"v1/runs/{jsonable_encoder(run_id)}/retry_webhook",
method="POST",
+ json=convert_and_respect_annotation_metadata(
+ object_=request, annotation=RetryRunWebhookRequest, direction="write"
+ ),
+ headers={
+ "content-type": "application/json",
+ },
request_options=request_options,
- **request_kwargs,
+ omit=OMIT,
)
try:
if _response is None or not _response.text.strip():
@@ -3624,6 +3683,60 @@ class AsyncRawSkyvern:
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+ async def upload_file(
+ self, *, file: core.File, request_options: typing.Optional[RequestOptions] = None
+ ) -> AsyncHttpResponse[UploadFileResponse]:
+ """
+ Parameters
+ ----------
+ file : core.File
+ See core.File for more documentation
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ AsyncHttpResponse[UploadFileResponse]
+ Successful Response
+ """
+ _response = await self._client_wrapper.httpx_client.request(
+ "v1/upload_file",
+ method="POST",
+ data={},
+ files={
+ "file": file,
+ },
+ request_options=request_options,
+ omit=OMIT,
+ force_multipart=True,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ UploadFileResponse,
+ parse_obj_as(
+ type_=UploadFileResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return AsyncHttpResponse(response=_response, data=_data)
+ if _response.status_code == 422:
+ raise UnprocessableEntityError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ typing.Optional[typing.Any],
+ parse_obj_as(
+ type_=typing.Optional[typing.Any], # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
async def list_browser_profiles(
self, *, include_deleted: typing.Optional[bool] = None, request_options: typing.Optional[RequestOptions] = None
) -> AsyncHttpResponse[typing.List[BrowserProfile]]:
diff --git a/skyvern/client/types/__init__.py b/skyvern/client/types/__init__.py
index efa99655..f18c4ed2 100644
--- a/skyvern/client/types/__init__.py
+++ b/skyvern/client/types/__init__.py
@@ -310,6 +310,7 @@ if typing.TYPE_CHECKING:
from .prompt_action import PromptAction
from .prompt_branch_criteria import PromptBranchCriteria
from .proxy_location import ProxyLocation
+ from .retry_run_webhook_request import RetryRunWebhookRequest
from .run_engine import RunEngine
from .run_sdk_action_request_action import (
RunSdkActionRequestAction,
@@ -385,6 +386,7 @@ if typing.TYPE_CHECKING:
from .totp_type import TotpType
from .upload_file_action import UploadFileAction
from .upload_file_action_data import UploadFileActionData
+ from .upload_file_response import UploadFileResponse
from .upload_to_s3block import UploadToS3Block
from .upload_to_s3block_yaml import UploadToS3BlockYaml
from .url_block import UrlBlock
@@ -818,6 +820,7 @@ _dynamic_imports: typing.Dict[str, str] = {
"PromptAction": ".prompt_action",
"PromptBranchCriteria": ".prompt_branch_criteria",
"ProxyLocation": ".proxy_location",
+ "RetryRunWebhookRequest": ".retry_run_webhook_request",
"RunEngine": ".run_engine",
"RunSdkActionRequestAction": ".run_sdk_action_request_action",
"RunSdkActionRequestAction_AiAct": ".run_sdk_action_request_action",
@@ -887,6 +890,7 @@ _dynamic_imports: typing.Dict[str, str] = {
"TotpType": ".totp_type",
"UploadFileAction": ".upload_file_action",
"UploadFileActionData": ".upload_file_action_data",
+ "UploadFileResponse": ".upload_file_response",
"UploadToS3Block": ".upload_to_s3block",
"UploadToS3BlockYaml": ".upload_to_s3block_yaml",
"UrlBlock": ".url_block",
@@ -1330,6 +1334,7 @@ __all__ = [
"PromptAction",
"PromptBranchCriteria",
"ProxyLocation",
+ "RetryRunWebhookRequest",
"RunEngine",
"RunSdkActionRequestAction",
"RunSdkActionRequestAction_AiAct",
@@ -1399,6 +1404,7 @@ __all__ = [
"TotpType",
"UploadFileAction",
"UploadFileActionData",
+ "UploadFileResponse",
"UploadToS3Block",
"UploadToS3BlockYaml",
"UrlBlock",
diff --git a/skyvern/client/types/prompt_action.py b/skyvern/client/types/prompt_action.py
index c494ade5..9b9c2110 100644
--- a/skyvern/client/types/prompt_action.py
+++ b/skyvern/client/types/prompt_action.py
@@ -3,9 +3,7 @@
import typing
import pydantic
-import typing_extensions
from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
-from ..core.serialization import FieldMetadata
class PromptAction(UniversalBaseModel):
@@ -18,9 +16,7 @@ class PromptAction(UniversalBaseModel):
The prompt to send to the LLM
"""
- schema_: typing_extensions.Annotated[
- typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]], FieldMetadata(alias="schema")
- ] = pydantic.Field(default=None)
+ response_schema: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = pydantic.Field(default=None)
"""
Optional JSON schema to structure the response
"""
diff --git a/skyvern/client/types/retry_run_webhook_request.py b/skyvern/client/types/retry_run_webhook_request.py
new file mode 100644
index 00000000..e16ac938
--- /dev/null
+++ b/skyvern/client/types/retry_run_webhook_request.py
@@ -0,0 +1,22 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
+
+
+class RetryRunWebhookRequest(UniversalBaseModel):
+ webhook_url: typing.Optional[str] = pydantic.Field(default=None)
+ """
+ Optional webhook URL to send the payload to instead of the stored configuration
+ """
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/skyvern/client/types/run_sdk_action_request_action.py b/skyvern/client/types/run_sdk_action_request_action.py
index d591075d..9b5897a2 100644
--- a/skyvern/client/types/run_sdk_action_request_action.py
+++ b/skyvern/client/types/run_sdk_action_request_action.py
@@ -5,9 +5,7 @@ from __future__ import annotations
import typing
import pydantic
-import typing_extensions
from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
-from ..core.serialization import FieldMetadata
from .act_action_data import ActActionData
from .click_action_data import ClickActionData
from .extract_action_data import ExtractActionData
@@ -172,9 +170,7 @@ class RunSdkActionRequestAction_Prompt(UniversalBaseModel):
type: typing.Literal["prompt"] = "prompt"
prompt: str
- schema_: typing_extensions.Annotated[
- typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]], FieldMetadata(alias="schema")
- ] = None
+ response_schema: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = None
model: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = None
if IS_PYDANTIC_V2:
diff --git a/skyvern/client/types/upload_file_response.py b/skyvern/client/types/upload_file_response.py
new file mode 100644
index 00000000..5778fb01
--- /dev/null
+++ b/skyvern/client/types/upload_file_response.py
@@ -0,0 +1,29 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+import typing_extensions
+from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
+from ..core.serialization import FieldMetadata
+
+
+class UploadFileResponse(UniversalBaseModel):
+ s3uri: typing_extensions.Annotated[str, FieldMetadata(alias="s3_uri")] = pydantic.Field()
+ """
+ S3 URI where the file was uploaded
+ """
+
+ presigned_url: str = pydantic.Field()
+ """
+ Presigned URL to access the uploaded file
+ """
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/skyvern/client/workflows/__init__.py b/skyvern/client/workflows/__init__.py
deleted file mode 100644
index 5cde0202..00000000
--- a/skyvern/client/workflows/__init__.py
+++ /dev/null
@@ -1,4 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-# isort: skip_file
-
diff --git a/skyvern/client/workflows/client.py b/skyvern/client/workflows/client.py
deleted file mode 100644
index 46edb7a0..00000000
--- a/skyvern/client/workflows/client.py
+++ /dev/null
@@ -1,127 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
-from ..core.request_options import RequestOptions
-from .raw_client import AsyncRawWorkflowsClient, RawWorkflowsClient
-
-
-class WorkflowsClient:
- def __init__(self, *, client_wrapper: SyncClientWrapper):
- self._raw_client = RawWorkflowsClient(client_wrapper=client_wrapper)
-
- @property
- def with_raw_response(self) -> RawWorkflowsClient:
- """
- Retrieves a raw implementation of this client that returns raw responses.
-
- Returns
- -------
- RawWorkflowsClient
- """
- return self._raw_client
-
- def set_workflow_template_status(
- self, workflow_permanent_id: str, *, is_template: bool, request_options: typing.Optional[RequestOptions] = None
- ) -> typing.Dict[str, typing.Optional[typing.Any]]:
- """
- Set or unset a workflow as a template.
-
- Template status is stored at the workflow_permanent_id level (not per-version),
- meaning all versions of a workflow share the same template status.
-
- Parameters
- ----------
- workflow_permanent_id : str
-
- is_template : bool
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- typing.Dict[str, typing.Optional[typing.Any]]
- Successful Response
-
- Examples
- --------
- from skyvern import Skyvern
-
- client = Skyvern(
- api_key="YOUR_API_KEY",
- )
- client.workflows.set_workflow_template_status(
- workflow_permanent_id="workflow_permanent_id",
- is_template=True,
- )
- """
- _response = self._raw_client.set_workflow_template_status(
- workflow_permanent_id, is_template=is_template, request_options=request_options
- )
- return _response.data
-
-
-class AsyncWorkflowsClient:
- def __init__(self, *, client_wrapper: AsyncClientWrapper):
- self._raw_client = AsyncRawWorkflowsClient(client_wrapper=client_wrapper)
-
- @property
- def with_raw_response(self) -> AsyncRawWorkflowsClient:
- """
- Retrieves a raw implementation of this client that returns raw responses.
-
- Returns
- -------
- AsyncRawWorkflowsClient
- """
- return self._raw_client
-
- async def set_workflow_template_status(
- self, workflow_permanent_id: str, *, is_template: bool, request_options: typing.Optional[RequestOptions] = None
- ) -> typing.Dict[str, typing.Optional[typing.Any]]:
- """
- Set or unset a workflow as a template.
-
- Template status is stored at the workflow_permanent_id level (not per-version),
- meaning all versions of a workflow share the same template status.
-
- Parameters
- ----------
- workflow_permanent_id : str
-
- is_template : bool
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- typing.Dict[str, typing.Optional[typing.Any]]
- Successful Response
-
- Examples
- --------
- import asyncio
-
- from skyvern import AsyncSkyvern
-
- client = AsyncSkyvern(
- api_key="YOUR_API_KEY",
- )
-
-
- async def main() -> None:
- await client.workflows.set_workflow_template_status(
- workflow_permanent_id="workflow_permanent_id",
- is_template=True,
- )
-
-
- asyncio.run(main())
- """
- _response = await self._raw_client.set_workflow_template_status(
- workflow_permanent_id, is_template=is_template, request_options=request_options
- )
- return _response.data
diff --git a/skyvern/client/workflows/raw_client.py b/skyvern/client/workflows/raw_client.py
deleted file mode 100644
index c8fb091e..00000000
--- a/skyvern/client/workflows/raw_client.py
+++ /dev/null
@@ -1,136 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-from json.decoder import JSONDecodeError
-
-from ..core.api_error import ApiError
-from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
-from ..core.http_response import AsyncHttpResponse, HttpResponse
-from ..core.jsonable_encoder import jsonable_encoder
-from ..core.pydantic_utilities import parse_obj_as
-from ..core.request_options import RequestOptions
-from ..errors.unprocessable_entity_error import UnprocessableEntityError
-
-
-class RawWorkflowsClient:
- def __init__(self, *, client_wrapper: SyncClientWrapper):
- self._client_wrapper = client_wrapper
-
- def set_workflow_template_status(
- self, workflow_permanent_id: str, *, is_template: bool, request_options: typing.Optional[RequestOptions] = None
- ) -> HttpResponse[typing.Dict[str, typing.Optional[typing.Any]]]:
- """
- Set or unset a workflow as a template.
-
- Template status is stored at the workflow_permanent_id level (not per-version),
- meaning all versions of a workflow share the same template status.
-
- Parameters
- ----------
- workflow_permanent_id : str
-
- is_template : bool
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- HttpResponse[typing.Dict[str, typing.Optional[typing.Any]]]
- Successful Response
- """
- _response = self._client_wrapper.httpx_client.request(
- f"v1/workflows/{jsonable_encoder(workflow_permanent_id)}/template",
- method="PUT",
- params={
- "is_template": is_template,
- },
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- _data = typing.cast(
- typing.Dict[str, typing.Optional[typing.Any]],
- parse_obj_as(
- type_=typing.Dict[str, typing.Optional[typing.Any]], # type: ignore
- object_=_response.json(),
- ),
- )
- return HttpResponse(response=_response, data=_data)
- if _response.status_code == 422:
- raise UnprocessableEntityError(
- headers=dict(_response.headers),
- body=typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- ),
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
- raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
-
-
-class AsyncRawWorkflowsClient:
- def __init__(self, *, client_wrapper: AsyncClientWrapper):
- self._client_wrapper = client_wrapper
-
- async def set_workflow_template_status(
- self, workflow_permanent_id: str, *, is_template: bool, request_options: typing.Optional[RequestOptions] = None
- ) -> AsyncHttpResponse[typing.Dict[str, typing.Optional[typing.Any]]]:
- """
- Set or unset a workflow as a template.
-
- Template status is stored at the workflow_permanent_id level (not per-version),
- meaning all versions of a workflow share the same template status.
-
- Parameters
- ----------
- workflow_permanent_id : str
-
- is_template : bool
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- AsyncHttpResponse[typing.Dict[str, typing.Optional[typing.Any]]]
- Successful Response
- """
- _response = await self._client_wrapper.httpx_client.request(
- f"v1/workflows/{jsonable_encoder(workflow_permanent_id)}/template",
- method="PUT",
- params={
- "is_template": is_template,
- },
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- _data = typing.cast(
- typing.Dict[str, typing.Optional[typing.Any]],
- parse_obj_as(
- type_=typing.Dict[str, typing.Optional[typing.Any]], # type: ignore
- object_=_response.json(),
- ),
- )
- return AsyncHttpResponse(response=_response, data=_data)
- if _response.status_code == 422:
- raise UnprocessableEntityError(
- headers=dict(_response.headers),
- body=typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- ),
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
- raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
diff --git a/uv.lock b/uv.lock
index b5478b2b..46372eaf 100644
--- a/uv.lock
+++ b/uv.lock
@@ -5082,7 +5082,7 @@ wheels = [
[[package]]
name = "skyvern"
-version = "1.0.3"
+version = "1.0.6"
source = { editable = "." }
dependencies = [
{ name = "aioboto3" },