Release SDK v1.0.3 (#4277)

This commit is contained in:
Stanislav Novosad
2025-12-12 09:10:50 -07:00
committed by GitHub
parent 401af044b4
commit 30bb5a8c71
51 changed files with 123 additions and 3151 deletions

View File

@@ -1,6 +1,6 @@
[project]
name = "skyvern"
version = "1.0.2"
version = "1.0.3"
description = ""
authors = [{ name = "Skyvern AI", email = "info@skyvern.com" }]
requires-python = ">=3.11,<3.14"

View File

@@ -1,6 +1,6 @@
#!/usr/bin/env bash
#CURRENT_VERSION=$(grep '^version = ' pyproject.toml | sed 's/version = "\(.*\)"/\1/')
CURRENT_VERSION=$(grep '^version = ' pyproject.toml | sed 's/version = "\(.*\)"/\1/')
fern generate --group ts-sdk --log-level debug --version "$CURRENT_VERSION" --preview
mkdir -p skyvern-ts/client

View File

@@ -56,7 +56,7 @@ following namespace:
```typescript
import { Skyvern } from "@skyvern/client";
const request: Skyvern.GetFoldersV1FoldersGetRequest = {
const request: Skyvern.RunTaskRequest = {
...
};
```

View File

@@ -1,12 +1,12 @@
{
"name": "@skyvern/client",
"version": "1.0.2",
"version": "1.0.3",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@skyvern/client",
"version": "1.0.2",
"version": "1.0.3",
"dependencies": {
"playwright": "^1.48.0"
},
@@ -1589,9 +1589,9 @@
}
},
"node_modules/baseline-browser-mapping": {
"version": "2.9.5",
"resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.5.tgz",
"integrity": "sha512-D5vIoztZOq1XM54LUdttJVc96ggEsIfju2JBvht06pSzpckp3C7HReun67Bghzrtdsq9XdMGbSSB3v3GhMNmAA==",
"version": "2.9.6",
"resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.6.tgz",
"integrity": "sha512-v9BVVpOTLB59C9E7aSnmIF8h7qRsFpx+A2nugVMTszEOMcfjlZMsXRm4LF23I3Z9AJxc8ANpIvzbzONoX9VJlg==",
"dev": true,
"license": "Apache-2.0",
"bin": {
@@ -1860,9 +1860,9 @@
"license": "MIT"
},
"node_modules/enhanced-resolve": {
"version": "5.18.3",
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.3.tgz",
"integrity": "sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==",
"version": "5.18.4",
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.4.tgz",
"integrity": "sha512-LgQMM4WXU3QI+SYgEc2liRgznaD5ojbmY3sb8LxyguVkIg5FxdpTkvk72te2R38/TGKxH634oLxXRGY6d7AP+Q==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -2794,9 +2794,9 @@
}
},
"node_modules/terser-webpack-plugin": {
"version": "5.3.15",
"resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.15.tgz",
"integrity": "sha512-PGkOdpRFK+rb1TzVz+msVhw4YMRT9txLF4kRqvJhGhCM324xuR3REBSHALN+l+sAhKUmz0aotnjp5D+P83mLhQ==",
"version": "5.3.16",
"resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.16.tgz",
"integrity": "sha512-h9oBFCWrq78NyWWVcSwZarJkZ01c2AyGrzs1crmHZO3QUg9D61Wu4NPjBy69n7JqylFF5y+CsUZYmYEIZ3mR+Q==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -3076,9 +3076,9 @@
}
},
"node_modules/vite-node/node_modules/@types/node": {
"version": "24.10.2",
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.2.tgz",
"integrity": "sha512-WOhQTZ4G8xZ1tjJTvKOpyEVSGgOTvJAfDK3FNFgELyaTpzhdgHVHeqW8V+UJvzF5BT+/B54T/1S2K6gd9c7bbA==",
"version": "25.0.0",
"resolved": "https://registry.npmjs.org/@types/node/-/node-25.0.0.tgz",
"integrity": "sha512-rl78HwuZlaDIUSeUKkmogkhebA+8K1Hy7tddZuJ3D0xV8pZSfsYGTsliGUol1JPzu9EKnTxPC4L1fiWouStRew==",
"dev": true,
"license": "MIT",
"optional": true,

View File

@@ -1,6 +1,6 @@
{
"name": "@skyvern/client",
"version": "1.0.2",
"version": "1.0.3",
"private": false,
"repository": {
"type": "git",

View File

@@ -68,417 +68,6 @@ await client.runSdkAction({
</details>
##
## Workflows
<details><summary><code>client.workflows.<a href="/src/api/resources/workflows/client/Client.ts">getFolders</a>({ ...params }) -> Skyvern.Folder[]</code></summary>
<dl>
<dd>
#### 📝 Description
<dl>
<dd>
<dl>
<dd>
Get all folders for the organization
</dd>
</dl>
</dd>
</dl>
#### 🔌 Usage
<dl>
<dd>
<dl>
<dd>
```typescript
await client.workflows.getFolders({
page: 1,
page_size: 1,
search: "search"
});
```
</dd>
</dl>
</dd>
</dl>
#### ⚙️ Parameters
<dl>
<dd>
<dl>
<dd>
**request:** `Skyvern.GetFoldersV1FoldersGetRequest`
</dd>
</dl>
<dl>
<dd>
**requestOptions:** `Workflows.RequestOptions`
</dd>
</dl>
</dd>
</dl>
</dd>
</dl>
</details>
<details><summary><code>client.workflows.<a href="/src/api/resources/workflows/client/Client.ts">createFolder</a>({ ...params }) -> Skyvern.Folder</code></summary>
<dl>
<dd>
#### 📝 Description
<dl>
<dd>
<dl>
<dd>
Create a new folder to organize workflows
</dd>
</dl>
</dd>
</dl>
#### 🔌 Usage
<dl>
<dd>
<dl>
<dd>
```typescript
await client.workflows.createFolder({
title: "title"
});
```
</dd>
</dl>
</dd>
</dl>
#### ⚙️ Parameters
<dl>
<dd>
<dl>
<dd>
**request:** `Skyvern.FolderCreate`
</dd>
</dl>
<dl>
<dd>
**requestOptions:** `Workflows.RequestOptions`
</dd>
</dl>
</dd>
</dl>
</dd>
</dl>
</details>
<details><summary><code>client.workflows.<a href="/src/api/resources/workflows/client/Client.ts">getFolder</a>(folderId) -> Skyvern.Folder</code></summary>
<dl>
<dd>
#### 📝 Description
<dl>
<dd>
<dl>
<dd>
Get a specific folder by ID
</dd>
</dl>
</dd>
</dl>
#### 🔌 Usage
<dl>
<dd>
<dl>
<dd>
```typescript
await client.workflows.getFolder("fld_123");
```
</dd>
</dl>
</dd>
</dl>
#### ⚙️ Parameters
<dl>
<dd>
<dl>
<dd>
**folderId:** `string` — Folder ID
</dd>
</dl>
<dl>
<dd>
**requestOptions:** `Workflows.RequestOptions`
</dd>
</dl>
</dd>
</dl>
</dd>
</dl>
</details>
<details><summary><code>client.workflows.<a href="/src/api/resources/workflows/client/Client.ts">updateFolder</a>(folderId, { ...params }) -> Skyvern.Folder</code></summary>
<dl>
<dd>
#### 📝 Description
<dl>
<dd>
<dl>
<dd>
Update a folder's title or description
</dd>
</dl>
</dd>
</dl>
#### 🔌 Usage
<dl>
<dd>
<dl>
<dd>
```typescript
await client.workflows.updateFolder("fld_123");
```
</dd>
</dl>
</dd>
</dl>
#### ⚙️ Parameters
<dl>
<dd>
<dl>
<dd>
**folderId:** `string` — Folder ID
</dd>
</dl>
<dl>
<dd>
**request:** `Skyvern.FolderUpdate`
</dd>
</dl>
<dl>
<dd>
**requestOptions:** `Workflows.RequestOptions`
</dd>
</dl>
</dd>
</dl>
</dd>
</dl>
</details>
<details><summary><code>client.workflows.<a href="/src/api/resources/workflows/client/Client.ts">deleteFolder</a>(folderId, { ...params }) -> Record<string, unknown></code></summary>
<dl>
<dd>
#### 📝 Description
<dl>
<dd>
<dl>
<dd>
Delete a folder. Optionally delete all workflows in the folder.
</dd>
</dl>
</dd>
</dl>
#### 🔌 Usage
<dl>
<dd>
<dl>
<dd>
```typescript
await client.workflows.deleteFolder("fld_123", {
delete_workflows: true
});
```
</dd>
</dl>
</dd>
</dl>
#### ⚙️ Parameters
<dl>
<dd>
<dl>
<dd>
**folderId:** `string` — Folder ID
</dd>
</dl>
<dl>
<dd>
**request:** `Skyvern.DeleteFolderV1FoldersFolderIdDeleteRequest`
</dd>
</dl>
<dl>
<dd>
**requestOptions:** `Workflows.RequestOptions`
</dd>
</dl>
</dd>
</dl>
</dd>
</dl>
</details>
<details><summary><code>client.workflows.<a href="/src/api/resources/workflows/client/Client.ts">updateWorkflowFolder</a>(workflowPermanentId, { ...params }) -> Skyvern.Workflow</code></summary>
<dl>
<dd>
#### 📝 Description
<dl>
<dd>
<dl>
<dd>
Update a workflow's folder assignment for the latest version
</dd>
</dl>
</dd>
</dl>
#### 🔌 Usage
<dl>
<dd>
<dl>
<dd>
```typescript
await client.workflows.updateWorkflowFolder("wpid_123");
```
</dd>
</dl>
</dd>
</dl>
#### ⚙️ Parameters
<dl>
<dd>
<dl>
<dd>
**workflowPermanentId:** `string` — Workflow permanent ID
</dd>
</dl>
<dl>
<dd>
**request:** `Skyvern.UpdateWorkflowFolderRequest`
</dd>
</dl>
<dl>
<dd>
**requestOptions:** `Workflows.RequestOptions`
</dd>
</dl>
</dd>
</dl>
</dd>
</dl>
</details>
## Scripts
<details><summary><code>client.scripts.<a href="/src/api/resources/scripts/client/Client.ts">runScript</a>(scriptId) -> unknown</code></summary>
<dl>

View File

@@ -2,7 +2,6 @@
import * as Skyvern from "./api/index.js";
import { Scripts } from "./api/resources/scripts/client/Client.js";
import { Workflows } from "./api/resources/workflows/client/Client.js";
import type { BaseClientOptions, BaseRequestOptions } from "./BaseClient.js";
import { mergeHeaders, mergeOnlyDefinedHeaders } from "./core/headers.js";
import * as core from "./core/index.js";
@@ -17,7 +16,6 @@ export declare namespace SkyvernClient {
export class SkyvernClient {
protected readonly _options: SkyvernClient.Options;
protected _workflows: Workflows | undefined;
protected _scripts: Scripts | undefined;
constructor(_options: SkyvernClient.Options = {}) {
@@ -28,8 +26,8 @@ export class SkyvernClient {
"x-api-key": _options?.apiKey,
"X-Fern-Language": "JavaScript",
"X-Fern-SDK-Name": "@skyvern/client",
"X-Fern-SDK-Version": "1.0.2",
"User-Agent": "@skyvern/client/1.0.2",
"X-Fern-SDK-Version": "1.0.3",
"User-Agent": "@skyvern/client/1.0.3",
"X-Fern-Runtime": core.RUNTIME.type,
"X-Fern-Runtime-Version": core.RUNTIME.version,
},
@@ -38,10 +36,6 @@ export class SkyvernClient {
};
}
public get workflows(): Workflows {
return (this._workflows ??= new Workflows(this._options));
}
public get scripts(): Scripts {
return (this._scripts ??= new Scripts(this._options));
}

View File

@@ -27,5 +27,8 @@ export namespace CreateCredentialRequest {
/**
* The credential data to store
*/
export type Credential = Skyvern.NonEmptyPasswordCredential | Skyvern.NonEmptyCreditCardCredential;
export type Credential =
| Skyvern.NonEmptyPasswordCredential
| Skyvern.NonEmptyCreditCardCredential
| Skyvern.SecretCredential;
}

View File

@@ -1,3 +1 @@
export * as scripts from "./scripts/index.js";
export * from "./workflows/client/requests/index.js";
export * as workflows from "./workflows/index.js";

View File

@@ -1,540 +0,0 @@
// This file was auto-generated by Fern from our API Definition.
import type { BaseClientOptions, BaseRequestOptions } from "../../../../BaseClient.js";
import { mergeHeaders, mergeOnlyDefinedHeaders } from "../../../../core/headers.js";
import * as core from "../../../../core/index.js";
import * as environments from "../../../../environments.js";
import * as errors from "../../../../errors/index.js";
import * as Skyvern from "../../../index.js";
export declare namespace Workflows {
export interface Options extends BaseClientOptions {}
export interface RequestOptions extends BaseRequestOptions {}
}
export class Workflows {
protected readonly _options: Workflows.Options;
constructor(_options: Workflows.Options = {}) {
this._options = _options;
}
/**
* Get all folders for the organization
*
* @param {Skyvern.GetFoldersV1FoldersGetRequest} request
* @param {Workflows.RequestOptions} requestOptions - Request-specific configuration.
*
* @throws {@link Skyvern.UnprocessableEntityError}
*
* @example
* await client.workflows.getFolders({
* page: 1,
* page_size: 1,
* search: "search"
* })
*/
public getFolders(
request: Skyvern.GetFoldersV1FoldersGetRequest = {},
requestOptions?: Workflows.RequestOptions,
): core.HttpResponsePromise<Skyvern.Folder[]> {
return core.HttpResponsePromise.fromPromise(this.__getFolders(request, requestOptions));
}
private async __getFolders(
request: Skyvern.GetFoldersV1FoldersGetRequest = {},
requestOptions?: Workflows.RequestOptions,
): Promise<core.WithRawResponse<Skyvern.Folder[]>> {
const { page, page_size: pageSize, search } = request;
const _queryParams: Record<string, string | string[] | object | object[] | null> = {};
if (page != null) {
_queryParams.page = page.toString();
}
if (pageSize != null) {
_queryParams.page_size = pageSize.toString();
}
if (search != null) {
_queryParams.search = search;
}
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/folders",
),
method: "GET",
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 Skyvern.Folder[], 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 GET /v1/folders.");
case "unknown":
throw new errors.SkyvernError({
message: _response.error.errorMessage,
rawResponse: _response.rawResponse,
});
}
}
/**
* Create a new folder to organize workflows
*
* @param {Skyvern.FolderCreate} request
* @param {Workflows.RequestOptions} requestOptions - Request-specific configuration.
*
* @throws {@link Skyvern.BadRequestError}
* @throws {@link Skyvern.UnprocessableEntityError}
*
* @example
* await client.workflows.createFolder({
* title: "title"
* })
*/
public createFolder(
request: Skyvern.FolderCreate,
requestOptions?: Workflows.RequestOptions,
): core.HttpResponsePromise<Skyvern.Folder> {
return core.HttpResponsePromise.fromPromise(this.__createFolder(request, requestOptions));
}
private async __createFolder(
request: Skyvern.FolderCreate,
requestOptions?: Workflows.RequestOptions,
): Promise<core.WithRawResponse<Skyvern.Folder>> {
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/folders",
),
method: "POST",
headers: _headers,
contentType: "application/json",
queryParameters: requestOptions?.queryParams,
requestType: "json",
body: request,
timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 60) * 1000,
maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries,
abortSignal: requestOptions?.abortSignal,
});
if (_response.ok) {
return { data: _response.body as Skyvern.Folder, rawResponse: _response.rawResponse };
}
if (_response.error.reason === "status-code") {
switch (_response.error.statusCode) {
case 400:
throw new Skyvern.BadRequestError(_response.error.body as unknown, _response.rawResponse);
case 422:
throw new Skyvern.UnprocessableEntityError(_response.error.body as unknown, _response.rawResponse);
default:
throw new errors.SkyvernError({
statusCode: _response.error.statusCode,
body: _response.error.body,
rawResponse: _response.rawResponse,
});
}
}
switch (_response.error.reason) {
case "non-json":
throw new errors.SkyvernError({
statusCode: _response.error.statusCode,
body: _response.error.rawBody,
rawResponse: _response.rawResponse,
});
case "timeout":
throw new errors.SkyvernTimeoutError("Timeout exceeded when calling POST /v1/folders.");
case "unknown":
throw new errors.SkyvernError({
message: _response.error.errorMessage,
rawResponse: _response.rawResponse,
});
}
}
/**
* Get a specific folder by ID
*
* @param {string} folderId - Folder ID
* @param {Workflows.RequestOptions} requestOptions - Request-specific configuration.
*
* @throws {@link Skyvern.NotFoundError}
* @throws {@link Skyvern.UnprocessableEntityError}
*
* @example
* await client.workflows.getFolder("fld_123")
*/
public getFolder(
folderId: string,
requestOptions?: Workflows.RequestOptions,
): core.HttpResponsePromise<Skyvern.Folder> {
return core.HttpResponsePromise.fromPromise(this.__getFolder(folderId, requestOptions));
}
private async __getFolder(
folderId: string,
requestOptions?: Workflows.RequestOptions,
): Promise<core.WithRawResponse<Skyvern.Folder>> {
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/folders/${core.url.encodePathParam(folderId)}`,
),
method: "GET",
headers: _headers,
queryParameters: 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 Skyvern.Folder, rawResponse: _response.rawResponse };
}
if (_response.error.reason === "status-code") {
switch (_response.error.statusCode) {
case 404:
throw new Skyvern.NotFoundError(_response.error.body as unknown, _response.rawResponse);
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 GET /v1/folders/{folder_id}.");
case "unknown":
throw new errors.SkyvernError({
message: _response.error.errorMessage,
rawResponse: _response.rawResponse,
});
}
}
/**
* Update a folder's title or description
*
* @param {string} folderId - Folder ID
* @param {Skyvern.FolderUpdate} request
* @param {Workflows.RequestOptions} requestOptions - Request-specific configuration.
*
* @throws {@link Skyvern.NotFoundError}
* @throws {@link Skyvern.UnprocessableEntityError}
*
* @example
* await client.workflows.updateFolder("fld_123")
*/
public updateFolder(
folderId: string,
request: Skyvern.FolderUpdate = {},
requestOptions?: Workflows.RequestOptions,
): core.HttpResponsePromise<Skyvern.Folder> {
return core.HttpResponsePromise.fromPromise(this.__updateFolder(folderId, request, requestOptions));
}
private async __updateFolder(
folderId: string,
request: Skyvern.FolderUpdate = {},
requestOptions?: Workflows.RequestOptions,
): Promise<core.WithRawResponse<Skyvern.Folder>> {
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/folders/${core.url.encodePathParam(folderId)}`,
),
method: "PUT",
headers: _headers,
contentType: "application/json",
queryParameters: requestOptions?.queryParams,
requestType: "json",
body: request,
timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 60) * 1000,
maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries,
abortSignal: requestOptions?.abortSignal,
});
if (_response.ok) {
return { data: _response.body as Skyvern.Folder, rawResponse: _response.rawResponse };
}
if (_response.error.reason === "status-code") {
switch (_response.error.statusCode) {
case 404:
throw new Skyvern.NotFoundError(_response.error.body as unknown, _response.rawResponse);
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/folders/{folder_id}.");
case "unknown":
throw new errors.SkyvernError({
message: _response.error.errorMessage,
rawResponse: _response.rawResponse,
});
}
}
/**
* Delete a folder. Optionally delete all workflows in the folder.
*
* @param {string} folderId - Folder ID
* @param {Skyvern.DeleteFolderV1FoldersFolderIdDeleteRequest} request
* @param {Workflows.RequestOptions} requestOptions - Request-specific configuration.
*
* @throws {@link Skyvern.NotFoundError}
* @throws {@link Skyvern.UnprocessableEntityError}
*
* @example
* await client.workflows.deleteFolder("fld_123", {
* delete_workflows: true
* })
*/
public deleteFolder(
folderId: string,
request: Skyvern.DeleteFolderV1FoldersFolderIdDeleteRequest = {},
requestOptions?: Workflows.RequestOptions,
): core.HttpResponsePromise<Record<string, unknown>> {
return core.HttpResponsePromise.fromPromise(this.__deleteFolder(folderId, request, requestOptions));
}
private async __deleteFolder(
folderId: string,
request: Skyvern.DeleteFolderV1FoldersFolderIdDeleteRequest = {},
requestOptions?: Workflows.RequestOptions,
): Promise<core.WithRawResponse<Record<string, unknown>>> {
const { delete_workflows: deleteWorkflows } = request;
const _queryParams: Record<string, string | string[] | object | object[] | null> = {};
if (deleteWorkflows != null) {
_queryParams.delete_workflows = deleteWorkflows.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/folders/${core.url.encodePathParam(folderId)}`,
),
method: "DELETE",
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<string, unknown>, rawResponse: _response.rawResponse };
}
if (_response.error.reason === "status-code") {
switch (_response.error.statusCode) {
case 404:
throw new Skyvern.NotFoundError(_response.error.body as unknown, _response.rawResponse);
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 DELETE /v1/folders/{folder_id}.");
case "unknown":
throw new errors.SkyvernError({
message: _response.error.errorMessage,
rawResponse: _response.rawResponse,
});
}
}
/**
* Update a workflow's folder assignment for the latest version
*
* @param {string} workflowPermanentId - Workflow permanent ID
* @param {Skyvern.UpdateWorkflowFolderRequest} request
* @param {Workflows.RequestOptions} requestOptions - Request-specific configuration.
*
* @throws {@link Skyvern.BadRequestError}
* @throws {@link Skyvern.NotFoundError}
* @throws {@link Skyvern.UnprocessableEntityError}
*
* @example
* await client.workflows.updateWorkflowFolder("wpid_123")
*/
public updateWorkflowFolder(
workflowPermanentId: string,
request: Skyvern.UpdateWorkflowFolderRequest = {},
requestOptions?: Workflows.RequestOptions,
): core.HttpResponsePromise<Skyvern.Workflow> {
return core.HttpResponsePromise.fromPromise(
this.__updateWorkflowFolder(workflowPermanentId, request, requestOptions),
);
}
private async __updateWorkflowFolder(
workflowPermanentId: string,
request: Skyvern.UpdateWorkflowFolderRequest = {},
requestOptions?: Workflows.RequestOptions,
): Promise<core.WithRawResponse<Skyvern.Workflow>> {
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)}/folder`,
),
method: "PUT",
headers: _headers,
contentType: "application/json",
queryParameters: requestOptions?.queryParams,
requestType: "json",
body: request,
timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 60) * 1000,
maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries,
abortSignal: requestOptions?.abortSignal,
});
if (_response.ok) {
return { data: _response.body as Skyvern.Workflow, rawResponse: _response.rawResponse };
}
if (_response.error.reason === "status-code") {
switch (_response.error.statusCode) {
case 400:
throw new Skyvern.BadRequestError(_response.error.body as unknown, _response.rawResponse);
case 404:
throw new Skyvern.NotFoundError(_response.error.body as unknown, _response.rawResponse);
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}/folder.",
);
case "unknown":
throw new errors.SkyvernError({
message: _response.error.errorMessage,
rawResponse: _response.rawResponse,
});
}
}
}

