From 5d2bb073713d8e275978f6f1ad74091944889558 Mon Sep 17 00:00:00 2001 From: Stanislav Novosad Date: Wed, 17 Dec 2025 14:11:39 -0700 Subject: [PATCH] SDK: docs and improvements (#4310) --- README.md | 67 +++ skyvern-ts/client/README.md | 2 +- skyvern-ts/client/package-lock.json | 451 +++++++++--------- skyvern-ts/client/reference.md | 77 +++ skyvern-ts/client/src/Client.ts | 12 + .../client/requests/GetWorkflowsRequest.ts | 2 + skyvern-ts/client/src/api/resources/index.ts | 2 + .../api/resources/workflows/client/Client.ts | 112 +++++ .../api/resources/workflows/client/index.ts | 1 + ...wsWorkflowPermanentIdTemplatePutRequest.ts | 11 + .../workflows/client/requests/index.ts | 1 + .../src/api/resources/workflows/index.ts | 1 + skyvern-ts/client/src/api/types/Action.ts | 1 + skyvern-ts/client/src/api/types/Artifact.ts | 1 + skyvern-ts/client/src/api/types/Workflow.ts | 1 + skyvern-ts/client/src/library/Skyvern.ts | 22 +- .../client/src/library/SkyvernBrowserPage.ts | 275 +++++++++-- .../src/library/SkyvernBrowserPageAgent.ts | 150 ++++-- skyvern-ts/client/tests/wire/main.test.ts | 11 + .../client/tests/wire/workflows.test.ts | 48 ++ skyvern/client/__init__.py | 4 +- skyvern/client/client.py | 29 ++ skyvern/client/raw_client.py | 8 + skyvern/client/types/action.py | 1 + skyvern/client/types/artifact.py | 1 + skyvern/client/types/workflow.py | 1 + skyvern/client/workflows/__init__.py | 4 + skyvern/client/workflows/client.py | 127 +++++ skyvern/client/workflows/raw_client.py | 136 ++++++ skyvern/forge/sdk/routes/sdk.py | 2 +- skyvern/forge/sdk/schemas/sdk_actions.py | 2 +- skyvern/library/skyvern_browser_page_ai.py | 2 +- 32 files changed, 1274 insertions(+), 291 deletions(-) create mode 100644 skyvern-ts/client/src/api/resources/workflows/client/Client.ts create mode 100644 skyvern-ts/client/src/api/resources/workflows/client/index.ts create mode 100644 skyvern-ts/client/src/api/resources/workflows/client/requests/SetWorkflowTemplateStatusV1WorkflowsWorkflowPermanentIdTemplatePutRequest.ts create mode 100644 skyvern-ts/client/src/api/resources/workflows/client/requests/index.ts create mode 100644 skyvern-ts/client/src/api/resources/workflows/index.ts create mode 100644 skyvern-ts/client/tests/wire/workflows.test.ts create mode 100644 skyvern/client/workflows/__init__.py create mode 100644 skyvern/client/workflows/client.py create mode 100644 skyvern/client/workflows/raw_client.py diff --git a/README.md b/README.md index 41017b8b..0a7569fa 100644 --- a/README.md +++ b/README.md @@ -141,6 +141,73 @@ task = await skyvern.run_task(prompt="Find the top post on hackernews today") print(task) ``` +## SDK + +**Installation:** +- Python: `pip install skyvern` then run `skyvern quickstart` for local setup +- TypeScript: `npm install @skyvern/client` + +Skyvern provides SDKs for both Python and TypeScript to integrate browser automation into your applications. + +### Python SDK + +```python +from skyvern import Skyvern + +# Connect to Skyvern Cloud +skyvern = Skyvern(api_key="your-api-key") + +# Or run locally +skyvern = Skyvern.local() + +# Launch a cloud browser +browser = await skyvern.launch_cloud_browser() +page = await browser.get_working_page() + +# Use AI-powered actions for complex workflows +await page.agent.run_task("Navigate to the most recent invoice and download it") + +# Or mix with Playwright actions +await page.goto("https://example.com") +await page.click("#button") +``` + +### TypeScript SDK + +```typescript +import { Skyvern } from "@skyvern/client"; + +// Connect to Skyvern Cloud +const skyvern = new Skyvern({ apiKey: "your-api-key" }); + +// Launch a cloud browser +const browser = await skyvern.launchCloudBrowser(); +const page = await browser.getWorkingPage(); + +// Use AI-powered actions for complex workflows +await page.agent.runTask("Navigate to the most recent invoice and download it"); + +// Or mix with Playwright actions +await page.goto("https://example.com"); +await page.click("#button"); +``` + +Skyvern enhances Playwright methods with AI capabilities. Use regular Playwright syntax with a `prompt` parameter to make any action AI-powered: + +```python +# Traditional Playwright - uses selectors +await page.click("#submit-button") + +# AI-augmented Playwright - uses natural language +await page.click(prompt="Click on the Submit button") +await page.fill(prompt="Enter email address", value="user@example.com") + +# Mix both approaches in the same workflow +await page.goto("https://example.com/dashboard") +await page.click(prompt="Click on the most recent unpaid invoice") +await page.click("#download-button") +``` + ## Advanced Usage ### Control your own browser (Chrome) diff --git a/skyvern-ts/client/README.md b/skyvern-ts/client/README.md index c8ff4998..f92dee52 100644 --- a/skyvern-ts/client/README.md +++ b/skyvern-ts/client/README.md @@ -56,7 +56,7 @@ following namespace: ```typescript import { Skyvern } from "@skyvern/client"; -const request: Skyvern.RunTaskRequest = { +const request: Skyvern.SetWorkflowTemplateStatusV1WorkflowsWorkflowPermanentIdTemplatePutRequest = { ... }; ``` diff --git a/skyvern-ts/client/package-lock.json b/skyvern-ts/client/package-lock.json index 2dff4771..7cf36d76 100644 --- a/skyvern-ts/client/package-lock.json +++ b/skyvern-ts/client/package-lock.json @@ -207,9 +207,9 @@ } }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", - "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.2.tgz", + "integrity": "sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==", "cpu": [ "ppc64" ], @@ -224,9 +224,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz", - "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.2.tgz", + "integrity": "sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==", "cpu": [ "arm" ], @@ -241,9 +241,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz", - "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.2.tgz", + "integrity": "sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==", "cpu": [ "arm64" ], @@ -258,9 +258,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz", - "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.2.tgz", + "integrity": "sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==", "cpu": [ "x64" ], @@ -275,9 +275,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz", - "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.2.tgz", + "integrity": "sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==", "cpu": [ "arm64" ], @@ -292,9 +292,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz", - "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.2.tgz", + "integrity": "sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==", "cpu": [ "x64" ], @@ -309,9 +309,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz", - "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.2.tgz", + "integrity": "sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==", "cpu": [ "arm64" ], @@ -326,9 +326,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz", - "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.2.tgz", + "integrity": "sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==", "cpu": [ "x64" ], @@ -343,9 +343,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz", - "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.2.tgz", + "integrity": "sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==", "cpu": [ "arm" ], @@ -360,9 +360,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz", - "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.2.tgz", + "integrity": "sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==", "cpu": [ "arm64" ], @@ -377,9 +377,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz", - "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.2.tgz", + "integrity": "sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==", "cpu": [ "ia32" ], @@ -394,9 +394,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz", - "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.2.tgz", + "integrity": "sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==", "cpu": [ "loong64" ], @@ -411,9 +411,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz", - "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.2.tgz", + "integrity": "sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==", "cpu": [ "mips64el" ], @@ -428,9 +428,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz", - "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.2.tgz", + "integrity": "sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==", "cpu": [ "ppc64" ], @@ -445,9 +445,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz", - "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.2.tgz", + "integrity": "sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==", "cpu": [ "riscv64" ], @@ -462,9 +462,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz", - "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.2.tgz", + "integrity": "sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==", "cpu": [ "s390x" ], @@ -479,9 +479,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz", - "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.2.tgz", + "integrity": "sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==", "cpu": [ "x64" ], @@ -496,9 +496,9 @@ } }, "node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz", - "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.2.tgz", + "integrity": "sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==", "cpu": [ "arm64" ], @@ -513,9 +513,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz", - "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.2.tgz", + "integrity": "sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==", "cpu": [ "x64" ], @@ -530,9 +530,9 @@ } }, "node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz", - "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.2.tgz", + "integrity": "sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==", "cpu": [ "arm64" ], @@ -547,9 +547,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz", - "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.2.tgz", + "integrity": "sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==", "cpu": [ "x64" ], @@ -564,9 +564,9 @@ } }, "node_modules/@esbuild/openharmony-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz", - "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.2.tgz", + "integrity": "sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==", "cpu": [ "arm64" ], @@ -581,9 +581,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz", - "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.2.tgz", + "integrity": "sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==", "cpu": [ "x64" ], @@ -598,9 +598,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz", - "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.2.tgz", + "integrity": "sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==", "cpu": [ "arm64" ], @@ -615,9 +615,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz", - "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.2.tgz", + "integrity": "sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==", "cpu": [ "ia32" ], @@ -632,9 +632,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz", - "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.2.tgz", + "integrity": "sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==", "cpu": [ "x64" ], @@ -830,9 +830,9 @@ "license": "MIT" }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.53.3.tgz", - "integrity": "sha512-mRSi+4cBjrRLoaal2PnqH82Wqyb+d3HsPUN/W+WslCXsZsyHa9ZeQQX/pQsZaVIWDkPcpV6jJ+3KLbTbgnwv8w==", + "version": "4.53.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.53.5.tgz", + "integrity": "sha512-iDGS/h7D8t7tvZ1t6+WPK04KD0MwzLZrG0se1hzBjSi5fyxlsiggoJHwh18PCFNn7tG43OWb6pdZ6Y+rMlmyNQ==", "cpu": [ "arm" ], @@ -844,9 +844,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.53.3.tgz", - "integrity": "sha512-CbDGaMpdE9sh7sCmTrTUyllhrg65t6SwhjlMJsLr+J8YjFuPmCEjbBSx4Z/e4SmDyH3aB5hGaJUP2ltV/vcs4w==", + "version": "4.53.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.53.5.tgz", + "integrity": "sha512-wrSAViWvZHBMMlWk6EJhvg8/rjxzyEhEdgfMMjREHEq11EtJ6IP6yfcCH57YAEca2Oe3FNCE9DSTgU70EIGmVw==", "cpu": [ "arm64" ], @@ -858,9 +858,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.53.3.tgz", - "integrity": "sha512-Nr7SlQeqIBpOV6BHHGZgYBuSdanCXuw09hon14MGOLGmXAFYjx1wNvquVPmpZnl0tLjg25dEdr4IQ6GgyToCUA==", + "version": "4.53.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.53.5.tgz", + "integrity": "sha512-S87zZPBmRO6u1YXQLwpveZm4JfPpAa6oHBX7/ghSiGH3rz/KDgAu1rKdGutV+WUI6tKDMbaBJomhnT30Y2t4VQ==", "cpu": [ "arm64" ], @@ -872,9 +872,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.53.3.tgz", - "integrity": "sha512-DZ8N4CSNfl965CmPktJ8oBnfYr3F8dTTNBQkRlffnUarJ2ohudQD17sZBa097J8xhQ26AwhHJ5mvUyQW8ddTsQ==", + "version": "4.53.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.53.5.tgz", + "integrity": "sha512-YTbnsAaHo6VrAczISxgpTva8EkfQus0VPEVJCEaboHtZRIb6h6j0BNxRBOwnDciFTZLDPW5r+ZBmhL/+YpTZgA==", "cpu": [ "x64" ], @@ -886,9 +886,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.53.3.tgz", - "integrity": "sha512-yMTrCrK92aGyi7GuDNtGn2sNW+Gdb4vErx4t3Gv/Tr+1zRb8ax4z8GWVRfr3Jw8zJWvpGHNpss3vVlbF58DZ4w==", + "version": "4.53.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.53.5.tgz", + "integrity": "sha512-1T8eY2J8rKJWzaznV7zedfdhD1BqVs1iqILhmHDq/bqCUZsrMt+j8VCTHhP0vdfbHK3e1IQ7VYx3jlKqwlf+vw==", "cpu": [ "arm64" ], @@ -900,9 +900,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.53.3.tgz", - "integrity": "sha512-lMfF8X7QhdQzseM6XaX0vbno2m3hlyZFhwcndRMw8fbAGUGL3WFMBdK0hbUBIUYcEcMhVLr1SIamDeuLBnXS+Q==", + "version": "4.53.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.53.5.tgz", + "integrity": "sha512-sHTiuXyBJApxRn+VFMaw1U+Qsz4kcNlxQ742snICYPrY+DDL8/ZbaC4DVIB7vgZmp3jiDaKA0WpBdP0aqPJoBQ==", "cpu": [ "x64" ], @@ -914,9 +914,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.53.3.tgz", - "integrity": "sha512-k9oD15soC/Ln6d2Wv/JOFPzZXIAIFLp6B+i14KhxAfnq76ajt0EhYc5YPeX6W1xJkAdItcVT+JhKl1QZh44/qw==", + "version": "4.53.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.53.5.tgz", + "integrity": "sha512-dV3T9MyAf0w8zPVLVBptVlzaXxka6xg1f16VAQmjg+4KMSTWDvhimI/Y6mp8oHwNrmnmVl9XxJ/w/mO4uIQONA==", "cpu": [ "arm" ], @@ -928,9 +928,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.53.3.tgz", - "integrity": "sha512-vTNlKq+N6CK/8UktsrFuc+/7NlEYVxgaEgRXVUVK258Z5ymho29skzW1sutgYjqNnquGwVUObAaxae8rZ6YMhg==", + "version": "4.53.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.53.5.tgz", + "integrity": "sha512-wIGYC1x/hyjP+KAu9+ewDI+fi5XSNiUi9Bvg6KGAh2TsNMA3tSEs+Sh6jJ/r4BV/bx/CyWu2ue9kDnIdRyafcQ==", "cpu": [ "arm" ], @@ -942,9 +942,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.53.3.tgz", - "integrity": "sha512-RGrFLWgMhSxRs/EWJMIFM1O5Mzuz3Xy3/mnxJp/5cVhZ2XoCAxJnmNsEyeMJtpK+wu0FJFWz+QF4mjCA7AUQ3w==", + "version": "4.53.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.53.5.tgz", + "integrity": "sha512-Y+qVA0D9d0y2FRNiG9oM3Hut/DgODZbU9I8pLLPwAsU0tUKZ49cyV1tzmB/qRbSzGvY8lpgGkJuMyuhH7Ma+Vg==", "cpu": [ "arm64" ], @@ -956,9 +956,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.53.3.tgz", - "integrity": "sha512-kASyvfBEWYPEwe0Qv4nfu6pNkITLTb32p4yTgzFCocHnJLAHs+9LjUu9ONIhvfT/5lv4YS5muBHyuV84epBo/A==", + "version": "4.53.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.53.5.tgz", + "integrity": "sha512-juaC4bEgJsyFVfqhtGLz8mbopaWD+WeSOYr5E16y+1of6KQjc0BpwZLuxkClqY1i8sco+MdyoXPNiCkQou09+g==", "cpu": [ "arm64" ], @@ -970,9 +970,9 @@ ] }, "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.53.3.tgz", - "integrity": "sha512-JiuKcp2teLJwQ7vkJ95EwESWkNRFJD7TQgYmCnrPtlu50b4XvT5MOmurWNrCj3IFdyjBQ5p9vnrX4JM6I8OE7g==", + "version": "4.53.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.53.5.tgz", + "integrity": "sha512-rIEC0hZ17A42iXtHX+EPJVL/CakHo+tT7W0pbzdAGuWOt2jxDFh7A/lRhsNHBcqL4T36+UiAgwO8pbmn3dE8wA==", "cpu": [ "loong64" ], @@ -984,9 +984,9 @@ ] }, "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.53.3.tgz", - "integrity": "sha512-EoGSa8nd6d3T7zLuqdojxC20oBfNT8nexBbB/rkxgKj5T5vhpAQKKnD+h3UkoMuTyXkP5jTjK/ccNRmQrPNDuw==", + "version": "4.53.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.53.5.tgz", + "integrity": "sha512-T7l409NhUE552RcAOcmJHj3xyZ2h7vMWzcwQI0hvn5tqHh3oSoclf9WgTl+0QqffWFG8MEVZZP1/OBglKZx52Q==", "cpu": [ "ppc64" ], @@ -998,9 +998,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.53.3.tgz", - "integrity": "sha512-4s+Wped2IHXHPnAEbIB0YWBv7SDohqxobiiPA1FIWZpX+w9o2i4LezzH/NkFUl8LRci/8udci6cLq+jJQlh+0g==", + "version": "4.53.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.53.5.tgz", + "integrity": "sha512-7OK5/GhxbnrMcxIFoYfhV/TkknarkYC1hqUw1wU2xUN3TVRLNT5FmBv4KkheSG2xZ6IEbRAhTooTV2+R5Tk0lQ==", "cpu": [ "riscv64" ], @@ -1012,9 +1012,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.53.3.tgz", - "integrity": "sha512-68k2g7+0vs2u9CxDt5ktXTngsxOQkSEV/xBbwlqYcUrAVh6P9EgMZvFsnHy4SEiUl46Xf0IObWVbMvPrr2gw8A==", + "version": "4.53.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.53.5.tgz", + "integrity": "sha512-GwuDBE/PsXaTa76lO5eLJTyr2k8QkPipAyOrs4V/KJufHCZBJ495VCGJol35grx9xryk4V+2zd3Ri+3v7NPh+w==", "cpu": [ "riscv64" ], @@ -1026,9 +1026,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.53.3.tgz", - "integrity": "sha512-VYsFMpULAz87ZW6BVYw3I6sWesGpsP9OPcyKe8ofdg9LHxSbRMd7zrVrr5xi/3kMZtpWL/wC+UIJWJYVX5uTKg==", + "version": "4.53.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.53.5.tgz", + "integrity": "sha512-IAE1Ziyr1qNfnmiQLHBURAD+eh/zH1pIeJjeShleII7Vj8kyEm2PF77o+lf3WTHDpNJcu4IXJxNO0Zluro8bOw==", "cpu": [ "s390x" ], @@ -1040,9 +1040,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.53.3.tgz", - "integrity": "sha512-3EhFi1FU6YL8HTUJZ51imGJWEX//ajQPfqWLI3BQq4TlvHy4X0MOr5q3D2Zof/ka0d5FNdPwZXm3Yyib/UEd+w==", + "version": "4.53.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.53.5.tgz", + "integrity": "sha512-Pg6E+oP7GvZ4XwgRJBuSXZjcqpIW3yCBhK4BcsANvb47qMvAbCjR6E+1a/U2WXz1JJxp9/4Dno3/iSJLcm5auw==", "cpu": [ "x64" ], @@ -1054,9 +1054,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.53.3.tgz", - "integrity": "sha512-eoROhjcc6HbZCJr+tvVT8X4fW3/5g/WkGvvmwz/88sDtSJzO7r/blvoBDgISDiCjDRZmHpwud7h+6Q9JxFwq1Q==", + "version": "4.53.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.53.5.tgz", + "integrity": "sha512-txGtluxDKTxaMDzUduGP0wdfng24y1rygUMnmlUJ88fzCCULCLn7oE5kb2+tRB+MWq1QDZT6ObT5RrR8HFRKqg==", "cpu": [ "x64" ], @@ -1068,9 +1068,9 @@ ] }, "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.53.3.tgz", - "integrity": "sha512-OueLAWgrNSPGAdUdIjSWXw+u/02BRTcnfw9PN41D2vq/JSEPnJnVuBgw18VkN8wcd4fjUs+jFHVM4t9+kBSNLw==", + "version": "4.53.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.53.5.tgz", + "integrity": "sha512-3DFiLPnTxiOQV993fMc+KO8zXHTcIjgaInrqlG8zDp1TlhYl6WgrOHuJkJQ6M8zHEcntSJsUp1XFZSY8C1DYbg==", "cpu": [ "arm64" ], @@ -1082,9 +1082,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.53.3.tgz", - "integrity": "sha512-GOFuKpsxR/whszbF/bzydebLiXIHSgsEUp6M0JI8dWvi+fFa1TD6YQa4aSZHtpmh2/uAlj/Dy+nmby3TJ3pkTw==", + "version": "4.53.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.53.5.tgz", + "integrity": "sha512-nggc/wPpNTgjGg75hu+Q/3i32R00Lq1B6N1DO7MCU340MRKL3WZJMjA9U4K4gzy3dkZPXm9E1Nc81FItBVGRlA==", "cpu": [ "arm64" ], @@ -1096,9 +1096,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.53.3.tgz", - "integrity": "sha512-iah+THLcBJdpfZ1TstDFbKNznlzoxa8fmnFYK4V67HvmuNYkVdAywJSoteUszvBQ9/HqN2+9AZghbajMsFT+oA==", + "version": "4.53.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.53.5.tgz", + "integrity": "sha512-U/54pTbdQpPLBdEzCT6NBCFAfSZMvmjr0twhnD9f4EIvlm9wy3jjQ38yQj1AGznrNO65EWQMgm/QUjuIVrYF9w==", "cpu": [ "ia32" ], @@ -1110,9 +1110,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-gnu": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.53.3.tgz", - "integrity": "sha512-J9QDiOIZlZLdcot5NXEepDkstocktoVjkaKUtqzgzpt2yWjGlbYiKyp05rWwk4nypbYUNoFAztEgixoLaSETkg==", + "version": "4.53.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.53.5.tgz", + "integrity": "sha512-2NqKgZSuLH9SXBBV2dWNRCZmocgSOx8OJSdpRaEcRlIfX8YrKxUT6z0F1NpvDVhOsl190UFTRh2F2WDWWCYp3A==", "cpu": [ "x64" ], @@ -1124,9 +1124,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.53.3.tgz", - "integrity": "sha512-UhTd8u31dXadv0MopwGgNOBpUVROFKWVQgAg5N1ESyCz8AuBcMqm4AuTjrwgQKGDfoFuz02EuMRHQIw/frmYKQ==", + "version": "4.53.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.53.5.tgz", + "integrity": "sha512-JRpZUhCfhZ4keB5v0fe02gQJy05GqboPOaxvjugW04RLSYYoB/9t2lx2u/tMs/Na/1NXfY8QYjgRljRpN+MjTQ==", "cpu": [ "x64" ], @@ -1589,9 +1589,9 @@ } }, "node_modules/baseline-browser-mapping": { - "version": "2.9.6", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.6.tgz", - "integrity": "sha512-v9BVVpOTLB59C9E7aSnmIF8h7qRsFpx+A2nugVMTszEOMcfjlZMsXRm4LF23I3Z9AJxc8ANpIvzbzONoX9VJlg==", + "version": "2.9.8", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.8.tgz", + "integrity": "sha512-Y1fOuNDowLfgKOypdc9SPABfoWXuZHBOyCS4cD52IeZBhr4Md6CLLs6atcxVrzRmQ06E7hSlm5bHHApPKR/byA==", "dev": true, "license": "Apache-2.0", "bin": { @@ -1881,9 +1881,9 @@ "license": "MIT" }, "node_modules/esbuild": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", - "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.2.tgz", + "integrity": "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -1894,32 +1894,32 @@ "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.12", - "@esbuild/android-arm": "0.25.12", - "@esbuild/android-arm64": "0.25.12", - "@esbuild/android-x64": "0.25.12", - "@esbuild/darwin-arm64": "0.25.12", - "@esbuild/darwin-x64": "0.25.12", - "@esbuild/freebsd-arm64": "0.25.12", - "@esbuild/freebsd-x64": "0.25.12", - "@esbuild/linux-arm": "0.25.12", - "@esbuild/linux-arm64": "0.25.12", - "@esbuild/linux-ia32": "0.25.12", - "@esbuild/linux-loong64": "0.25.12", - "@esbuild/linux-mips64el": "0.25.12", - "@esbuild/linux-ppc64": "0.25.12", - "@esbuild/linux-riscv64": "0.25.12", - "@esbuild/linux-s390x": "0.25.12", - "@esbuild/linux-x64": "0.25.12", - "@esbuild/netbsd-arm64": "0.25.12", - "@esbuild/netbsd-x64": "0.25.12", - "@esbuild/openbsd-arm64": "0.25.12", - "@esbuild/openbsd-x64": "0.25.12", - "@esbuild/openharmony-arm64": "0.25.12", - "@esbuild/sunos-x64": "0.25.12", - "@esbuild/win32-arm64": "0.25.12", - "@esbuild/win32-ia32": "0.25.12", - "@esbuild/win32-x64": "0.25.12" + "@esbuild/aix-ppc64": "0.27.2", + "@esbuild/android-arm": "0.27.2", + "@esbuild/android-arm64": "0.27.2", + "@esbuild/android-x64": "0.27.2", + "@esbuild/darwin-arm64": "0.27.2", + "@esbuild/darwin-x64": "0.27.2", + "@esbuild/freebsd-arm64": "0.27.2", + "@esbuild/freebsd-x64": "0.27.2", + "@esbuild/linux-arm": "0.27.2", + "@esbuild/linux-arm64": "0.27.2", + "@esbuild/linux-ia32": "0.27.2", + "@esbuild/linux-loong64": "0.27.2", + "@esbuild/linux-mips64el": "0.27.2", + "@esbuild/linux-ppc64": "0.27.2", + "@esbuild/linux-riscv64": "0.27.2", + "@esbuild/linux-s390x": "0.27.2", + "@esbuild/linux-x64": "0.27.2", + "@esbuild/netbsd-arm64": "0.27.2", + "@esbuild/netbsd-x64": "0.27.2", + "@esbuild/openbsd-arm64": "0.27.2", + "@esbuild/openbsd-x64": "0.27.2", + "@esbuild/openharmony-arm64": "0.27.2", + "@esbuild/sunos-x64": "0.27.2", + "@esbuild/win32-arm64": "0.27.2", + "@esbuild/win32-ia32": "0.27.2", + "@esbuild/win32-x64": "0.27.2" } }, "node_modules/escalade": { @@ -2509,9 +2509,9 @@ "license": "MIT" }, "node_modules/rollup": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.53.3.tgz", - "integrity": "sha512-w8GmOxZfBmKknvdXU1sdM9NHcoQejwF/4mNgj2JuEEdRaHwwF12K7e9eXn1nLZ07ad+du76mkVsyeb2rKGllsA==", + "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": { @@ -2525,28 +2525,28 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.53.3", - "@rollup/rollup-android-arm64": "4.53.3", - "@rollup/rollup-darwin-arm64": "4.53.3", - "@rollup/rollup-darwin-x64": "4.53.3", - "@rollup/rollup-freebsd-arm64": "4.53.3", - "@rollup/rollup-freebsd-x64": "4.53.3", - "@rollup/rollup-linux-arm-gnueabihf": "4.53.3", - "@rollup/rollup-linux-arm-musleabihf": "4.53.3", - "@rollup/rollup-linux-arm64-gnu": "4.53.3", - "@rollup/rollup-linux-arm64-musl": "4.53.3", - "@rollup/rollup-linux-loong64-gnu": "4.53.3", - "@rollup/rollup-linux-ppc64-gnu": "4.53.3", - "@rollup/rollup-linux-riscv64-gnu": "4.53.3", - "@rollup/rollup-linux-riscv64-musl": "4.53.3", - "@rollup/rollup-linux-s390x-gnu": "4.53.3", - "@rollup/rollup-linux-x64-gnu": "4.53.3", - "@rollup/rollup-linux-x64-musl": "4.53.3", - "@rollup/rollup-openharmony-arm64": "4.53.3", - "@rollup/rollup-win32-arm64-msvc": "4.53.3", - "@rollup/rollup-win32-ia32-msvc": "4.53.3", - "@rollup/rollup-win32-x64-gnu": "4.53.3", - "@rollup/rollup-win32-x64-msvc": "4.53.3", + "@rollup/rollup-android-arm-eabi": "4.53.5", + "@rollup/rollup-android-arm64": "4.53.5", + "@rollup/rollup-darwin-arm64": "4.53.5", + "@rollup/rollup-darwin-x64": "4.53.5", + "@rollup/rollup-freebsd-arm64": "4.53.5", + "@rollup/rollup-freebsd-x64": "4.53.5", + "@rollup/rollup-linux-arm-gnueabihf": "4.53.5", + "@rollup/rollup-linux-arm-musleabihf": "4.53.5", + "@rollup/rollup-linux-arm64-gnu": "4.53.5", + "@rollup/rollup-linux-arm64-musl": "4.53.5", + "@rollup/rollup-linux-loong64-gnu": "4.53.5", + "@rollup/rollup-linux-ppc64-gnu": "4.53.5", + "@rollup/rollup-linux-riscv64-gnu": "4.53.5", + "@rollup/rollup-linux-riscv64-musl": "4.53.5", + "@rollup/rollup-linux-s390x-gnu": "4.53.5", + "@rollup/rollup-linux-x64-gnu": "4.53.5", + "@rollup/rollup-linux-x64-musl": "4.53.5", + "@rollup/rollup-openharmony-arm64": "4.53.5", + "@rollup/rollup-win32-arm64-msvc": "4.53.5", + "@rollup/rollup-win32-ia32-msvc": "4.53.5", + "@rollup/rollup-win32-x64-gnu": "4.53.5", + "@rollup/rollup-win32-x64-msvc": "4.53.5", "fsevents": "~2.3.2" } }, @@ -3022,9 +3022,9 @@ "license": "MIT" }, "node_modules/update-browserslist-db": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.2.tgz", - "integrity": "sha512-E85pfNzMQ9jpKkA7+TJAi4TJN+tBCuWh5rUcS/sv6cFi+1q9LYDwDI5dpUL0u/73EElyQ8d3TEaeW4sPedBqYA==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", "dev": true, "funding": [ { @@ -3076,9 +3076,9 @@ } }, "node_modules/vite-node/node_modules/@types/node": { - "version": "25.0.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-25.0.0.tgz", - "integrity": "sha512-rl78HwuZlaDIUSeUKkmogkhebA+8K1Hy7tddZuJ3D0xV8pZSfsYGTsliGUol1JPzu9EKnTxPC4L1fiWouStRew==", + "version": "25.0.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-25.0.3.tgz", + "integrity": "sha512-W609buLVRVmeW693xKfzHeIV6nJGGz98uCPfeXI1ELMLXVeKYZ9m15fAMSaUPBHYLGFsVRcMmSCksQOrZV9BYA==", "dev": true, "license": "MIT", "optional": true, @@ -3143,13 +3143,13 @@ "peer": true }, "node_modules/vite-node/node_modules/vite": { - "version": "7.2.7", - "resolved": "https://registry.npmjs.org/vite/-/vite-7.2.7.tgz", - "integrity": "sha512-ITcnkFeR3+fI8P1wMgItjGrR10170d8auB4EpMLPqmx6uxElH3a/hHGQabSHKdqd4FXWO1nFIp9rRn7JQ34ACQ==", + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.0.tgz", + "integrity": "sha512-dZwN5L1VlUBewiP6H9s2+B3e3Jg96D0vzN+Ry73sOefebhYr9f94wwkMNN/9ouoU8pV1BqA1d1zGk8928cx0rg==", "dev": true, "license": "MIT", "dependencies": { - "esbuild": "^0.25.0", + "esbuild": "^0.27.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", @@ -3364,13 +3364,13 @@ } }, "node_modules/vitest/node_modules/vite": { - "version": "7.2.7", - "resolved": "https://registry.npmjs.org/vite/-/vite-7.2.7.tgz", - "integrity": "sha512-ITcnkFeR3+fI8P1wMgItjGrR10170d8auB4EpMLPqmx6uxElH3a/hHGQabSHKdqd4FXWO1nFIp9rRn7JQ34ACQ==", + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.0.tgz", + "integrity": "sha512-dZwN5L1VlUBewiP6H9s2+B3e3Jg96D0vzN+Ry73sOefebhYr9f94wwkMNN/9ouoU8pV1BqA1d1zGk8928cx0rg==", "dev": true, "license": "MIT", "dependencies": { - "esbuild": "^0.25.0", + "esbuild": "^0.27.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", @@ -3453,9 +3453,9 @@ } }, "node_modules/webpack": { - "version": "5.103.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.103.0.tgz", - "integrity": "sha512-HU1JOuV1OavsZ+mfigY0j8d1TgQgbZ6M+J75zDkpEAwYeXjWSqrGJtgnPblJjd/mAyTNQ7ygw0MiKOn6etz8yw==", + "version": "5.104.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.104.0.tgz", + "integrity": "sha512-5DeICTX8BVgNp6afSPYXAFjskIgWGlygQH58bcozPOXgo2r/6xx39Y1+cULZ3gTxUYQP88jmwLj2anu4Xaq84g==", "dev": true, "license": "MIT", "dependencies": { @@ -3467,10 +3467,10 @@ "@webassemblyjs/wasm-parser": "^1.14.1", "acorn": "^8.15.0", "acorn-import-phases": "^1.0.3", - "browserslist": "^4.26.3", + "browserslist": "^4.28.1", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.17.3", - "es-module-lexer": "^1.2.1", + "enhanced-resolve": "^5.17.4", + "es-module-lexer": "^2.0.0", "eslint-scope": "5.1.1", "events": "^3.2.0", "glob-to-regexp": "^0.4.1", @@ -3481,7 +3481,7 @@ "neo-async": "^2.6.2", "schema-utils": "^4.3.3", "tapable": "^2.3.0", - "terser-webpack-plugin": "^5.3.11", + "terser-webpack-plugin": "^5.3.16", "watchpack": "^2.4.4", "webpack-sources": "^3.3.3" }, @@ -3511,6 +3511,13 @@ "node": ">=10.13.0" } }, + "node_modules/webpack/node_modules/es-module-lexer": { + "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" + }, "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", diff --git a/skyvern-ts/client/reference.md b/skyvern-ts/client/reference.md index 133f9410..8129a6a9 100644 --- a/skyvern-ts/client/reference.md +++ b/skyvern-ts/client/reference.md @@ -68,6 +68,83 @@ 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 596546e5..e1cb84e0 100644 --- a/skyvern-ts/client/src/Client.ts +++ b/skyvern-ts/client/src/Client.ts @@ -2,6 +2,7 @@ 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"; @@ -16,6 +17,7 @@ export declare namespace SkyvernClient { export class SkyvernClient { protected readonly _options: SkyvernClient.Options; + protected _workflows: Workflows | undefined; protected _scripts: Scripts | undefined; constructor(_options: SkyvernClient.Options = {}) { @@ -36,6 +38,10 @@ 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)); } @@ -399,6 +405,7 @@ export class SkyvernClient { * page_size: 1, * only_saved_tasks: true, * only_workflows: true, + * only_templates: true, * search_key: "search_key", * title: "title", * folder_id: "folder_id", @@ -421,6 +428,7 @@ export class SkyvernClient { page_size: pageSize, only_saved_tasks: onlySavedTasks, only_workflows: onlyWorkflows, + only_templates: onlyTemplates, search_key: searchKey, title, folder_id: folderId, @@ -444,6 +452,10 @@ export class SkyvernClient { _queryParams.only_workflows = onlyWorkflows.toString(); } + if (onlyTemplates != null) { + _queryParams.only_templates = onlyTemplates.toString(); + } + if (searchKey != null) { _queryParams.search_key = searchKey; } diff --git a/skyvern-ts/client/src/api/client/requests/GetWorkflowsRequest.ts b/skyvern-ts/client/src/api/client/requests/GetWorkflowsRequest.ts index 15a33632..a4445114 100644 --- a/skyvern-ts/client/src/api/client/requests/GetWorkflowsRequest.ts +++ b/skyvern-ts/client/src/api/client/requests/GetWorkflowsRequest.ts @@ -9,6 +9,7 @@ import type * as Skyvern from "../../index.js"; * page_size: 1, * only_saved_tasks: true, * only_workflows: true, + * only_templates: true, * search_key: "search_key", * title: "title", * folder_id: "folder_id", @@ -20,6 +21,7 @@ export interface GetWorkflowsRequest { page_size?: number; only_saved_tasks?: boolean; only_workflows?: boolean; + only_templates?: boolean; /** Unified search across workflow title, folder name, and parameter metadata (key, description, default_value). */ search_key?: string; /** Deprecated: use search_key instead. */ diff --git a/skyvern-ts/client/src/api/resources/index.ts b/skyvern-ts/client/src/api/resources/index.ts index 7c69f0c4..9852fa96 100644 --- a/skyvern-ts/client/src/api/resources/index.ts +++ b/skyvern-ts/client/src/api/resources/index.ts @@ -1 +1,3 @@ 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 new file mode 100644 index 00000000..7b14e6da --- /dev/null +++ b/skyvern-ts/client/src/api/resources/workflows/client/Client.ts @@ -0,0 +1,112 @@ +// 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 new file mode 100644 index 00000000..195f9aa8 --- /dev/null +++ b/skyvern-ts/client/src/api/resources/workflows/client/index.ts @@ -0,0 +1 @@ +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 new file mode 100644 index 00000000..768d68a3 --- /dev/null +++ b/skyvern-ts/client/src/api/resources/workflows/client/requests/SetWorkflowTemplateStatusV1WorkflowsWorkflowPermanentIdTemplatePutRequest.ts @@ -0,0 +1,11 @@ +// 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 new file mode 100644 index 00000000..c5fa001f --- /dev/null +++ b/skyvern-ts/client/src/api/resources/workflows/client/requests/index.ts @@ -0,0 +1 @@ +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 new file mode 100644 index 00000000..914b8c3c --- /dev/null +++ b/skyvern-ts/client/src/api/resources/workflows/index.ts @@ -0,0 +1 @@ +export * from "./client/index.js"; diff --git a/skyvern-ts/client/src/api/types/Action.ts b/skyvern-ts/client/src/api/types/Action.ts index 535cb02b..127e5236 100644 --- a/skyvern-ts/client/src/api/types/Action.ts +++ b/skyvern-ts/client/src/api/types/Action.ts @@ -36,6 +36,7 @@ export interface Action { verified?: boolean; click_context?: Skyvern.ClickContext; totp_timing_info?: Record; + has_mini_agent?: boolean; created_at?: string; modified_at?: string; created_by?: string; diff --git a/skyvern-ts/client/src/api/types/Artifact.ts b/skyvern-ts/client/src/api/types/Artifact.ts index 6cf39b77..91a2bd04 100644 --- a/skyvern-ts/client/src/api/types/Artifact.ts +++ b/skyvern-ts/client/src/api/types/Artifact.ts @@ -14,6 +14,7 @@ export interface Artifact { step_id?: string; workflow_run_id?: string; workflow_run_block_id?: string; + run_id?: string; observer_cruise_id?: string; observer_thought_id?: string; ai_suggestion_id?: string; diff --git a/skyvern-ts/client/src/api/types/Workflow.ts b/skyvern-ts/client/src/api/types/Workflow.ts index f46534b7..b6b4c066 100644 --- a/skyvern-ts/client/src/api/types/Workflow.ts +++ b/skyvern-ts/client/src/api/types/Workflow.ts @@ -9,6 +9,7 @@ export interface Workflow { workflow_permanent_id: string; version: number; is_saved_task: boolean; + is_template?: boolean; description?: string; workflow_definition: Skyvern.WorkflowDefinition; proxy_location?: Workflow.ProxyLocation; diff --git a/skyvern-ts/client/src/library/Skyvern.ts b/skyvern-ts/client/src/library/Skyvern.ts index 0e1e5dcb..d5194e93 100644 --- a/skyvern-ts/client/src/library/Skyvern.ts +++ b/skyvern-ts/client/src/library/Skyvern.ts @@ -9,6 +9,10 @@ import type { GetRunResponse, ProxyLocation } from "../api/index.js"; import { LOG } from "./logger.js"; import * as core from "../core/index.js"; +function _getBrowserSessionUrl(browserSessionId: string): string { + return `https://app.skyvern.com/browser-session/${browserSessionId}`; +} + export interface SkyvernOptions extends BaseClientOptions { apiKey: string; } @@ -200,7 +204,11 @@ export class Skyvern extends SkyvernClient { proxy_location: options?.proxyLocation, }); - LOG.info("Launched new cloud browser session", { browser_session_id: browserSession.browser_session_id }); + if (this._environment === SkyvernEnvironment.Cloud) { + LOG.info("Launched new cloud browser session", { url: _getBrowserSessionUrl(browserSession.browser_session_id) }); + } else { + LOG.info("Launched new cloud browser session", { browser_session_id: browserSession.browser_session_id }); + } return this._connectToCloudBrowserSession(browserSession); } @@ -217,7 +225,11 @@ export class Skyvern extends SkyvernClient { const browserSession = await this.getBrowserSession(browserSessionId); - LOG.info("Connecting to existing cloud browser session", { browser_session_id: browserSession.browser_session_id }); + if (this._environment === SkyvernEnvironment.Cloud) { + LOG.info("Connecting to existing cloud browser session", { url: _getBrowserSessionUrl(browserSession.browser_session_id) }); + } else { + LOG.info("Connecting to existing cloud browser session", { browser_session_id: browserSession.browser_session_id }); + } return this._connectToCloudBrowserSession(browserSession); } @@ -254,7 +266,11 @@ export class Skyvern extends SkyvernClient { return this.launchCloudBrowser(options); } - LOG.info("Reusing existing cloud browser session", { browser_session_id: browserSession.browser_session_id }); + if (this._environment === SkyvernEnvironment.Cloud) { + LOG.info("Reusing existing cloud browser session", { url: _getBrowserSessionUrl(browserSession.browser_session_id) }); + } else { + LOG.info("Reusing existing cloud browser session", { browser_session_id: browserSession.browser_session_id }); + } return this._connectToCloudBrowserSession(browserSession); } diff --git a/skyvern-ts/client/src/library/SkyvernBrowserPage.ts b/skyvern-ts/client/src/library/SkyvernBrowserPage.ts index c0c35cdf..4e451528 100644 --- a/skyvern-ts/client/src/library/SkyvernBrowserPage.ts +++ b/skyvern-ts/client/src/library/SkyvernBrowserPage.ts @@ -63,74 +63,295 @@ export class SkyvernBrowserPageCore { return this._browser; } + /** + * Click an element using a CSS selector, AI-powered prompt matching, or both. + * + * This method supports three modes: + * - **Selector-based**: Click the element matching the CSS selector + * - **AI-powered**: Use natural language to describe which element to click + * - **Fallback mode**: Try the selector first, fall back to AI if it fails + * + * @param selector - CSS selector for the target element. + * @param options - Click options including prompt. + * @param options.prompt - Natural language description of which element to click. + * + * @example + * ```typescript + * // Click using a CSS selector + * await page.click("#open-invoice-button"); + * + * // Click using AI with natural language + * await page.click({ prompt: "Click on the 'Open Invoice' button" }); + * + * // Try selector first, fall back to AI if selector fails + * await page.click("#open-invoice-button", { prompt: "Click on the 'Open Invoice' button" }); + * ``` + */ async click(selector: string, options?: Parameters[1]): Promise; async click(options: { prompt: string } & Partial[1]>): Promise; async click( - selectorOrOptions: string | ({ prompt: string } & Partial[1]>), - options?: Parameters[1], + selector: string, + options: { prompt: string } & Partial[1]>, + ): Promise; + async click( + selectorOrOptions?: string | ({ prompt: string } & Partial[1]>), + options?: Parameters[1] | ({ prompt?: string } & Partial[1]>), ): Promise { + let selector: string | undefined; + let prompt: string | undefined; + let clickOptions: Partial[1]> = {}; + let timeout: number | undefined; + + // Parse arguments if (typeof selectorOrOptions === "string") { - return this._page.click(selectorOrOptions, options); - } else { - const { prompt, timeout, ...data } = selectorOrOptions; + selector = selectorOrOptions; + if (options && typeof options === "object") { + const { prompt: p, timeout: t, ...rest } = options as { + prompt?: string; + timeout?: number; + } & Partial[1]>; + prompt = p; + timeout = t; + clickOptions = rest; + } else if (options) { + clickOptions = options; + } + } else if (selectorOrOptions && typeof selectorOrOptions === "object") { + const { prompt: p, timeout: t, ...rest } = selectorOrOptions; + prompt = p; + timeout = t; + clickOptions = rest; + } + + if (!selector && !prompt) { + throw new Error("Missing input: pass a selector and/or a prompt."); + } + + // Try to click the element with the original selector first + let errorToRaise: Error | undefined; + if (selector) { + try { + await this._page.click(selector, { ...clickOptions, timeout }); + return; + } catch (error) { + errorToRaise = error as Error; + selector = undefined; + } + } + + // If the original selector doesn't work, try to click the element with the AI generated selector + if (prompt) { await this._ai.aiClick({ intention: prompt, + data: Object.keys(clickOptions).length > 0 ? clickOptions : undefined, timeout, - data: Object.keys(data).length > 0 ? data : undefined, }); + return; + } + + if (errorToRaise) { + throw errorToRaise; } } + /** + * Fill an input field using a CSS selector, AI-powered prompt matching, or both. + * + * This method supports three modes: + * - **Selector-based**: Fill the input field with a value using CSS selector + * - **AI-powered**: Use natural language prompt (AI extracts value from prompt or uses provided value) + * - **Fallback mode**: Try the selector first, fall back to AI if it fails + * + * @param selector - CSS selector for the target input element. + * @param value - The text value to input into the field. + * @param options - Fill options including prompt. + * @param options.prompt - Natural language description of which field to fill and what value. + * + * @example + * ```typescript + * // Fill using selector and value + * await page.fill("#email-input", "user@example.com"); + * + * // Fill using AI with natural language + * await page.fill({ prompt: "Fill 'user@example.com' in the email address field" }); + * + * // Try selector first, fall back to AI if selector fails + * await page.fill("#email-input", "user@example.com", { prompt: "Fill the email address" }); + * ``` + */ async fill(selector: string, value: string, options?: Parameters[2]): Promise; async fill(options: { prompt: string; value?: string } & Partial[2]>): Promise; async fill( - selectorOrOptions: string | ({ prompt: string; value?: string } & Partial[2]>), + selector: string, + value: string, + options: { prompt: string } & Partial[2]>, + ): Promise; + async fill( + selectorOrOptions?: string | ({ prompt: string; value?: string } & Partial[2]>), value?: string, - options?: Parameters[2], + options?: Parameters[2] | ({ prompt?: string } & Partial[2]>), ): Promise { + let selector: string | undefined; + let fillValue: string | undefined; + let prompt: string | undefined; + let fillOptions: Partial[2]> = {}; + let timeout: number | undefined; + if (typeof selectorOrOptions === "string") { - if (value === undefined) { - throw new Error("value is required when selector is provided"); + selector = selectorOrOptions; + fillValue = value; + if (options && typeof options === "object") { + const { prompt: p, timeout: t, ...rest } = options as { + prompt?: string; + timeout?: number; + } & Partial[2]>; + prompt = p; + timeout = t; + fillOptions = rest; + } else if (options) { + fillOptions = options; } - return this._page.fill(selectorOrOptions, value, options); - } else { - const { prompt, value: fillValue, timeout, ...data } = selectorOrOptions; + } else if (selectorOrOptions && typeof selectorOrOptions === "object") { + const { prompt: p, value: v, timeout: t, ...rest } = selectorOrOptions; + prompt = p; + fillValue = v; + timeout = t; + fillOptions = rest; + } + + if (!selector && !prompt) { + throw new Error("Missing input: pass a selector and/or a prompt."); + } + + let errorToRaise: Error | undefined; + if (selector && fillValue !== undefined) { + try { + await this._page.fill(selector, fillValue, { ...fillOptions, timeout }); + return; + } catch (error) { + errorToRaise = error as Error; + selector = undefined; + } + } + + if (prompt) { await this._ai.aiInputText({ value: fillValue, intention: prompt, + data: Object.keys(fillOptions).length > 0 ? fillOptions : undefined, timeout, - data: Object.keys(data).length > 0 ? data : undefined, }); + return; + } + + if (errorToRaise) { + throw errorToRaise; } } + /** + * Select an option from a dropdown using a CSS selector, AI-powered prompt matching, or both. + * + * This method supports three modes: + * - **Selector-based**: Select the option with a value using CSS selector + * - **AI-powered**: Use natural language prompt (AI extracts value from prompt or uses provided value) + * - **Fallback mode**: Try the selector first, fall back to AI if it fails + * + * @param selector - CSS selector for the target select/dropdown element. + * @param value - The option value to select. + * @param options - Select options including prompt. + * @param options.prompt - Natural language description of which option to select. + * + * @example + * ```typescript + * // Select using selector and value + * await page.selectOption("#country", "us"); + * + * // Select using AI with natural language + * await page.selectOption({ prompt: "Select 'United States' from the country dropdown" }); + * + * // Try selector first, fall back to AI if selector fails + * await page.selectOption("#country", "us", { prompt: "Select United States from country" }); + * ``` + */ async selectOption( selector: string, values: string | string[], options?: Parameters[2], - ): Promise; + ): Promise; async selectOption( options: { prompt: string; value?: string } & Partial[2]>, - ): Promise; + ): Promise; async selectOption( - selectorOrOptions: string | ({ prompt: string; value?: string } & Partial[2]>), + selector: string, + values: string | string[], + options: { prompt: string } & Partial[2]>, + ): Promise; + async selectOption( + selectorOrOptions?: + | string + | ({ prompt: string; value?: string } & Partial[2]>), values?: string | string[], - options?: Parameters[2], - ): Promise { + options?: Parameters[2] | ({ prompt?: string } & Partial[2]>), + ): Promise { + let selector: string | undefined; + let selectValue: string | string[] | undefined; + let prompt: string | undefined; + let selectOptions: Partial[2]> = {}; + let timeout: number | undefined; + + // Parse arguments if (typeof selectorOrOptions === "string") { - if (values === undefined) { - throw new Error("value is required when selector is provided"); + selector = selectorOrOptions; + selectValue = values; + if (options && typeof options === "object") { + const { prompt: p, timeout: t, ...rest } = options as { + prompt?: string; + timeout?: number; + } & Partial[2]>; + prompt = p; + timeout = t; + selectOptions = rest; + } else if (options) { + selectOptions = options; } - return this._page.selectOption(selectorOrOptions, values, options); - } else { - const { prompt, value, timeout, ...data } = selectorOrOptions; + } else if (selectorOrOptions && typeof selectorOrOptions === "object") { + const { prompt: p, value: v, timeout: t, ...rest } = selectorOrOptions; + prompt = p; + selectValue = v; + timeout = t; + selectOptions = rest; + } + + if (!selector && !prompt) { + throw new Error("Missing input: pass a selector and/or a prompt."); + } + + // Try to select the option with the original selector first + let errorToRaise: Error | undefined; + if (selector && selectValue !== undefined) { + try { + await this._page.selectOption(selector, selectValue, { ...selectOptions, timeout }); + return; + } catch (error) { + errorToRaise = error as Error; + selector = undefined; + } + } + + // If the original selector doesn't work, try to select the option with AI + if (prompt) { await this._ai.aiSelectOption({ - value, + value: typeof selectValue === "string" ? selectValue : selectValue?.[0], intention: prompt, + data: Object.keys(selectOptions).length > 0 ? selectOptions : undefined, timeout, - data: Object.keys(data).length > 0 ? data : undefined, }); - return value ? [value] : []; + return; + } + + if (errorToRaise) { + throw errorToRaise; } } diff --git a/skyvern-ts/client/src/library/SkyvernBrowserPageAgent.ts b/skyvern-ts/client/src/library/SkyvernBrowserPageAgent.ts index c0deac34..0607865e 100644 --- a/skyvern-ts/client/src/library/SkyvernBrowserPageAgent.ts +++ b/skyvern-ts/client/src/library/SkyvernBrowserPageAgent.ts @@ -99,32 +99,110 @@ export class SkyvernBrowserPageAgent { /** * Run a login task in the context of this page and wait for it to finish. * - * @param credentialType - Type of credential store to use (e.g., skyvern, bitwarden, onepassword). - * @param options - Optional configuration - * @param options.url - URL to navigate to for login. If not provided, uses the current page URL. - * @param options.credentialId - ID of the credential to use. - * @param options.bitwardenCollectionId - Bitwarden collection ID containing the credentials. - * @param options.bitwardenItemId - Bitwarden item ID for the credentials. - * @param options.onepasswordVaultId - 1Password vault ID containing the credentials. - * @param options.onepasswordItemId - 1Password item ID for the credentials. - * @param options.prompt - Additional instructions for the login process. - * @param options.webhookUrl - URL to receive webhook notifications about login progress. - * @param options.totpIdentifier - Identifier for TOTP authentication. - * @param options.totpUrl - URL to fetch TOTP codes from. - * @param options.extraHttpHeaders - Additional HTTP headers to include in requests. - * @param options.timeout - Maximum time in seconds to wait for login completion. + * This method has multiple overloaded signatures for different credential types: * - * @returns WorkflowRunResponse containing the login workflow execution results. + * 1. Skyvern credentials: + * ```typescript + * await page.agent.login("skyvern", { + * credentialId: "cred_123" + * }); + * ``` + * + * 2. Bitwarden credentials: + * ```typescript + * await page.agent.login("bitwarden", { + * bitwardenItemId: "item_id", + * bitwardenCollectionId: "collection_id" + * }); + * ``` + * + * 3. 1Password credentials: + * ```typescript + * await page.agent.login("1password", { + * onepasswordVaultId: "vault_id", + * onepasswordItemId: "item_id" + * }); + * ``` + * + * 4. Azure Vault credentials: + * ```typescript + * await page.agent.login("azure_vault", { + * azureVaultName: "vault_name", + * azureVaultUsernameKey: "username_key", + * azureVaultPasswordKey: "password_key", + * }); + * ``` */ async login( - credentialType: string, - options?: { + credentialType: "skyvern", + options: { + credentialId: string; + url?: string; + prompt?: string; + webhookUrl?: string; + totpIdentifier?: string; + totpUrl?: string; + extraHttpHeaders?: Record; + timeout?: number; + }, + ): Promise; + async login( + credentialType: "bitwarden", + options: { + bitwardenItemId: string; + bitwardenCollectionId?: string; + url?: string; + prompt?: string; + webhookUrl?: string; + totpIdentifier?: string; + totpUrl?: string; + extraHttpHeaders?: Record; + timeout?: number; + }, + ): Promise; + async login( + credentialType: "1password", + options: { + onepasswordVaultId: string; + onepasswordItemId: string; + url?: string; + prompt?: string; + webhookUrl?: string; + totpIdentifier?: string; + totpUrl?: string; + extraHttpHeaders?: Record; + timeout?: number; + }, + ): Promise; + async login( + credentialType: "azure_vault", + options: { + azureVaultName: string; + azureVaultUsernameKey: string; + azureVaultPasswordKey: string; + azureVaultTotpSecretKey?: string; + url?: string; + prompt?: string; + webhookUrl?: string; + totpIdentifier?: string; + totpUrl?: string; + extraHttpHeaders?: Record; + timeout?: number; + }, + ): Promise; + async login( + credentialType: Skyvern.SkyvernSchemasRunBlocksCredentialType, + options: { url?: string; credentialId?: string; bitwardenCollectionId?: string; bitwardenItemId?: string; onepasswordVaultId?: string; onepasswordItemId?: string; + azureVaultName?: string; + azureVaultUsernameKey?: string; + azureVaultPasswordKey?: string; + azureVaultTotpSecretKey?: string; prompt?: string; webhookUrl?: string; totpIdentifier?: string; @@ -137,20 +215,24 @@ export class SkyvernBrowserPageAgent { const workflowRun = await this._browser.skyvern.login( { - credential_type: credentialType as Skyvern.SkyvernSchemasRunBlocksCredentialType, - url: options?.url ?? this._getPageUrl(), - credential_id: options?.credentialId, - bitwarden_collection_id: options?.bitwardenCollectionId, - bitwarden_item_id: options?.bitwardenItemId, - onepassword_vault_id: options?.onepasswordVaultId, - onepassword_item_id: options?.onepasswordItemId, - prompt: options?.prompt, - webhook_url: options?.webhookUrl, - totp_identifier: options?.totpIdentifier, - totp_url: options?.totpUrl, + credential_type: credentialType, + url: options.url ?? this._getPageUrl(), + credential_id: options.credentialId, + bitwarden_collection_id: options.bitwardenCollectionId, + bitwarden_item_id: options.bitwardenItemId, + onepassword_vault_id: options.onepasswordVaultId, + onepassword_item_id: options.onepasswordItemId, + azure_vault_name: options.azureVaultName, + azure_vault_username_key: options.azureVaultUsernameKey, + azure_vault_password_key: options.azureVaultPasswordKey, + azure_vault_totp_secret_key: options.azureVaultTotpSecretKey, + prompt: options.prompt, + webhook_url: options.webhookUrl, + totp_identifier: options.totpIdentifier, + totp_url: options.totpUrl, browser_session_id: this._browser.browserSessionId, browser_address: this._browser.browserAddress, - extra_http_headers: options?.extraHttpHeaders, + extra_http_headers: options.extraHttpHeaders, }, { headers: { "x-user-agent": "skyvern-sdk" }, @@ -158,15 +240,15 @@ export class SkyvernBrowserPageAgent { ); if (this._browser.skyvern.environment === SkyvernEnvironment.Cloud) { - LOG.info("AI login workflow is running, this may take a while", { url: getAppUrlForRun(workflowRun.run_id), run_id: workflowRun.run_id }); + LOG.info("AI login workflow is running, this may take a while", { + url: getAppUrlForRun(workflowRun.run_id), + run_id: workflowRun.run_id, + }); } else { LOG.info("AI login workflow is running, this may take a while", { run_id: workflowRun.run_id }); } - const completedRun = await this._waitForRunCompletion( - workflowRun.run_id, - options?.timeout ?? DEFAULT_AGENT_TIMEOUT, - ); + const completedRun = await this._waitForRunCompletion(workflowRun.run_id, options.timeout ?? DEFAULT_AGENT_TIMEOUT); LOG.info("AI login workflow finished", { run_id: completedRun.run_id, status: completedRun.status }); return completedRun as Skyvern.WorkflowRunResponse; diff --git a/skyvern-ts/client/tests/wire/main.test.ts b/skyvern-ts/client/tests/wire/main.test.ts index 6fb80f74..c8405105 100644 --- a/skyvern-ts/client/tests/wire/main.test.ts +++ b/skyvern-ts/client/tests/wire/main.test.ts @@ -535,6 +535,7 @@ describe("SkyvernClient", () => { workflow_permanent_id: "workflow_permanent_id", version: 1, is_saved_task: true, + is_template: true, description: "description", workflow_definition: { version: 1, @@ -591,6 +592,7 @@ describe("SkyvernClient", () => { page_size: 1, only_saved_tasks: true, only_workflows: true, + only_templates: true, search_key: "search_key", title: "title", folder_id: "folder_id", @@ -604,6 +606,7 @@ describe("SkyvernClient", () => { workflow_permanent_id: "workflow_permanent_id", version: 1, is_saved_task: true, + is_template: true, description: "description", workflow_definition: { version: 1, @@ -682,6 +685,7 @@ describe("SkyvernClient", () => { workflow_permanent_id: "workflow_permanent_id", version: 1, is_saved_task: true, + is_template: true, description: "description", workflow_definition: { version: 1, @@ -750,6 +754,7 @@ describe("SkyvernClient", () => { workflow_permanent_id: "workflow_permanent_id", version: 1, is_saved_task: true, + is_template: true, description: "description", workflow_definition: { version: 1, @@ -836,6 +841,7 @@ describe("SkyvernClient", () => { workflow_permanent_id: "workflow_permanent_id", version: 1, is_saved_task: true, + is_template: true, description: "description", workflow_definition: { version: 1, @@ -901,6 +907,7 @@ describe("SkyvernClient", () => { workflow_permanent_id: "workflow_permanent_id", version: 1, is_saved_task: true, + is_template: true, description: "description", workflow_definition: { version: 1, @@ -1025,6 +1032,7 @@ describe("SkyvernClient", () => { step_id: "step_id", workflow_run_id: "workflow_run_id", workflow_run_block_id: "workflow_run_block_id", + run_id: "run_id", observer_cruise_id: "observer_cruise_id", observer_thought_id: "observer_thought_id", ai_suggestion_id: "ai_suggestion_id", @@ -1050,6 +1058,7 @@ describe("SkyvernClient", () => { step_id: "step_id", workflow_run_id: "workflow_run_id", workflow_run_block_id: "workflow_run_block_id", + run_id: "run_id", observer_cruise_id: "observer_cruise_id", observer_thought_id: "observer_thought_id", ai_suggestion_id: "ai_suggestion_id", @@ -1109,6 +1118,7 @@ describe("SkyvernClient", () => { step_id: "step_id", workflow_run_id: "workflow_run_id", workflow_run_block_id: "workflow_run_block_id", + run_id: "run_id", observer_cruise_id: "observer_cruise_id", observer_thought_id: "observer_thought_id", ai_suggestion_id: "ai_suggestion_id", @@ -1136,6 +1146,7 @@ describe("SkyvernClient", () => { step_id: "step_id", workflow_run_id: "workflow_run_id", workflow_run_block_id: "workflow_run_block_id", + run_id: "run_id", observer_cruise_id: "observer_cruise_id", observer_thought_id: "observer_thought_id", ai_suggestion_id: "ai_suggestion_id", diff --git a/skyvern-ts/client/tests/wire/workflows.test.ts b/skyvern-ts/client/tests/wire/workflows.test.ts new file mode 100644 index 00000000..8cc25256 --- /dev/null +++ b/skyvern-ts/client/tests/wire/workflows.test.ts @@ -0,0 +1,48 @@ +// 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 2293b30b..2fdb2b0a 100644 --- a/skyvern/client/__init__.py +++ b/skyvern/client/__init__.py @@ -496,7 +496,7 @@ if typing.TYPE_CHECKING: WorkflowStatus, ) from .errors import BadRequestError, ConflictError, ForbiddenError, NotFoundError, UnprocessableEntityError - from . import scripts + from . import scripts, workflows from .client import AsyncSkyvern, Skyvern from .environment import SkyvernEnvironment from .version import __version__ @@ -998,6 +998,7 @@ _dynamic_imports: typing.Dict[str, str] = { "WorkflowStatus": ".types", "__version__": ".version", "scripts": ".scripts", + "workflows": ".workflows", } @@ -1520,4 +1521,5 @@ __all__ = [ "WorkflowStatus", "__version__", "scripts", + "workflows", ] diff --git a/skyvern/client/client.py b/skyvern/client/client.py index 1b77085b..36244807 100644 --- a/skyvern/client/client.py +++ b/skyvern/client/client.py @@ -39,6 +39,7 @@ 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, ...) @@ -109,6 +110,7 @@ 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 @@ -500,6 +502,7 @@ class Skyvern: page_size: typing.Optional[int] = None, only_saved_tasks: typing.Optional[bool] = None, only_workflows: typing.Optional[bool] = None, + only_templates: typing.Optional[bool] = None, search_key: typing.Optional[str] = None, title: typing.Optional[str] = None, folder_id: typing.Optional[str] = None, @@ -527,6 +530,8 @@ class Skyvern: only_workflows : typing.Optional[bool] + only_templates : typing.Optional[bool] + search_key : typing.Optional[str] Unified search across workflow title, folder name, and parameter metadata (key, description, default_value). @@ -560,6 +565,7 @@ class Skyvern: page_size=1, only_saved_tasks=True, only_workflows=True, + only_templates=True, search_key="search_key", title="title", folder_id="folder_id", @@ -571,6 +577,7 @@ class Skyvern: page_size=page_size, only_saved_tasks=only_saved_tasks, only_workflows=only_workflows, + only_templates=only_templates, search_key=search_key, title=title, folder_id=folder_id, @@ -1849,6 +1856,14 @@ 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: @@ -1924,6 +1939,7 @@ 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 @@ -2347,6 +2363,7 @@ class AsyncSkyvern: page_size: typing.Optional[int] = None, only_saved_tasks: typing.Optional[bool] = None, only_workflows: typing.Optional[bool] = None, + only_templates: typing.Optional[bool] = None, search_key: typing.Optional[str] = None, title: typing.Optional[str] = None, folder_id: typing.Optional[str] = None, @@ -2374,6 +2391,8 @@ class AsyncSkyvern: only_workflows : typing.Optional[bool] + only_templates : typing.Optional[bool] + search_key : typing.Optional[str] Unified search across workflow title, folder name, and parameter metadata (key, description, default_value). @@ -2412,6 +2431,7 @@ class AsyncSkyvern: page_size=1, only_saved_tasks=True, only_workflows=True, + only_templates=True, search_key="search_key", title="title", folder_id="folder_id", @@ -2426,6 +2446,7 @@ class AsyncSkyvern: page_size=page_size, only_saved_tasks=only_saved_tasks, only_workflows=only_workflows, + only_templates=only_templates, search_key=search_key, title=title, folder_id=folder_id, @@ -3926,6 +3947,14 @@ 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/raw_client.py b/skyvern/client/raw_client.py index d64067d6..5317e9cd 100644 --- a/skyvern/client/raw_client.py +++ b/skyvern/client/raw_client.py @@ -546,6 +546,7 @@ class RawSkyvern: page_size: typing.Optional[int] = None, only_saved_tasks: typing.Optional[bool] = None, only_workflows: typing.Optional[bool] = None, + only_templates: typing.Optional[bool] = None, search_key: typing.Optional[str] = None, title: typing.Optional[str] = None, folder_id: typing.Optional[str] = None, @@ -573,6 +574,8 @@ class RawSkyvern: only_workflows : typing.Optional[bool] + only_templates : typing.Optional[bool] + search_key : typing.Optional[str] Unified search across workflow title, folder name, and parameter metadata (key, description, default_value). @@ -602,6 +605,7 @@ class RawSkyvern: "page_size": page_size, "only_saved_tasks": only_saved_tasks, "only_workflows": only_workflows, + "only_templates": only_templates, "search_key": search_key, "title": title, "folder_id": folder_id, @@ -3062,6 +3066,7 @@ class AsyncRawSkyvern: page_size: typing.Optional[int] = None, only_saved_tasks: typing.Optional[bool] = None, only_workflows: typing.Optional[bool] = None, + only_templates: typing.Optional[bool] = None, search_key: typing.Optional[str] = None, title: typing.Optional[str] = None, folder_id: typing.Optional[str] = None, @@ -3089,6 +3094,8 @@ class AsyncRawSkyvern: only_workflows : typing.Optional[bool] + only_templates : typing.Optional[bool] + search_key : typing.Optional[str] Unified search across workflow title, folder name, and parameter metadata (key, description, default_value). @@ -3118,6 +3125,7 @@ class AsyncRawSkyvern: "page_size": page_size, "only_saved_tasks": only_saved_tasks, "only_workflows": only_workflows, + "only_templates": only_templates, "search_key": search_key, "title": title, "folder_id": folder_id, diff --git a/skyvern/client/types/action.py b/skyvern/client/types/action.py index 23a0efd1..a014f4c3 100644 --- a/skyvern/client/types/action.py +++ b/skyvern/client/types/action.py @@ -47,6 +47,7 @@ class Action(UniversalBaseModel): verified: typing.Optional[bool] = None click_context: typing.Optional[ClickContext] = None totp_timing_info: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = None + has_mini_agent: typing.Optional[bool] = None created_at: typing.Optional[dt.datetime] = None modified_at: typing.Optional[dt.datetime] = None created_by: typing.Optional[str] = None diff --git a/skyvern/client/types/artifact.py b/skyvern/client/types/artifact.py index f3dc9f84..fe2620c6 100644 --- a/skyvern/client/types/artifact.py +++ b/skyvern/client/types/artifact.py @@ -25,6 +25,7 @@ class Artifact(UniversalBaseModel): step_id: typing.Optional[str] = None workflow_run_id: typing.Optional[str] = None workflow_run_block_id: typing.Optional[str] = None + run_id: typing.Optional[str] = None observer_cruise_id: typing.Optional[str] = None observer_thought_id: typing.Optional[str] = None ai_suggestion_id: typing.Optional[str] = None diff --git a/skyvern/client/types/workflow.py b/skyvern/client/types/workflow.py index c3a61acf..b60945fe 100644 --- a/skyvern/client/types/workflow.py +++ b/skyvern/client/types/workflow.py @@ -19,6 +19,7 @@ class Workflow(UniversalBaseModel): workflow_permanent_id: str version: int is_saved_task: bool + is_template: typing.Optional[bool] = None description: typing.Optional[str] = None workflow_definition: WorkflowDefinition proxy_location: typing.Optional[WorkflowProxyLocation] = None diff --git a/skyvern/client/workflows/__init__.py b/skyvern/client/workflows/__init__.py new file mode 100644 index 00000000..5cde0202 --- /dev/null +++ b/skyvern/client/workflows/__init__.py @@ -0,0 +1,4 @@ +# 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 new file mode 100644 index 00000000..46edb7a0 --- /dev/null +++ b/skyvern/client/workflows/client.py @@ -0,0 +1,127 @@ +# 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 new file mode 100644 index 00000000..c8fb091e --- /dev/null +++ b/skyvern/client/workflows/raw_client.py @@ -0,0 +1,136 @@ +# 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/skyvern/forge/sdk/routes/sdk.py b/skyvern/forge/sdk/routes/sdk.py index a039f17d..a01924be 100644 --- a/skyvern/forge/sdk/routes/sdk.py +++ b/skyvern/forge/sdk/routes/sdk.py @@ -214,7 +214,7 @@ async def run_sdk_action( elif action.type == "prompt": prompt_result = await page_ai.ai_prompt( prompt=action.prompt, - schema=action.schema, + schema=action.response_schema, model=action.model, ) result = prompt_result diff --git a/skyvern/forge/sdk/schemas/sdk_actions.py b/skyvern/forge/sdk/schemas/sdk_actions.py index bf5b82a9..56672d54 100644 --- a/skyvern/forge/sdk/schemas/sdk_actions.py +++ b/skyvern/forge/sdk/schemas/sdk_actions.py @@ -172,7 +172,7 @@ class PromptAction(SdkActionBase): type: Literal["prompt"] = "prompt" prompt: str = Field(..., description="The prompt to send to the LLM") - schema: dict[str, Any] | None = Field(None, description="Optional JSON schema to structure the response") + response_schema: dict[str, Any] | None = Field(None, description="Optional JSON schema to structure the response") model: dict[str, Any] | None = Field(None, description="Optional model configuration") def get_navigation_goal(self) -> str | None: diff --git a/skyvern/library/skyvern_browser_page_ai.py b/skyvern/library/skyvern_browser_page_ai.py index 1356c8e4..d6e47d5b 100644 --- a/skyvern/library/skyvern_browser_page_ai.py +++ b/skyvern/library/skyvern_browser_page_ai.py @@ -275,7 +275,7 @@ class SdkSkyvernPageAi(SkyvernPageAi): url=self._page.url, action=RunSdkActionRequestAction_Prompt( prompt=prompt, - schema=schema, + response_schema=schema, model=model, ), browser_session_id=self._browser.browser_session_id,