View File

@@ -1 +0,0 @@
export * from "./requests/index.js";

View File

@@ -1,12 +0,0 @@
// This file was auto-generated by Fern from our API Definition.
/**
* @example
* {
* delete_workflows: true
* }
*/
export interface DeleteFolderV1FoldersFolderIdDeleteRequest {
/** If true, also delete all workflows in this folder */
delete_workflows?: boolean;
}

View File

@@ -1,14 +0,0 @@
// This file was auto-generated by Fern from our API Definition.
/**
* @example
* {
* title: "title"
* }
*/
export interface FolderCreate {
/** Folder title */
title: string;
/** Folder description */
description?: string;
}

View File

@@ -1,12 +0,0 @@
// This file was auto-generated by Fern from our API Definition.
/**
* @example
* {}
*/
export interface FolderUpdate {
/** Folder title */
title?: string;
/** Folder description */
description?: string;
}

View File

@@ -1,18 +0,0 @@
// This file was auto-generated by Fern from our API Definition.
/**
* @example
* {
* page: 1,
* page_size: 1,
* search: "search"
* }
*/
export interface GetFoldersV1FoldersGetRequest {
/** Page number */
page?: number;
/** Number of folders per page */
page_size?: number;
/** Search folders by title or description */
search?: string;
}

View File

@@ -1,10 +0,0 @@
// This file was auto-generated by Fern from our API Definition.
/**
* @example
* {}
*/
export interface UpdateWorkflowFolderRequest {
/** Folder ID to assign workflow to. Set to null to remove from folder. */
folder_id?: string;
}

View File

@@ -1,5 +0,0 @@
export type { DeleteFolderV1FoldersFolderIdDeleteRequest } from "./DeleteFolderV1FoldersFolderIdDeleteRequest.js";
export type { FolderCreate } from "./FolderCreate.js";
export type { FolderUpdate } from "./FolderUpdate.js";
export type { GetFoldersV1FoldersGetRequest } from "./GetFoldersV1FoldersGetRequest.js";
export type { UpdateWorkflowFolderRequest } from "./UpdateWorkflowFolderRequest.js";

View File

@@ -1 +0,0 @@
export * from "./client/index.js";

View File

@@ -8,6 +8,7 @@ export const ActionType = {
SelectOption: "select_option",
Checkbox: "checkbox",
Wait: "wait",
Hover: "hover",
NullAction: "null_action",
SolveCaptcha: "solve_captcha",
Terminate: "terminate",

View File

@@ -20,5 +20,8 @@ export namespace CredentialResponse {
/**
* The credential data
*/
export type Credential = Skyvern.PasswordCredentialResponse | Skyvern.CreditCardCredentialResponse;
export type Credential =
| Skyvern.PasswordCredentialResponse
| Skyvern.CreditCardCredentialResponse
| Skyvern.SecretCredentialResponse;
}

View File

@@ -4,5 +4,6 @@
export const CredentialTypeOutput = {
Password: "password",
CreditCard: "credit_card",
Secret: "secret",
} as const;
export type CredentialTypeOutput = (typeof CredentialTypeOutput)[keyof typeof CredentialTypeOutput];

View File

@@ -1,17 +0,0 @@
// This file was auto-generated by Fern from our API Definition.
/**
* Response model for a folder
*/
export interface Folder {
/** Folder title */
title: string;
/** Folder description */
description?: string;
folder_id: string;
organization_id: string;
/** Number of workflows in this folder */
workflow_count?: number;
created_at: string;
modified_at: string;
}

View File

@@ -16,6 +16,7 @@ export interface HttpRequestBlock {
url?: string;
headers?: Record<string, string | undefined>;
body?: Record<string, unknown>;
files?: Record<string, string | undefined>;
timeout?: number;
follow_redirects?: boolean;
parameters?: Skyvern.HttpRequestBlockParametersItem[];

View File

@@ -12,6 +12,7 @@ export interface HttpRequestBlockYaml {
url?: string;
headers?: Record<string, string | undefined>;
body?: Record<string, unknown>;
files?: Record<string, string | undefined>;
timeout?: number;
follow_redirects?: boolean;
parameter_keys?: string[];

View File

@@ -0,0 +1,11 @@
// This file was auto-generated by Fern from our API Definition.
/**
* Generic secret credential.
*/
export interface SecretCredential {
/** The secret value */
secret_value: string;
/** Optional label describing the secret */
secret_label?: string;
}

View File

@@ -0,0 +1,9 @@
// This file was auto-generated by Fern from our API Definition.
/**
* Response model for secret credentials.
*/
export interface SecretCredentialResponse {
/** Optional label for the stored secret */
secret_label?: string;
}

View File

@@ -4,6 +4,7 @@
export const SkyvernForgeSdkSchemasCredentialsCredentialType = {
Password: "password",
CreditCard: "credit_card",
Secret: "secret",
} as const;
export type SkyvernForgeSdkSchemasCredentialsCredentialType =
(typeof SkyvernForgeSdkSchemasCredentialsCredentialType)[keyof typeof SkyvernForgeSdkSchemasCredentialsCredentialType];

View File

@@ -59,7 +59,6 @@ export * from "./FileStorageType.js";
export * from "./FileType.js";
export * from "./FileUploadBlock.js";
export * from "./FileUploadBlockYaml.js";
export * from "./Folder.js";
export * from "./ForLoopBlock.js";
export * from "./ForLoopBlockLoopBlocksItem.js";
export * from "./ForLoopBlockLoopOver.js";
@@ -104,6 +103,8 @@ export * from "./RunStatus.js";
export * from "./Script.js";
export * from "./ScriptFileCreate.js";
export * from "./ScriptRunResponse.js";
export * from "./SecretCredential.js";
export * from "./SecretCredentialResponse.js";
export * from "./SelectOption.js";
export * from "./SelectOptionAction.js";
export * from "./SendEmailBlock.js";

View File

@@ -1 +1 @@
export const SDK_VERSION = "1.0.2";
export const SDK_VERSION = "1.0.3";

View File

@@ -1,517 +0,0 @@
// This file was auto-generated by Fern from our API Definition.
import * as Skyvern from "../../src/api/index";
import { SkyvernClient } from "../../src/Client";
import { mockServerPool } from "../mock-server/MockServerPool";
describe("Workflows", () => {
test("getFolders (1)", async () => {
const server = mockServerPool.createServer();
const client = new SkyvernClient({ apiKey: "test", environment: server.baseUrl });
const rawResponseBody = [
{
title: "title",
description: "description",
folder_id: "folder_id",
organization_id: "organization_id",
workflow_count: 1,
created_at: "2024-01-15T09:30:00Z",
modified_at: "2024-01-15T09:30:00Z",
},
];
server.mockEndpoint().get("/v1/folders").respondWith().statusCode(200).jsonBody(rawResponseBody).build();
const response = await client.workflows.getFolders({
page: 1,
page_size: 1,
search: "search",
});
expect(response).toEqual([
{
title: "title",
description: "description",
folder_id: "folder_id",
organization_id: "organization_id",
workflow_count: 1,
created_at: "2024-01-15T09:30:00Z",
modified_at: "2024-01-15T09:30:00Z",
},
]);
});
test("getFolders (2)", async () => {
const server = mockServerPool.createServer();
const client = new SkyvernClient({ apiKey: "test", environment: server.baseUrl });
const rawResponseBody = { key: "value" };
server.mockEndpoint().get("/v1/folders").respondWith().statusCode(422).jsonBody(rawResponseBody).build();
await expect(async () => {
return await client.workflows.getFolders();
}).rejects.toThrow(Skyvern.UnprocessableEntityError);
});
test("createFolder (1)", async () => {
const server = mockServerPool.createServer();
const client = new SkyvernClient({ apiKey: "test", environment: server.baseUrl });
const rawRequestBody = { title: "title" };
const rawResponseBody = {
title: "title",
description: "description",
folder_id: "folder_id",
organization_id: "organization_id",
workflow_count: 1,
created_at: "2024-01-15T09:30:00Z",
modified_at: "2024-01-15T09:30:00Z",
};
server
.mockEndpoint()
.post("/v1/folders")
.jsonBody(rawRequestBody)
.respondWith()
.statusCode(200)
.jsonBody(rawResponseBody)
.build();
const response = await client.workflows.createFolder({
title: "title",
});
expect(response).toEqual({
title: "title",
description: "description",
folder_id: "folder_id",
organization_id: "organization_id",
workflow_count: 1,
created_at: "2024-01-15T09:30:00Z",
modified_at: "2024-01-15T09:30:00Z",
});
});
test("createFolder (2)", async () => {
const server = mockServerPool.createServer();
const client = new SkyvernClient({ apiKey: "test", environment: server.baseUrl });
const rawRequestBody = { title: "x" };
const rawResponseBody = { key: "value" };
server
.mockEndpoint()
.post("/v1/folders")
.jsonBody(rawRequestBody)
.respondWith()
.statusCode(400)
.jsonBody(rawResponseBody)
.build();
await expect(async () => {
return await client.workflows.createFolder({
title: "x",
});
}).rejects.toThrow(Skyvern.BadRequestError);
});
test("createFolder (3)", async () => {
const server = mockServerPool.createServer();
const client = new SkyvernClient({ apiKey: "test", environment: server.baseUrl });
const rawRequestBody = { title: "x" };
const rawResponseBody = { key: "value" };
server
.mockEndpoint()
.post("/v1/folders")
.jsonBody(rawRequestBody)
.respondWith()
.statusCode(422)
.jsonBody(rawResponseBody)
.build();
await expect(async () => {
return await client.workflows.createFolder({
title: "x",
});
}).rejects.toThrow(Skyvern.UnprocessableEntityError);
});
test("getFolder (1)", async () => {
const server = mockServerPool.createServer();
const client = new SkyvernClient({ apiKey: "test", environment: server.baseUrl });
const rawResponseBody = {
title: "title",
description: "description",
folder_id: "folder_id",
organization_id: "organization_id",
workflow_count: 1,
created_at: "2024-01-15T09:30:00Z",
modified_at: "2024-01-15T09:30:00Z",
};
server
.mockEndpoint()
.get("/v1/folders/fld_123")
.respondWith()
.statusCode(200)
.jsonBody(rawResponseBody)
.build();
const response = await client.workflows.getFolder("fld_123");
expect(response).toEqual({
title: "title",
description: "description",
folder_id: "folder_id",
organization_id: "organization_id",
workflow_count: 1,
created_at: "2024-01-15T09:30:00Z",
modified_at: "2024-01-15T09:30:00Z",
});
});
test("getFolder (2)", async () => {
const server = mockServerPool.createServer();
const client = new SkyvernClient({ apiKey: "test", environment: server.baseUrl });
const rawResponseBody = { key: "value" };
server
.mockEndpoint()
.get("/v1/folders/folder_id")
.respondWith()
.statusCode(404)
.jsonBody(rawResponseBody)
.build();
await expect(async () => {
return await client.workflows.getFolder("folder_id");
}).rejects.toThrow(Skyvern.NotFoundError);
});
test("getFolder (3)", async () => {
const server = mockServerPool.createServer();
const client = new SkyvernClient({ apiKey: "test", environment: server.baseUrl });
const rawResponseBody = { key: "value" };
server
.mockEndpoint()
.get("/v1/folders/folder_id")
.respondWith()
.statusCode(422)
.jsonBody(rawResponseBody)
.build();
await expect(async () => {
return await client.workflows.getFolder("folder_id");
}).rejects.toThrow(Skyvern.UnprocessableEntityError);
});
test("updateFolder (1)", async () => {
const server = mockServerPool.createServer();
const client = new SkyvernClient({ apiKey: "test", environment: server.baseUrl });
const rawRequestBody = {};
const rawResponseBody = {
title: "title",
description: "description",
folder_id: "folder_id",
organization_id: "organization_id",
workflow_count: 1,
created_at: "2024-01-15T09:30:00Z",
modified_at: "2024-01-15T09:30:00Z",
};
server
.mockEndpoint()
.put("/v1/folders/fld_123")
.jsonBody(rawRequestBody)
.respondWith()
.statusCode(200)
.jsonBody(rawResponseBody)
.build();
const response = await client.workflows.updateFolder("fld_123");
expect(response).toEqual({
title: "title",
description: "description",
folder_id: "folder_id",
organization_id: "organization_id",
workflow_count: 1,
created_at: "2024-01-15T09:30:00Z",
modified_at: "2024-01-15T09:30:00Z",
});
});
test("updateFolder (2)", async () => {
const server = mockServerPool.createServer();
const client = new SkyvernClient({ apiKey: "test", environment: server.baseUrl });
const rawRequestBody = {};
const rawResponseBody = { key: "value" };
server
.mockEndpoint()
.put("/v1/folders/folder_id")
.jsonBody(rawRequestBody)
.respondWith()
.statusCode(404)
.jsonBody(rawResponseBody)
.build();
await expect(async () => {
return await client.workflows.updateFolder("folder_id");
}).rejects.toThrow(Skyvern.NotFoundError);
});
test("updateFolder (3)", async () => {
const server = mockServerPool.createServer();
const client = new SkyvernClient({ apiKey: "test", environment: server.baseUrl });
const rawRequestBody = {};
const rawResponseBody = { key: "value" };
server
.mockEndpoint()
.put("/v1/folders/folder_id")
.jsonBody(rawRequestBody)
.respondWith()
.statusCode(422)
.jsonBody(rawResponseBody)
.build();
await expect(async () => {
return await client.workflows.updateFolder("folder_id");
}).rejects.toThrow(Skyvern.UnprocessableEntityError);
});
test("deleteFolder (1)", async () => {
const server = mockServerPool.createServer();
const client = new SkyvernClient({ apiKey: "test", environment: server.baseUrl });
const rawResponseBody = { key: "value" };
server
.mockEndpoint()
.delete("/v1/folders/fld_123")
.respondWith()
.statusCode(200)
.jsonBody(rawResponseBody)
.build();
const response = await client.workflows.deleteFolder("fld_123", {
delete_workflows: true,
});
expect(response).toEqual({
key: "value",
});
});
test("deleteFolder (2)", async () => {
const server = mockServerPool.createServer();
const client = new SkyvernClient({ apiKey: "test", environment: server.baseUrl });
const rawResponseBody = { key: "value" };
server
.mockEndpoint()
.delete("/v1/folders/folder_id")
.respondWith()
.statusCode(404)
.jsonBody(rawResponseBody)
.build();
await expect(async () => {
return await client.workflows.deleteFolder("folder_id");
}).rejects.toThrow(Skyvern.NotFoundError);
});
test("deleteFolder (3)", async () => {
const server = mockServerPool.createServer();
const client = new SkyvernClient({ apiKey: "test", environment: server.baseUrl });
const rawResponseBody = { key: "value" };
server
.mockEndpoint()
.delete("/v1/folders/folder_id")
.respondWith()
.statusCode(422)
.jsonBody(rawResponseBody)
.build();
await expect(async () => {
return await client.workflows.deleteFolder("folder_id");
}).rejects.toThrow(Skyvern.UnprocessableEntityError);
});
test("updateWorkflowFolder (1)", async () => {
const server = mockServerPool.createServer();
const client = new SkyvernClient({ apiKey: "test", environment: server.baseUrl });
const rawRequestBody = {};
const rawResponseBody = {
workflow_id: "workflow_id",
organization_id: "organization_id",
title: "title",
workflow_permanent_id: "workflow_permanent_id",
version: 1,
is_saved_task: true,
description: "description",
workflow_definition: {
version: 1,
parameters: [
{
parameter_type: "aws_secret",
key: "key",
aws_secret_parameter_id: "aws_secret_parameter_id",
workflow_id: "workflow_id",
aws_key: "aws_key",
created_at: "2024-01-15T09:30:00Z",
modified_at: "2024-01-15T09:30:00Z",
},
],
blocks: [
{
block_type: "action",
label: "label",
output_parameter: {
key: "key",
output_parameter_id: "output_parameter_id",
workflow_id: "workflow_id",
created_at: "2024-01-15T09:30:00Z",
modified_at: "2024-01-15T09:30:00Z",
},
},
],
},
proxy_location: "RESIDENTIAL",
webhook_callback_url: "webhook_callback_url",
totp_verification_url: "totp_verification_url",
totp_identifier: "totp_identifier",
persist_browser_session: true,
model: { key: "value" },
status: "published",
max_screenshot_scrolls: 1,
extra_http_headers: { key: "value" },
run_with: "run_with",
ai_fallback: true,
cache_key: "cache_key",
run_sequentially: true,
sequential_key: "sequential_key",
folder_id: "folder_id",
import_error: "import_error",
created_at: "2024-01-15T09:30:00Z",
modified_at: "2024-01-15T09:30:00Z",
deleted_at: "2024-01-15T09:30:00Z",
};
server
.mockEndpoint()
.put("/v1/workflows/wpid_123/folder")
.jsonBody(rawRequestBody)
.respondWith()
.statusCode(200)
.jsonBody(rawResponseBody)
.build();
const response = await client.workflows.updateWorkflowFolder("wpid_123");
expect(response).toEqual({
workflow_id: "workflow_id",
organization_id: "organization_id",
title: "title",
workflow_permanent_id: "workflow_permanent_id",
version: 1,
is_saved_task: true,
description: "description",
workflow_definition: {
version: 1,
parameters: [
{
parameter_type: "aws_secret",
key: "key",
aws_secret_parameter_id: "aws_secret_parameter_id",
workflow_id: "workflow_id",
aws_key: "aws_key",
created_at: "2024-01-15T09:30:00Z",
modified_at: "2024-01-15T09:30:00Z",
},
],
blocks: [
{
block_type: "action",
label: "label",
output_parameter: {
key: "key",
output_parameter_id: "output_parameter_id",
workflow_id: "workflow_id",
created_at: "2024-01-15T09:30:00Z",
modified_at: "2024-01-15T09:30:00Z",
},
},
],
},
proxy_location: "RESIDENTIAL",
webhook_callback_url: "webhook_callback_url",
totp_verification_url: "totp_verification_url",
totp_identifier: "totp_identifier",
persist_browser_session: true,
model: {
key: "value",
},
status: "published",
max_screenshot_scrolls: 1,
extra_http_headers: {
key: "value",
},
run_with: "run_with",
ai_fallback: true,
cache_key: "cache_key",
run_sequentially: true,
sequential_key: "sequential_key",
folder_id: "folder_id",
import_error: "import_error",
created_at: "2024-01-15T09:30:00Z",
modified_at: "2024-01-15T09:30:00Z",
deleted_at: "2024-01-15T09:30:00Z",
});
});
test("updateWorkflowFolder (2)", async () => {
const server = mockServerPool.createServer();
const client = new SkyvernClient({ apiKey: "test", environment: server.baseUrl });
const rawRequestBody = {};
const rawResponseBody = { key: "value" };
server
.mockEndpoint()
.put("/v1/workflows/workflow_permanent_id/folder")
.jsonBody(rawRequestBody)
.respondWith()
.statusCode(400)
.jsonBody(rawResponseBody)
.build();
await expect(async () => {
return await client.workflows.updateWorkflowFolder("workflow_permanent_id");
}).rejects.toThrow(Skyvern.BadRequestError);
});
test("updateWorkflowFolder (3)", async () => {
const server = mockServerPool.createServer();
const client = new SkyvernClient({ apiKey: "test", environment: server.baseUrl });
const rawRequestBody = {};
const rawResponseBody = { key: "value" };
server
.mockEndpoint()
.put("/v1/workflows/workflow_permanent_id/folder")
.jsonBody(rawRequestBody)
.respondWith()
.statusCode(404)
.jsonBody(rawResponseBody)
.build();
await expect(async () => {
return await client.workflows.updateWorkflowFolder("workflow_permanent_id");
}).rejects.toThrow(Skyvern.NotFoundError);
});
test("updateWorkflowFolder (4)", async () => {
const server = mockServerPool.createServer();
const client = new SkyvernClient({ apiKey: "test", environment: server.baseUrl });
const rawRequestBody = {};
const rawResponseBody = { key: "value" };
server
.mockEndpoint()
.put("/v1/workflows/workflow_permanent_id/folder")
.jsonBody(rawRequestBody)
.respondWith()
.statusCode(422)
.jsonBody(rawResponseBody)
.build();
await expect(async () => {
return await client.workflows.updateWorkflowFolder("workflow_permanent_id");
}).rejects.toThrow(Skyvern.UnprocessableEntityError);
});
});

View File

@@ -137,7 +137,6 @@ if typing.TYPE_CHECKING:
FileType,
FileUploadBlock,
FileUploadBlockYaml,
Folder,
ForLoopBlock,
ForLoopBlockLoopBlocksItem,
ForLoopBlockLoopBlocksItem_Action,
@@ -300,6 +299,8 @@ if typing.TYPE_CHECKING:
Script,
ScriptFileCreate,
ScriptRunResponse,
SecretCredential,
SecretCredentialResponse,
SelectOption,
SelectOptionAction,
SelectOptionActionData,
@@ -495,7 +496,7 @@ if typing.TYPE_CHECKING:
WorkflowStatus,
)
from .errors import BadRequestError, ConflictError, ForbiddenError, NotFoundError, UnprocessableEntityError
from . import scripts, workflows
from . import scripts
from .client import AsyncSkyvern, Skyvern
from .environment import SkyvernEnvironment
from .version import __version__
@@ -633,7 +634,6 @@ _dynamic_imports: typing.Dict[str, str] = {
"FileType": ".types",
"FileUploadBlock": ".types",
"FileUploadBlockYaml": ".types",
"Folder": ".types",
"ForLoopBlock": ".types",
"ForLoopBlockLoopBlocksItem": ".types",
"ForLoopBlockLoopBlocksItem_Action": ".types",
@@ -798,6 +798,8 @@ _dynamic_imports: typing.Dict[str, str] = {
"Script": ".types",
"ScriptFileCreate": ".types",
"ScriptRunResponse": ".types",
"SecretCredential": ".types",
"SecretCredentialResponse": ".types",
"SelectOption": ".types",
"SelectOptionAction": ".types",
"SelectOptionActionData": ".types",
@@ -996,7 +998,6 @@ _dynamic_imports: typing.Dict[str, str] = {
"WorkflowStatus": ".types",
"__version__": ".version",
"scripts": ".scripts",
"workflows": ".workflows",
}
@@ -1155,7 +1156,6 @@ __all__ = [
"FileType",
"FileUploadBlock",
"FileUploadBlockYaml",
"Folder",
"ForLoopBlock",
"ForLoopBlockLoopBlocksItem",
"ForLoopBlockLoopBlocksItem_Action",
@@ -1320,6 +1320,8 @@ __all__ = [
"Script",
"ScriptFileCreate",
"ScriptRunResponse",
"SecretCredential",
"SecretCredentialResponse",
"SelectOption",
"SelectOptionAction",
"SelectOptionActionData",
@@ -1518,5 +1520,4 @@ __all__ = [
"WorkflowStatus",
"__version__",
"scripts",
"workflows",
]

View File

@@ -39,7 +39,6 @@ from .types.workflow_status import WorkflowStatus
if typing.TYPE_CHECKING:
from .scripts.client import AsyncScriptsClient, ScriptsClient
from .workflows.client import AsyncWorkflowsClient, WorkflowsClient
# this is used as the default value for optional parameters
OMIT = typing.cast(typing.Any, ...)
@@ -110,7 +109,6 @@ class Skyvern:
timeout=_defaulted_timeout,
)
self._raw_client = RawSkyvern(client_wrapper=self._client_wrapper)
self._workflows: typing.Optional[WorkflowsClient] = None
self._scripts: typing.Optional[ScriptsClient] = None
@property
@@ -1851,14 +1849,6 @@ class Skyvern:
)
return _response.data
@property
def workflows(self):
if self._workflows is None:
from .workflows.client import WorkflowsClient # noqa: E402
self._workflows = WorkflowsClient(client_wrapper=self._client_wrapper)
return self._workflows
@property
def scripts(self):
if self._scripts is None:
@@ -1934,7 +1924,6 @@ class AsyncSkyvern:
timeout=_defaulted_timeout,
)
self._raw_client = AsyncRawSkyvern(client_wrapper=self._client_wrapper)
self._workflows: typing.Optional[AsyncWorkflowsClient] = None
self._scripts: typing.Optional[AsyncScriptsClient] = None
@property
@@ -3937,14 +3926,6 @@ class AsyncSkyvern:
)
return _response.data
@property
def workflows(self):
if self._workflows is None:
from .workflows.client import AsyncWorkflowsClient # noqa: E402
self._workflows = AsyncWorkflowsClient(client_wrapper=self._client_wrapper)
return self._workflows
@property
def scripts(self):
if self._scripts is None:

View File

@@ -22,10 +22,10 @@ class BaseClientWrapper:
def get_headers(self) -> typing.Dict[str, str]:
headers: typing.Dict[str, str] = {
"User-Agent": "skyvern/1.0.2",
"User-Agent": "skyvern/1.0.3",
"X-Fern-Language": "Python",
"X-Fern-SDK-Name": "skyvern",
"X-Fern-SDK-Version": "1.0.2",
"X-Fern-SDK-Version": "1.0.3",
**(self.get_custom_headers() or {}),
}
if self._api_key is not None:

View File

@@ -148,7 +148,6 @@ if typing.TYPE_CHECKING:
from .file_type import FileType
from .file_upload_block import FileUploadBlock
from .file_upload_block_yaml import FileUploadBlockYaml
from .folder import Folder
from .for_loop_block import ForLoopBlock
from .for_loop_block_loop_blocks_item import (
ForLoopBlockLoopBlocksItem,
@@ -329,6 +328,8 @@ if typing.TYPE_CHECKING:
from .script import Script
from .script_file_create import ScriptFileCreate
from .script_run_response import ScriptRunResponse
from .secret_credential import SecretCredential
from .secret_credential_response import SecretCredentialResponse
from .select_option import SelectOption
from .select_option_action import SelectOptionAction
from .select_option_action_data import SelectOptionActionData
@@ -671,7 +672,6 @@ _dynamic_imports: typing.Dict[str, str] = {
"FileType": ".file_type",
"FileUploadBlock": ".file_upload_block",
"FileUploadBlockYaml": ".file_upload_block_yaml",
"Folder": ".folder",
"ForLoopBlock": ".for_loop_block",
"ForLoopBlockLoopBlocksItem": ".for_loop_block_loop_blocks_item",
"ForLoopBlockLoopBlocksItem_Action": ".for_loop_block_loop_blocks_item",
@@ -834,6 +834,8 @@ _dynamic_imports: typing.Dict[str, str] = {
"Script": ".script",
"ScriptFileCreate": ".script_file_create",
"ScriptRunResponse": ".script_run_response",
"SecretCredential": ".secret_credential",
"SecretCredentialResponse": ".secret_credential_response",
"SelectOption": ".select_option",
"SelectOptionAction": ".select_option_action",
"SelectOptionActionData": ".select_option_action_data",
@@ -1182,7 +1184,6 @@ __all__ = [
"FileType",
"FileUploadBlock",
"FileUploadBlockYaml",
"Folder",
"ForLoopBlock",
"ForLoopBlockLoopBlocksItem",
"ForLoopBlockLoopBlocksItem_Action",
@@ -1345,6 +1346,8 @@ __all__ = [
"Script",
"ScriptFileCreate",
"ScriptRunResponse",
"SecretCredential",
"SecretCredentialResponse",
"SelectOption",
"SelectOptionAction",
"SelectOptionActionData",

View File

@@ -11,6 +11,7 @@ ActionType = typing.Union[
"select_option",
"checkbox",
"wait",
"hover",
"null_action",
"solve_captcha",
"terminate",

View File

@@ -4,5 +4,8 @@ import typing
from .non_empty_credit_card_credential import NonEmptyCreditCardCredential
from .non_empty_password_credential import NonEmptyPasswordCredential
from .secret_credential import SecretCredential
CreateCredentialRequestCredential = typing.Union[NonEmptyPasswordCredential, NonEmptyCreditCardCredential]
CreateCredentialRequestCredential = typing.Union[
NonEmptyPasswordCredential, NonEmptyCreditCardCredential, SecretCredential
]

View File

@@ -4,5 +4,8 @@ import typing
from .credit_card_credential_response import CreditCardCredentialResponse
from .password_credential_response import PasswordCredentialResponse
from .secret_credential_response import SecretCredentialResponse
CredentialResponseCredential = typing.Union[PasswordCredentialResponse, CreditCardCredentialResponse]
CredentialResponseCredential = typing.Union[
PasswordCredentialResponse, CreditCardCredentialResponse, SecretCredentialResponse
]

View File

@@ -2,4 +2,4 @@
import typing
CredentialTypeOutput = typing.Union[typing.Literal["password", "credit_card"], typing.Any]
CredentialTypeOutput = typing.Union[typing.Literal["password", "credit_card", "secret"], typing.Any]

View File

@@ -355,6 +355,7 @@ class ForLoopBlockLoopBlocksItem_HttpRequest(UniversalBaseModel):
url: typing.Optional[str] = None
headers: typing.Optional[typing.Dict[str, typing.Optional[str]]] = None
body: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = None
files: typing.Optional[typing.Dict[str, typing.Optional[str]]] = None
timeout: typing.Optional[int] = None
follow_redirects: typing.Optional[bool] = None
parameters: typing.Optional[typing.List[HttpRequestBlockParametersItem]] = None

View File

@@ -532,6 +532,7 @@ class ForLoopBlockYamlLoopBlocksItem_HttpRequest(UniversalBaseModel):
url: typing.Optional[str] = None
headers: typing.Optional[typing.Dict[str, typing.Optional[str]]] = None
body: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = None
files: typing.Optional[typing.Dict[str, typing.Optional[str]]] = None
timeout: typing.Optional[int] = None
follow_redirects: typing.Optional[bool] = None
parameter_keys: typing.Optional[typing.List[str]] = None

View File

@@ -30,6 +30,7 @@ class HttpRequestBlock(UniversalBaseModel):
url: typing.Optional[str] = None
headers: typing.Optional[typing.Dict[str, typing.Optional[str]]] = None
body: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = None
files: typing.Optional[typing.Dict[str, typing.Optional[str]]] = None
timeout: typing.Optional[int] = None
follow_redirects: typing.Optional[bool] = None
parameters: typing.Optional[typing.List[HttpRequestBlockParametersItem]] = None

View File

@@ -24,6 +24,7 @@ class HttpRequestBlockYaml(UniversalBaseModel):
url: typing.Optional[str] = None
headers: typing.Optional[typing.Dict[str, typing.Optional[str]]] = None
body: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = None
files: typing.Optional[typing.Dict[str, typing.Optional[str]]] = None
timeout: typing.Optional[int] = None
follow_redirects: typing.Optional[bool] = None
parameter_keys: typing.Optional[typing.List[str]] = None

View File

@@ -1,37 +1,26 @@
# This file was auto-generated by Fern from our API Definition.
import datetime as dt
import typing
import pydantic
from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
class Folder(UniversalBaseModel):
class SecretCredential(UniversalBaseModel):
"""
Response model for a folder
Generic secret credential.
"""
title: str = pydantic.Field()
secret_value: str = pydantic.Field()
"""
Folder title
The secret value
"""
description: typing.Optional[str] = pydantic.Field(default=None)
secret_label: typing.Optional[str] = pydantic.Field(default=None)
"""
Folder description
Optional label describing the secret
"""
folder_id: str
organization_id: str
workflow_count: typing.Optional[int] = pydantic.Field(default=None)
"""
Number of workflows in this folder
"""
created_at: dt.datetime
modified_at: dt.datetime
if IS_PYDANTIC_V2:
model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
else:

View File

@@ -0,0 +1,26 @@
# This file was auto-generated by Fern from our API Definition.
import typing
import pydantic
from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
class SecretCredentialResponse(UniversalBaseModel):
"""
Response model for secret credentials.
"""
secret_label: typing.Optional[str] = pydantic.Field(default=None)
"""
Optional label for the stored secret
"""
if IS_PYDANTIC_V2:
model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
else:
class Config:
frozen = True
smart_union = True
extra = pydantic.Extra.allow

View File

@@ -2,4 +2,6 @@
import typing
SkyvernForgeSdkSchemasCredentialsCredentialType = typing.Union[typing.Literal["password", "credit_card"], typing.Any]
SkyvernForgeSdkSchemasCredentialsCredentialType = typing.Union[
typing.Literal["password", "credit_card", "secret"], typing.Any
]

View File

@@ -356,6 +356,7 @@ class WorkflowDefinitionBlocksItem_HttpRequest(UniversalBaseModel):
url: typing.Optional[str] = None
headers: typing.Optional[typing.Dict[str, typing.Optional[str]]] = None
body: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = None
files: typing.Optional[typing.Dict[str, typing.Optional[str]]] = None
timeout: typing.Optional[int] = None
follow_redirects: typing.Optional[bool] = None
parameters: typing.Optional[typing.List[HttpRequestBlockParametersItem]] = None

View File

@@ -267,6 +267,7 @@ class WorkflowDefinitionYamlBlocksItem_HttpRequest(UniversalBaseModel):
url: typing.Optional[str] = None
headers: typing.Optional[typing.Dict[str, typing.Optional[str]]] = None
body: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = None
files: typing.Optional[typing.Dict[str, typing.Optional[str]]] = None
timeout: typing.Optional[int] = None
follow_redirects: typing.Optional[bool] = None
parameter_keys: typing.Optional[typing.List[str]] = None

View File

@@ -1,4 +0,0 @@
# This file was auto-generated by Fern from our API Definition.
# isort: skip_file

View File

@@ -1,596 +0,0 @@
# This file was auto-generated by Fern from our API Definition.
import typing
from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
from ..core.request_options import RequestOptions
from ..types.folder import Folder
from ..types.workflow import Workflow
from .raw_client import AsyncRawWorkflowsClient, RawWorkflowsClient
# this is used as the default value for optional parameters
OMIT = typing.cast(typing.Any, ...)
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 get_folders(
self,
*,
page: typing.Optional[int] = None,
page_size: typing.Optional[int] = None,
search: typing.Optional[str] = None,
request_options: typing.Optional[RequestOptions] = None,
) -> typing.List[Folder]:
"""
Get all folders for the organization
Parameters
----------
page : typing.Optional[int]
Page number
page_size : typing.Optional[int]
Number of folders per page
search : typing.Optional[str]
Search folders by title or description
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
Returns
-------
typing.List[Folder]
Successfully retrieved folders
Examples
--------
from skyvern import Skyvern
client = Skyvern(
api_key="YOUR_API_KEY",
)
client.workflows.get_folders(
page=1,
page_size=1,
search="search",
)
"""
_response = self._raw_client.get_folders(
page=page, page_size=page_size, search=search, request_options=request_options
)
return _response.data
def create_folder(
self,
*,
title: str,
description: typing.Optional[str] = OMIT,
request_options: typing.Optional[RequestOptions] = None,
) -> Folder:
"""
Create a new folder to organize workflows
Parameters
----------
title : str
Folder title
description : typing.Optional[str]
Folder description
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
Returns
-------
Folder
Successfully created folder
Examples
--------
from skyvern import Skyvern
client = Skyvern(
api_key="YOUR_API_KEY",
)
client.workflows.create_folder(
title="title",
)
"""
_response = self._raw_client.create_folder(
title=title, description=description, request_options=request_options
)
return _response.data
def get_folder(self, folder_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> Folder:
"""
Get a specific folder by ID
Parameters
----------
folder_id : str
Folder ID
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
Returns
-------
Folder
Successfully retrieved folder
Examples
--------
from skyvern import Skyvern
client = Skyvern(
api_key="YOUR_API_KEY",
)
client.workflows.get_folder(
folder_id="fld_123",
)
"""
_response = self._raw_client.get_folder(folder_id, request_options=request_options)
return _response.data
def update_folder(
self,
folder_id: str,
*,
title: typing.Optional[str] = OMIT,
description: typing.Optional[str] = OMIT,
request_options: typing.Optional[RequestOptions] = None,
) -> Folder:
"""
Update a folder's title or description
Parameters
----------
folder_id : str
Folder ID
title : typing.Optional[str]
Folder title
description : typing.Optional[str]
Folder description
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
Returns
-------
Folder
Successfully updated folder
Examples
--------
from skyvern import Skyvern
client = Skyvern(
api_key="YOUR_API_KEY",
)
client.workflows.update_folder(
folder_id="fld_123",
)
"""
_response = self._raw_client.update_folder(
folder_id, title=title, description=description, request_options=request_options
)
return _response.data
def delete_folder(
self,
folder_id: str,
*,
delete_workflows: typing.Optional[bool] = None,
request_options: typing.Optional[RequestOptions] = None,
) -> typing.Dict[str, typing.Optional[typing.Any]]:
"""
Delete a folder. Optionally delete all workflows in the folder.
Parameters
----------
folder_id : str
Folder ID
delete_workflows : typing.Optional[bool]
If true, also delete all workflows in this folder
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
Returns
-------
typing.Dict[str, typing.Optional[typing.Any]]
Successfully deleted folder
Examples
--------
from skyvern import Skyvern
client = Skyvern(
api_key="YOUR_API_KEY",
)
client.workflows.delete_folder(
folder_id="fld_123",
delete_workflows=True,
)
"""
_response = self._raw_client.delete_folder(
folder_id, delete_workflows=delete_workflows, request_options=request_options
)
return _response.data
def update_workflow_folder(
self,
workflow_permanent_id: str,
*,
folder_id: typing.Optional[str] = OMIT,
request_options: typing.Optional[RequestOptions] = None,
) -> Workflow:
"""
Update a workflow's folder assignment for the latest version
Parameters
----------
workflow_permanent_id : str
Workflow permanent ID
folder_id : typing.Optional[str]
Folder ID to assign workflow to. Set to null to remove from folder.
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
Returns
-------
Workflow
Successfully updated workflow folder
Examples
--------
from skyvern import Skyvern
client = Skyvern(
api_key="YOUR_API_KEY",
)
client.workflows.update_workflow_folder(
workflow_permanent_id="wpid_123",
)
"""
_response = self._raw_client.update_workflow_folder(
workflow_permanent_id, folder_id=folder_id, 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 get_folders(
self,
*,
page: typing.Optional[int] = None,
page_size: typing.Optional[int] = None,
search: typing.Optional[str] = None,
request_options: typing.Optional[RequestOptions] = None,
) -> typing.List[Folder]:
"""
Get all folders for the organization
Parameters
----------
page : typing.Optional[int]
Page number
page_size : typing.Optional[int]
Number of folders per page
search : typing.Optional[str]
Search folders by title or description
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
Returns
-------
typing.List[Folder]
Successfully retrieved folders
Examples
--------
import asyncio
from skyvern import AsyncSkyvern
client = AsyncSkyvern(
api_key="YOUR_API_KEY",
)
async def main() -> None:
await client.workflows.get_folders(
page=1,
page_size=1,
search="search",
)
asyncio.run(main())
"""
_response = await self._raw_client.get_folders(
page=page, page_size=page_size, search=search, request_options=request_options
)
return _response.data
async def create_folder(
self,
*,
title: str,
description: typing.Optional[str] = OMIT,
request_options: typing.Optional[RequestOptions] = None,
) -> Folder:
"""
Create a new folder to organize workflows
Parameters
----------
title : str
Folder title
description : typing.Optional[str]
Folder description
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
Returns
-------
Folder
Successfully created folder
Examples
--------
import asyncio
from skyvern import AsyncSkyvern
client = AsyncSkyvern(
api_key="YOUR_API_KEY",
)
async def main() -> None:
await client.workflows.create_folder(
title="title",
)
asyncio.run(main())
"""
_response = await self._raw_client.create_folder(
title=title, description=description, request_options=request_options
)
return _response.data
async def get_folder(self, folder_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> Folder:
"""
Get a specific folder by ID
Parameters
----------
folder_id : str
Folder ID
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
Returns
-------
Folder
Successfully retrieved folder
Examples
--------
import asyncio
from skyvern import AsyncSkyvern
client = AsyncSkyvern(
api_key="YOUR_API_KEY",
)
async def main() -> None:
await client.workflows.get_folder(
folder_id="fld_123",
)
asyncio.run(main())
"""
_response = await self._raw_client.get_folder(folder_id, request_options=request_options)
return _response.data
async def update_folder(
self,
folder_id: str,
*,
title: typing.Optional[str] = OMIT,
description: typing.Optional[str] = OMIT,
request_options: typing.Optional[RequestOptions] = None,
) -> Folder:
"""
Update a folder's title or description
Parameters
----------
folder_id : str
Folder ID
title : typing.Optional[str]
Folder title
description : typing.Optional[str]
Folder description
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
Returns
-------
Folder
Successfully updated folder
Examples
--------
import asyncio
from skyvern import AsyncSkyvern
client = AsyncSkyvern(
api_key="YOUR_API_KEY",
)
async def main() -> None:
await client.workflows.update_folder(
folder_id="fld_123",
)
asyncio.run(main())
"""
_response = await self._raw_client.update_folder(
folder_id, title=title, description=description, request_options=request_options
)
return _response.data
async def delete_folder(
self,
folder_id: str,
*,
delete_workflows: typing.Optional[bool] = None,
request_options: typing.Optional[RequestOptions] = None,
) -> typing.Dict[str, typing.Optional[typing.Any]]:
"""
Delete a folder. Optionally delete all workflows in the folder.
Parameters
----------
folder_id : str
Folder ID
delete_workflows : typing.Optional[bool]
If true, also delete all workflows in this folder
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
Returns
-------
typing.Dict[str, typing.Optional[typing.Any]]
Successfully deleted folder
Examples
--------
import asyncio
from skyvern import AsyncSkyvern
client = AsyncSkyvern(
api_key="YOUR_API_KEY",
)
async def main() -> None:
await client.workflows.delete_folder(
folder_id="fld_123",
delete_workflows=True,
)
asyncio.run(main())
"""
_response = await self._raw_client.delete_folder(
folder_id, delete_workflows=delete_workflows, request_options=request_options
)
return _response.data
async def update_workflow_folder(
self,
workflow_permanent_id: str,
*,
folder_id: typing.Optional[str] = OMIT,
request_options: typing.Optional[RequestOptions] = None,
) -> Workflow:
"""
Update a workflow's folder assignment for the latest version
Parameters
----------
workflow_permanent_id : str
Workflow permanent ID
folder_id : typing.Optional[str]
Folder ID to assign workflow to. Set to null to remove from folder.
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
Returns
-------
Workflow
Successfully updated workflow folder
Examples
--------
import asyncio
from skyvern import AsyncSkyvern
client = AsyncSkyvern(
api_key="YOUR_API_KEY",
)
async def main() -> None:
await client.workflows.update_workflow_folder(
workflow_permanent_id="wpid_123",
)
asyncio.run(main())
"""
_response = await self._raw_client.update_workflow_folder(
workflow_permanent_id, folder_id=folder_id, request_options=request_options
)
return _response.data

View File

@@ -1,909 +0,0 @@
# This file was auto-generated by Fern from our API Definition.
import typing
from json.decoder import JSONDecodeError
from ..core.api_error import ApiError
from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
from ..core.http_response import AsyncHttpResponse, HttpResponse
from ..core.jsonable_encoder import jsonable_encoder
from ..core.pydantic_utilities import parse_obj_as
from ..core.request_options import RequestOptions
from ..errors.bad_request_error import BadRequestError
from ..errors.not_found_error import NotFoundError
from ..errors.unprocessable_entity_error import UnprocessableEntityError
from ..types.folder import Folder
from ..types.workflow import Workflow
# this is used as the default value for optional parameters
OMIT = typing.cast(typing.Any, ...)
class RawWorkflowsClient:
def __init__(self, *, client_wrapper: SyncClientWrapper):
self._client_wrapper = client_wrapper
def get_folders(
self,
*,
page: typing.Optional[int] = None,
page_size: typing.Optional[int] = None,
search: typing.Optional[str] = None,
request_options: typing.Optional[RequestOptions] = None,
) -> HttpResponse[typing.List[Folder]]:
"""
Get all folders for the organization
Parameters
----------
page : typing.Optional[int]
Page number
page_size : typing.Optional[int]
Number of folders per page
search : typing.Optional[str]
Search folders by title or description
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
Returns
-------
HttpResponse[typing.List[Folder]]
Successfully retrieved folders
"""
_response = self._client_wrapper.httpx_client.request(
"v1/folders",
method="GET",
params={
"page": page,
"page_size": page_size,
"search": search,
},
request_options=request_options,
)
try:
if 200 <= _response.status_code < 300:
_data = typing.cast(
typing.List[Folder],
parse_obj_as(
type_=typing.List[Folder], # type: ignore
object_=_response.json(),
),
)
return HttpResponse(response=_response, data=_data)
if _response.status_code == 422:
raise UnprocessableEntityError(
headers=dict(_response.headers),
body=typing.cast(
typing.Optional[typing.Any],
parse_obj_as(
type_=typing.Optional[typing.Any], # type: ignore
object_=_response.json(),
),
),
)
_response_json = _response.json()
except JSONDecodeError:
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
def create_folder(
self,
*,
title: str,
description: typing.Optional[str] = OMIT,
request_options: typing.Optional[RequestOptions] = None,
) -> HttpResponse[Folder]:
"""
Create a new folder to organize workflows
Parameters
----------
title : str
Folder title
description : typing.Optional[str]
Folder description
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
Returns
-------
HttpResponse[Folder]
Successfully created folder
"""
_response = self._client_wrapper.httpx_client.request(
"v1/folders",
method="POST",
json={
"title": title,
"description": description,
},
headers={
"content-type": "application/json",
},
request_options=request_options,
omit=OMIT,
)
try:
if 200 <= _response.status_code < 300:
_data = typing.cast(
Folder,
parse_obj_as(
type_=Folder, # type: ignore
object_=_response.json(),
),
)
return HttpResponse(response=_response, data=_data)
if _response.status_code == 400:
raise BadRequestError(
headers=dict(_response.headers),
body=typing.cast(
typing.Optional[typing.Any],
parse_obj_as(
type_=typing.Optional[typing.Any], # type: ignore
object_=_response.json(),
),
),
)
if _response.status_code == 422:
raise UnprocessableEntityError(
headers=dict(_response.headers),
body=typing.cast(
typing.Optional[typing.Any],
parse_obj_as(
type_=typing.Optional[typing.Any], # type: ignore
object_=_response.json(),
),
),
)
_response_json = _response.json()
except JSONDecodeError:
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
def get_folder(
self, folder_id: str, *, request_options: typing.Optional[RequestOptions] = None
) -> HttpResponse[Folder]:
"""
Get a specific folder by ID
Parameters
----------
folder_id : str
Folder ID
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
Returns
-------
HttpResponse[Folder]
Successfully retrieved folder
"""
_response = self._client_wrapper.httpx_client.request(
f"v1/folders/{jsonable_encoder(folder_id)}",
method="GET",
request_options=request_options,
)
try:
if 200 <= _response.status_code < 300:
_data = typing.cast(
Folder,
parse_obj_as(
type_=Folder, # type: ignore
object_=_response.json(),
),
)
return HttpResponse(response=_response, data=_data)
if _response.status_code == 404:
raise NotFoundError(
headers=dict(_response.headers),
body=typing.cast(
typing.Optional[typing.Any],
parse_obj_as(
type_=typing.Optional[typing.Any], # type: ignore
object_=_response.json(),
),
),
)
if _response.status_code == 422:
raise UnprocessableEntityError(
headers=dict(_response.headers),
body=typing.cast(
typing.Optional[typing.Any],
parse_obj_as(
type_=typing.Optional[typing.Any], # type: ignore
object_=_response.json(),
),
),
)
_response_json = _response.json()
except JSONDecodeError:
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
def update_folder(
self,
folder_id: str,
*,
title: typing.Optional[str] = OMIT,
description: typing.Optional[str] = OMIT,
request_options: typing.Optional[RequestOptions] = None,
) -> HttpResponse[Folder]:
"""
Update a folder's title or description
Parameters
----------
folder_id : str
Folder ID
title : typing.Optional[str]
Folder title
description : typing.Optional[str]
Folder description
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
Returns
-------
HttpResponse[Folder]
Successfully updated folder
"""
_response = self._client_wrapper.httpx_client.request(
f"v1/folders/{jsonable_encoder(folder_id)}",
method="PUT",
json={
"title": title,
"description": description,
},
headers={
"content-type": "application/json",
},
request_options=request_options,
omit=OMIT,
)
try:
if 200 <= _response.status_code < 300:
_data = typing.cast(
Folder,
parse_obj_as(
type_=Folder, # type: ignore
object_=_response.json(),
),
)
return HttpResponse(response=_response, data=_data)
if _response.status_code == 404:
raise NotFoundError(
headers=dict(_response.headers),
body=typing.cast(
typing.Optional[typing.Any],
parse_obj_as(
type_=typing.Optional[typing.Any], # type: ignore
object_=_response.json(),
),
),
)
if _response.status_code == 422:
raise UnprocessableEntityError(
headers=dict(_response.headers),
body=typing.cast(
typing.Optional[typing.Any],
parse_obj_as(
type_=typing.Optional[typing.Any], # type: ignore
object_=_response.json(),
),
),
)
_response_json = _response.json()
except JSONDecodeError:
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
def delete_folder(
self,
folder_id: str,
*,
delete_workflows: typing.Optional[bool] = None,
request_options: typing.Optional[RequestOptions] = None,
) -> HttpResponse[typing.Dict[str, typing.Optional[typing.Any]]]:
"""
Delete a folder. Optionally delete all workflows in the folder.
Parameters
----------
folder_id : str
Folder ID
delete_workflows : typing.Optional[bool]
If true, also delete all workflows in this folder
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
Returns
-------
HttpResponse[typing.Dict[str, typing.Optional[typing.Any]]]
Successfully deleted folder
"""
_response = self._client_wrapper.httpx_client.request(
f"v1/folders/{jsonable_encoder(folder_id)}",
method="DELETE",
params={
"delete_workflows": delete_workflows,
},
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 == 404:
raise NotFoundError(
headers=dict(_response.headers),
body=typing.cast(
typing.Optional[typing.Any],
parse_obj_as(
type_=typing.Optional[typing.Any], # type: ignore
object_=_response.json(),
),
),
)
if _response.status_code == 422:
raise UnprocessableEntityError(
headers=dict(_response.headers),
body=typing.cast(
typing.Optional[typing.Any],
parse_obj_as(
type_=typing.Optional[typing.Any], # type: ignore
object_=_response.json(),
),
),
)
_response_json = _response.json()
except JSONDecodeError:
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
def update_workflow_folder(
self,
workflow_permanent_id: str,
*,
folder_id: typing.Optional[str] = OMIT,
request_options: typing.Optional[RequestOptions] = None,
) -> HttpResponse[Workflow]:
"""
Update a workflow's folder assignment for the latest version
Parameters
----------
workflow_permanent_id : str
Workflow permanent ID
folder_id : typing.Optional[str]
Folder ID to assign workflow to. Set to null to remove from folder.
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
Returns
-------
HttpResponse[Workflow]
Successfully updated workflow folder
"""
_response = self._client_wrapper.httpx_client.request(
f"v1/workflows/{jsonable_encoder(workflow_permanent_id)}/folder",
method="PUT",
json={
"folder_id": folder_id,
},
headers={
"content-type": "application/json",
},
request_options=request_options,
omit=OMIT,
)
try:
if 200 <= _response.status_code < 300:
_data = typing.cast(
Workflow,
parse_obj_as(
type_=Workflow, # type: ignore
object_=_response.json(),
),
)
return HttpResponse(response=_response, data=_data)
if _response.status_code == 400:
raise BadRequestError(
headers=dict(_response.headers),
body=typing.cast(
typing.Optional[typing.Any],
parse_obj_as(
type_=typing.Optional[typing.Any], # type: ignore
object_=_response.json(),
),
),
)
if _response.status_code == 404:
raise NotFoundError(
headers=dict(_response.headers),
body=typing.cast(
typing.Optional[typing.Any],
parse_obj_as(
type_=typing.Optional[typing.Any], # type: ignore
object_=_response.json(),
),
),
)
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 get_folders(
self,
*,
page: typing.Optional[int] = None,
page_size: typing.Optional[int] = None,
search: typing.Optional[str] = None,
request_options: typing.Optional[RequestOptions] = None,
) -> AsyncHttpResponse[typing.List[Folder]]:
"""
Get all folders for the organization
Parameters
----------
page : typing.Optional[int]
Page number
page_size : typing.Optional[int]
Number of folders per page
search : typing.Optional[str]
Search folders by title or description
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
Returns
-------
AsyncHttpResponse[typing.List[Folder]]
Successfully retrieved folders
"""
_response = await self._client_wrapper.httpx_client.request(
"v1/folders",
method="GET",
params={
"page": page,
"page_size": page_size,
"search": search,
},
request_options=request_options,
)
try:
if 200 <= _response.status_code < 300:
_data = typing.cast(
typing.List[Folder],
parse_obj_as(
type_=typing.List[Folder], # type: ignore
object_=_response.json(),
),
)
return AsyncHttpResponse(response=_response, data=_data)
if _response.status_code == 422:
raise UnprocessableEntityError(
headers=dict(_response.headers),
body=typing.cast(
typing.Optional[typing.Any],
parse_obj_as(
type_=typing.Optional[typing.Any], # type: ignore
object_=_response.json(),
),
),
)
_response_json = _response.json()
except JSONDecodeError:
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
async def create_folder(
self,
*,
title: str,
description: typing.Optional[str] = OMIT,
request_options: typing.Optional[RequestOptions] = None,
) -> AsyncHttpResponse[Folder]:
"""
Create a new folder to organize workflows
Parameters
----------
title : str
Folder title
description : typing.Optional[str]
Folder description
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
Returns
-------
AsyncHttpResponse[Folder]
Successfully created folder
"""
_response = await self._client_wrapper.httpx_client.request(
"v1/folders",
method="POST",
json={
"title": title,
"description": description,
},
headers={
"content-type": "application/json",
},
request_options=request_options,
omit=OMIT,
)
try:
if 200 <= _response.status_code < 300:
_data = typing.cast(
Folder,
parse_obj_as(
type_=Folder, # type: ignore
object_=_response.json(),
),
)
return AsyncHttpResponse(response=_response, data=_data)
if _response.status_code == 400:
raise BadRequestError(
headers=dict(_response.headers),
body=typing.cast(
typing.Optional[typing.Any],
parse_obj_as(
type_=typing.Optional[typing.Any], # type: ignore
object_=_response.json(),
),
),
)
if _response.status_code == 422:
raise UnprocessableEntityError(
headers=dict(_response.headers),
body=typing.cast(
typing.Optional[typing.Any],
parse_obj_as(
type_=typing.Optional[typing.Any], # type: ignore
object_=_response.json(),
),
),
)
_response_json = _response.json()
except JSONDecodeError:
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
async def get_folder(
self, folder_id: str, *, request_options: typing.Optional[RequestOptions] = None
) -> AsyncHttpResponse[Folder]:
"""
Get a specific folder by ID
Parameters
----------
folder_id : str
Folder ID
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
Returns
-------
AsyncHttpResponse[Folder]
Successfully retrieved folder
"""
_response = await self._client_wrapper.httpx_client.request(
f"v1/folders/{jsonable_encoder(folder_id)}",
method="GET",
request_options=request_options,
)
try:
if 200 <= _response.status_code < 300:
_data = typing.cast(
Folder,
parse_obj_as(
type_=Folder, # type: ignore
object_=_response.json(),
),
)
return AsyncHttpResponse(response=_response, data=_data)
if _response.status_code == 404:
raise NotFoundError(
headers=dict(_response.headers),
body=typing.cast(
typing.Optional[typing.Any],
parse_obj_as(
type_=typing.Optional[typing.Any], # type: ignore
object_=_response.json(),
),
),
)
if _response.status_code == 422:
raise UnprocessableEntityError(
headers=dict(_response.headers),
body=typing.cast(
typing.Optional[typing.Any],
parse_obj_as(
type_=typing.Optional[typing.Any], # type: ignore
object_=_response.json(),
),
),
)
_response_json = _response.json()
except JSONDecodeError:
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
async def update_folder(
self,
folder_id: str,
*,
title: typing.Optional[str] = OMIT,
description: typing.Optional[str] = OMIT,
request_options: typing.Optional[RequestOptions] = None,
) -> AsyncHttpResponse[Folder]:
"""
Update a folder's title or description
Parameters
----------
folder_id : str
Folder ID
title : typing.Optional[str]
Folder title
description : typing.Optional[str]
Folder description
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
Returns
-------
AsyncHttpResponse[Folder]
Successfully updated folder
"""
_response = await self._client_wrapper.httpx_client.request(
f"v1/folders/{jsonable_encoder(folder_id)}",
method="PUT",
json={
"title": title,
"description": description,
},
headers={
"content-type": "application/json",
},
request_options=request_options,
omit=OMIT,
)
try:
if 200 <= _response.status_code < 300:
_data = typing.cast(
Folder,
parse_obj_as(
type_=Folder, # type: ignore
object_=_response.json(),
),
)
return AsyncHttpResponse(response=_response, data=_data)
if _response.status_code == 404:
raise NotFoundError(
headers=dict(_response.headers),
body=typing.cast(
typing.Optional[typing.Any],
parse_obj_as(
type_=typing.Optional[typing.Any], # type: ignore
object_=_response.json(),
),
),
)
if _response.status_code == 422:
raise UnprocessableEntityError(
headers=dict(_response.headers),
body=typing.cast(
typing.Optional[typing.Any],
parse_obj_as(
type_=typing.Optional[typing.Any], # type: ignore
object_=_response.json(),
),
),
)
_response_json = _response.json()
except JSONDecodeError:
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
async def delete_folder(
self,
folder_id: str,
*,
delete_workflows: typing.Optional[bool] = None,
request_options: typing.Optional[RequestOptions] = None,
) -> AsyncHttpResponse[typing.Dict[str, typing.Optional[typing.Any]]]:
"""
Delete a folder. Optionally delete all workflows in the folder.
Parameters
----------
folder_id : str
Folder ID
delete_workflows : typing.Optional[bool]
If true, also delete all workflows in this folder
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
Returns
-------
AsyncHttpResponse[typing.Dict[str, typing.Optional[typing.Any]]]
Successfully deleted folder
"""
_response = await self._client_wrapper.httpx_client.request(
f"v1/folders/{jsonable_encoder(folder_id)}",
method="DELETE",
params={
"delete_workflows": delete_workflows,
},
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 == 404:
raise NotFoundError(
headers=dict(_response.headers),
body=typing.cast(
typing.Optional[typing.Any],
parse_obj_as(
type_=typing.Optional[typing.Any], # type: ignore
object_=_response.json(),
),
),
)
if _response.status_code == 422:
raise UnprocessableEntityError(
headers=dict(_response.headers),
body=typing.cast(
typing.Optional[typing.Any],
parse_obj_as(
type_=typing.Optional[typing.Any], # type: ignore
object_=_response.json(),
),
),
)
_response_json = _response.json()
except JSONDecodeError:
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
async def update_workflow_folder(
self,
workflow_permanent_id: str,
*,
folder_id: typing.Optional[str] = OMIT,
request_options: typing.Optional[RequestOptions] = None,
) -> AsyncHttpResponse[Workflow]:
"""
Update a workflow's folder assignment for the latest version
Parameters
----------
workflow_permanent_id : str
Workflow permanent ID
folder_id : typing.Optional[str]
Folder ID to assign workflow to. Set to null to remove from folder.
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
Returns
-------
AsyncHttpResponse[Workflow]
Successfully updated workflow folder
"""
_response = await self._client_wrapper.httpx_client.request(
f"v1/workflows/{jsonable_encoder(workflow_permanent_id)}/folder",
method="PUT",
json={
"folder_id": folder_id,
},
headers={
"content-type": "application/json",
},
request_options=request_options,
omit=OMIT,
)
try:
if 200 <= _response.status_code < 300:
_data = typing.cast(
Workflow,
parse_obj_as(
type_=Workflow, # type: ignore
object_=_response.json(),
),
)
return AsyncHttpResponse(response=_response, data=_data)
if _response.status_code == 400:
raise BadRequestError(
headers=dict(_response.headers),
body=typing.cast(
typing.Optional[typing.Any],
parse_obj_as(
type_=typing.Optional[typing.Any], # type: ignore
object_=_response.json(),
),
),
)
if _response.status_code == 404:
raise NotFoundError(
headers=dict(_response.headers),
body=typing.cast(
typing.Optional[typing.Any],
parse_obj_as(
type_=typing.Optional[typing.Any], # type: ignore
object_=_response.json(),
),
),
)
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)

2
uv.lock generated
View File

@@ -5029,7 +5029,7 @@ wheels = [
[[package]]
name = "skyvern"
version = "1.0.2"
version = "1.0.3"
source = { editable = "." }
dependencies = [
{ name = "aioboto3" },