diff --git a/pyproject.toml b/pyproject.toml index 90b3c36af..1145f40e9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "skyvern" -version = "1.0.30" +version = "1.0.31" description = "" authors = [{ name = "Skyvern AI", email = "info@skyvern.com" }] requires-python = ">=3.11,<3.14" diff --git a/skyvern-ts/client/README.md b/skyvern-ts/client/README.md index b1fa9680d..4ef64c35f 100644 --- a/skyvern-ts/client/README.md +++ b/skyvern-ts/client/README.md @@ -11,7 +11,6 @@ The Skyvern TypeScript library provides convenient access to the Skyvern APIs fr - [Usage](#usage) - [Request and Response Types](#request-and-response-types) - [Exception Handling](#exception-handling) -- [File Uploads](#file-uploads) - [Advanced](#advanced) - [Additional Headers](#additional-headers) - [Additional Query String Parameters](#additional-query-string-parameters) @@ -56,7 +55,7 @@ following namespace: ```typescript import { Skyvern } from "@skyvern/client"; -const request: Skyvern.RunTaskRequest = { +const request: Skyvern.SchedulesListAllRequest = { ... }; ``` @@ -81,50 +80,6 @@ try { } ``` -## File Uploads - -You can upload files using the client: - -```typescript -import { createReadStream } from "fs"; -import { SkyvernClient } from "@skyvern/client"; -import * as fs from "fs"; - -const client = new SkyvernClient({ apiKey: "YOUR_API_KEY" }); -await client.uploadFile({ - file: fs.createReadStream("/path/to/your/file") -}); -``` -The client accepts a variety of types for file upload parameters: -* Stream types: `fs.ReadStream`, `stream.Readable`, and `ReadableStream` -* Buffered types: `Buffer`, `Blob`, `File`, `ArrayBuffer`, `ArrayBufferView`, and `Uint8Array` - -### Metadata - -You can configure metadata when uploading a file: -```typescript -const file: Uploadable.WithMetadata = { - data: createReadStream("path/to/file"), - filename: "my-file", // optional - contentType: "audio/mpeg", // optional - contentLength: 1949, // optional -}; -``` - -Alternatively, you can upload a file directly from a file path: -```typescript -const file : Uploadable.FromPath = { - path: "path/to/file", - filename: "my-file", // optional - contentType: "audio/mpeg", // optional - contentLength: 1949, // optional -}; -``` - -The metadata is used to set the `Content-Length`, `Content-Type`, and `Content-Disposition` headers. If not provided, the client will attempt to determine them automatically. -For example, `fs.ReadStream` has a `path` property which the SDK uses to retrieve the file size from the filesystem without loading it into memory. - - ## Advanced ### Additional Headers diff --git a/skyvern-ts/client/package-lock.json b/skyvern-ts/client/package-lock.json index f3de454f5..459514f42 100644 --- a/skyvern-ts/client/package-lock.json +++ b/skyvern-ts/client/package-lock.json @@ -1,12 +1,12 @@ { "name": "@skyvern/client", - "version": "1.0.30", + "version": "1.0.31", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@skyvern/client", - "version": "1.0.30", + "version": "1.0.31", "dependencies": { "playwright": "^1.48.0" }, @@ -1631,9 +1631,9 @@ } }, "node_modules/baseline-browser-mapping": { - "version": "2.10.16", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.16.tgz", - "integrity": "sha512-Lyf3aK28zpsD1yQMiiHD4RvVb6UdMoo8xzG2XzFIfR9luPzOpcBlAsT/qfB1XWS1bxWT+UtE4WmQgsp297FYOA==", + "version": "2.10.19", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.19.tgz", + "integrity": "sha512-qCkNLi2sfBOn8XhZQ0FXsT1Ki/Yo5P90hrkRamVFRS7/KV9hpfA4HkoWNU152+8w0zPjnxo5psx5NL3PSGgv5g==", "dev": true, "license": "Apache-2.0", "bin": { @@ -1708,9 +1708,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001787", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001787.tgz", - "integrity": "sha512-mNcrMN9KeI68u7muanUpEejSLghOKlVhRqS/Za2IeyGllJ9I9otGpR9g3nsw7n4W378TE/LyIteA0+/FOZm4Kg==", + "version": "1.0.30001788", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001788.tgz", + "integrity": "sha512-6q8HFp+lOQtcf7wBK+uEenxymVWkGKkjFpCvw5W25cmMwEDU45p1xQFBQv8JDlMMry7eNxyBaR+qxgmTUZkIRQ==", "dev": true, "funding": [ { @@ -1891,9 +1891,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.333", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.333.tgz", - "integrity": "sha512-skNh4FsE+IpCJV7xAQGbQ4eyOGvcEctVBAk7a5KPzxC3alES9rLrT+2IsPRPgeQr8LVxdJr8BHQ9481+TOr0xg==", + "version": "1.5.336", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.336.tgz", + "integrity": "sha512-AbH9q9J455r/nLmdNZes0G0ZKcRX73FicwowalLs6ijwOmCJSRRrLX63lcAlzy9ux3dWK1w1+1nsBJEWN11hcQ==", "dev": true, "license": "ISC" }, @@ -3082,15 +3082,15 @@ } }, "node_modules/vite-node/node_modules/@types/node": { - "version": "25.5.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-25.5.2.tgz", - "integrity": "sha512-tO4ZIRKNC+MDWV4qKVZe3Ql/woTnmHDr5JD8UI5hn2pwBrHEwOEMZK7WlNb5RKB6EoJ02gwmQS9OrjuFnZYdpg==", + "version": "25.6.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-25.6.0.tgz", + "integrity": "sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ==", "dev": true, "license": "MIT", "optional": true, "peer": true, "dependencies": { - "undici-types": "~7.18.0" + "undici-types": "~7.19.0" } }, "node_modules/vite-node/node_modules/fdir": { @@ -3140,9 +3140,9 @@ } }, "node_modules/vite-node/node_modules/undici-types": { - "version": "7.18.2", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz", - "integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==", + "version": "7.19.2", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.19.2.tgz", + "integrity": "sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg==", "dev": true, "license": "MIT", "optional": true, @@ -3459,9 +3459,9 @@ } }, "node_modules/webpack": { - "version": "5.105.4", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.105.4.tgz", - "integrity": "sha512-jTywjboN9aHxFlToqb0K0Zs9SbBoW4zRUlGzI2tYNxVYcEi/IPpn+Xi4ye5jTLvX2YeLuic/IvxNot+Q1jMoOw==", + "version": "5.106.1", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.106.1.tgz", + "integrity": "sha512-EW8af29ak8Oaf4T8k8YsajjrDBDYgnKZ5er6ljWFJsXABfTNowQfvHLftwcepVgdz+IoLSdEAbBiM9DFXoll9w==", "dev": true, "license": "MIT", "dependencies": { diff --git a/skyvern-ts/client/package.json b/skyvern-ts/client/package.json index c1005fccd..f885b381d 100644 --- a/skyvern-ts/client/package.json +++ b/skyvern-ts/client/package.json @@ -1,6 +1,6 @@ { "name": "@skyvern/client", - "version": "1.0.30", + "version": "1.0.31", "private": false, "repository": { "type": "git", diff --git a/skyvern-ts/client/reference.md b/skyvern-ts/client/reference.md index 0045fd618..34e2444fe 100644 --- a/skyvern-ts/client/reference.md +++ b/skyvern-ts/client/reference.md @@ -192,6 +192,466 @@ await client.scripts.runScript("s_abc123"); + + + + +## Schedules +
client.schedules.listAll({ ...params }) -> Skyvern.OrganizationScheduleListResponse +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```typescript +await client.schedules.listAll({ + page: 1, + page_size: 1, + status: "active", + search: "search" +}); + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**request:** `Skyvern.SchedulesListAllRequest` + +
+
+ +
+
+ +**requestOptions:** `Schedules.RequestOptions` + +
+
+
+
+ + +
+
+
+ +
client.schedules.list(workflowPermanentId) -> Skyvern.WorkflowScheduleListResponse +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```typescript +await client.schedules.list("workflow_permanent_id"); + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**workflowPermanentId:** `string` + +
+
+ +
+
+ +**requestOptions:** `Schedules.RequestOptions` + +
+
+
+
+ + +
+
+
+ +
client.schedules.create(workflowPermanentId, { ...params }) -> Skyvern.WorkflowScheduleResponse +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```typescript +await client.schedules.create("workflow_permanent_id", { + cron_expression: "cron_expression", + timezone: "timezone" +}); + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**workflowPermanentId:** `string` + +
+
+ +
+
+ +**request:** `Skyvern.WorkflowScheduleUpsertRequest` + +
+
+ +
+
+ +**requestOptions:** `Schedules.RequestOptions` + +
+
+
+
+ + +
+
+
+ +
client.schedules.get(workflowPermanentId, workflowScheduleId) -> Skyvern.WorkflowScheduleResponse +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```typescript +await client.schedules.get("workflow_permanent_id", "workflow_schedule_id"); + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**workflowPermanentId:** `string` + +
+
+ +
+
+ +**workflowScheduleId:** `string` + +
+
+ +
+
+ +**requestOptions:** `Schedules.RequestOptions` + +
+
+
+
+ + +
+
+
+ +
client.schedules.update(workflowPermanentId, workflowScheduleId, { ...params }) -> Skyvern.WorkflowScheduleResponse +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```typescript +await client.schedules.update("workflow_permanent_id", "workflow_schedule_id", { + cron_expression: "cron_expression", + timezone: "timezone" +}); + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**workflowPermanentId:** `string` + +
+
+ +
+
+ +**workflowScheduleId:** `string` + +
+
+ +
+
+ +**request:** `Skyvern.WorkflowScheduleUpsertRequest` + +
+
+ +
+
+ +**requestOptions:** `Schedules.RequestOptions` + +
+
+
+
+ + +
+
+
+ +
client.schedules.delete(workflowPermanentId, workflowScheduleId) -> Skyvern.DeleteScheduleResponse +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```typescript +await client.schedules.delete("workflow_permanent_id", "workflow_schedule_id"); + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**workflowPermanentId:** `string` + +
+
+ +
+
+ +**workflowScheduleId:** `string` + +
+
+ +
+
+ +**requestOptions:** `Schedules.RequestOptions` + +
+
+
+
+ + +
+
+
+ +
client.schedules.enable(workflowPermanentId, workflowScheduleId) -> Skyvern.WorkflowScheduleResponse +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```typescript +await client.schedules.enable("workflow_permanent_id", "workflow_schedule_id"); + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**workflowPermanentId:** `string` + +
+
+ +
+
+ +**workflowScheduleId:** `string` + +
+
+ +
+
+ +**requestOptions:** `Schedules.RequestOptions` + +
+
+
+
+ + +
+
+
+ +
client.schedules.disable(workflowPermanentId, workflowScheduleId) -> Skyvern.WorkflowScheduleResponse +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```typescript +await client.schedules.disable("workflow_permanent_id", "workflow_schedule_id"); + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**workflowPermanentId:** `string` + +
+
+ +
+
+ +**workflowScheduleId:** `string` + +
+
+ +
+
+ +**requestOptions:** `Schedules.RequestOptions` + +
+
+
+
+ +
diff --git a/skyvern-ts/client/src/Client.ts b/skyvern-ts/client/src/Client.ts index 72e79a368..15b759228 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 { Artifacts } from "./api/resources/artifacts/client/Client.js"; +import { Schedules } from "./api/resources/schedules/client/Client.js"; import { Scripts } from "./api/resources/scripts/client/Client.js"; import type { BaseClientOptions, BaseRequestOptions } from "./BaseClient.js"; import { mergeHeaders, mergeOnlyDefinedHeaders } from "./core/headers.js"; @@ -19,6 +20,7 @@ export class SkyvernClient { protected readonly _options: SkyvernClient.Options; protected _artifacts: Artifacts | undefined; protected _scripts: Scripts | undefined; + protected _schedules: Schedules | undefined; constructor(_options: SkyvernClient.Options = {}) { this._options = { @@ -28,8 +30,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.30", - "User-Agent": "@skyvern/client/1.0.30", + "X-Fern-SDK-Version": "1.0.31", + "User-Agent": "@skyvern/client/1.0.31", "X-Fern-Runtime": core.RUNTIME.type, "X-Fern-Runtime-Version": core.RUNTIME.version, }, @@ -46,6 +48,10 @@ export class SkyvernClient { return (this._scripts ??= new Scripts(this._options)); } + public get schedules(): Schedules { + return (this._schedules ??= new Schedules(this._options)); + } + /** * Run a task * @@ -1970,7 +1976,7 @@ export class SkyvernClient { * @example * import { createReadStream } from "fs"; * await client.uploadFile({ - * file: fs.createReadStream("/path/to/your/file") + * file: "file" * }) */ public uploadFile( @@ -1985,7 +1991,7 @@ export class SkyvernClient { requestOptions?: SkyvernClient.RequestOptions, ): Promise> { const _request = await core.newFormData(); - await _request.appendFile("file", request.file); + _request.append("file", request.file); const _maybeEncodedRequest = await _request.getRequest(); const _headers: core.Fetcher.Args["headers"] = mergeHeaders( this._options?.headers, diff --git a/skyvern-ts/client/src/api/client/requests/BodyUploadFileV1UploadFilePost.ts b/skyvern-ts/client/src/api/client/requests/BodyUploadFileV1UploadFilePost.ts index 8264af6cd..94fb1858b 100644 --- a/skyvern-ts/client/src/api/client/requests/BodyUploadFileV1UploadFilePost.ts +++ b/skyvern-ts/client/src/api/client/requests/BodyUploadFileV1UploadFilePost.ts @@ -1,13 +1,11 @@ // This file was auto-generated by Fern from our API Definition. -import type * as core from "../../../core/index.js"; - /** * @example * { - * file: fs.createReadStream("/path/to/your/file") + * file: "file" * } */ export interface BodyUploadFileV1UploadFilePost { - file: core.file.Uploadable; + file: string; } diff --git a/skyvern-ts/client/src/api/resources/index.ts b/skyvern-ts/client/src/api/resources/index.ts index 690b3a9c7..99ec6b700 100644 --- a/skyvern-ts/client/src/api/resources/index.ts +++ b/skyvern-ts/client/src/api/resources/index.ts @@ -1,2 +1,5 @@ export * as artifacts from "./artifacts/index.js"; +export * from "./schedules/client/requests/index.js"; +export * as schedules from "./schedules/index.js"; +export * from "./schedules/types/index.js"; export * as scripts from "./scripts/index.js"; diff --git a/skyvern-ts/client/src/api/resources/schedules/client/Client.ts b/skyvern-ts/client/src/api/resources/schedules/client/Client.ts new file mode 100644 index 000000000..1a4448697 --- /dev/null +++ b/skyvern-ts/client/src/api/resources/schedules/client/Client.ts @@ -0,0 +1,689 @@ +// 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 Schedules { + export interface Options extends BaseClientOptions {} + + export interface RequestOptions extends BaseRequestOptions {} +} + +export class Schedules { + protected readonly _options: Schedules.Options; + + constructor(_options: Schedules.Options = {}) { + this._options = _options; + } + + /** + * @param {Skyvern.SchedulesListAllRequest} request + * @param {Schedules.RequestOptions} requestOptions - Request-specific configuration. + * + * @throws {@link Skyvern.UnprocessableEntityError} + * + * @example + * await client.schedules.listAll({ + * page: 1, + * page_size: 1, + * status: "active", + * search: "search" + * }) + */ + public listAll( + request: Skyvern.SchedulesListAllRequest = {}, + requestOptions?: Schedules.RequestOptions, + ): core.HttpResponsePromise { + return core.HttpResponsePromise.fromPromise(this.__listAll(request, requestOptions)); + } + + private async __listAll( + request: Skyvern.SchedulesListAllRequest = {}, + requestOptions?: Schedules.RequestOptions, + ): Promise> { + const { page, page_size: pageSize, status, search } = request; + const _queryParams: Record = {}; + if (page != null) { + _queryParams.page = page.toString(); + } + + if (pageSize != null) { + _queryParams.page_size = pageSize.toString(); + } + + if (status != null) { + _queryParams.status = status; + } + + 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/schedules", + ), + 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.OrganizationScheduleListResponse, + 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/schedules."); + case "unknown": + throw new errors.SkyvernError({ + message: _response.error.errorMessage, + rawResponse: _response.rawResponse, + }); + } + } + + /** + * @param {string} workflowPermanentId + * @param {Schedules.RequestOptions} requestOptions - Request-specific configuration. + * + * @throws {@link Skyvern.UnprocessableEntityError} + * + * @example + * await client.schedules.list("workflow_permanent_id") + */ + public list( + workflowPermanentId: string, + requestOptions?: Schedules.RequestOptions, + ): core.HttpResponsePromise { + return core.HttpResponsePromise.fromPromise(this.__list(workflowPermanentId, requestOptions)); + } + + private async __list( + workflowPermanentId: string, + requestOptions?: Schedules.RequestOptions, + ): Promise> { + 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)}/schedules`, + ), + 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.WorkflowScheduleListResponse, 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/workflows/{workflow_permanent_id}/schedules.", + ); + case "unknown": + throw new errors.SkyvernError({ + message: _response.error.errorMessage, + rawResponse: _response.rawResponse, + }); + } + } + + /** + * @param {string} workflowPermanentId + * @param {Skyvern.WorkflowScheduleUpsertRequest} request + * @param {Schedules.RequestOptions} requestOptions - Request-specific configuration. + * + * @throws {@link Skyvern.UnprocessableEntityError} + * + * @example + * await client.schedules.create("workflow_permanent_id", { + * cron_expression: "cron_expression", + * timezone: "timezone" + * }) + */ + public create( + workflowPermanentId: string, + request: Skyvern.WorkflowScheduleUpsertRequest, + requestOptions?: Schedules.RequestOptions, + ): core.HttpResponsePromise { + return core.HttpResponsePromise.fromPromise(this.__create(workflowPermanentId, request, requestOptions)); + } + + private async __create( + workflowPermanentId: string, + request: Skyvern.WorkflowScheduleUpsertRequest, + requestOptions?: Schedules.RequestOptions, + ): Promise> { + 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)}/schedules`, + ), + 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.WorkflowScheduleResponse, rawResponse: _response.rawResponse }; + } + + if (_response.error.reason === "status-code") { + switch (_response.error.statusCode) { + case 422: + throw new Skyvern.UnprocessableEntityError(_response.error.body as unknown, _response.rawResponse); + default: + throw new errors.SkyvernError({ + statusCode: _response.error.statusCode, + body: _response.error.body, + rawResponse: _response.rawResponse, + }); + } + } + + switch (_response.error.reason) { + case "non-json": + throw new errors.SkyvernError({ + statusCode: _response.error.statusCode, + body: _response.error.rawBody, + rawResponse: _response.rawResponse, + }); + case "timeout": + throw new errors.SkyvernTimeoutError( + "Timeout exceeded when calling POST /v1/workflows/{workflow_permanent_id}/schedules.", + ); + case "unknown": + throw new errors.SkyvernError({ + message: _response.error.errorMessage, + rawResponse: _response.rawResponse, + }); + } + } + + /** + * @param {string} workflowPermanentId + * @param {string} workflowScheduleId + * @param {Schedules.RequestOptions} requestOptions - Request-specific configuration. + * + * @throws {@link Skyvern.UnprocessableEntityError} + * + * @example + * await client.schedules.get("workflow_permanent_id", "workflow_schedule_id") + */ + public get( + workflowPermanentId: string, + workflowScheduleId: string, + requestOptions?: Schedules.RequestOptions, + ): core.HttpResponsePromise { + return core.HttpResponsePromise.fromPromise( + this.__get(workflowPermanentId, workflowScheduleId, requestOptions), + ); + } + + private async __get( + workflowPermanentId: string, + workflowScheduleId: string, + requestOptions?: Schedules.RequestOptions, + ): Promise> { + 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)}/schedules/${core.url.encodePathParam(workflowScheduleId)}`, + ), + 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.WorkflowScheduleResponse, 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/workflows/{workflow_permanent_id}/schedules/{workflow_schedule_id}.", + ); + case "unknown": + throw new errors.SkyvernError({ + message: _response.error.errorMessage, + rawResponse: _response.rawResponse, + }); + } + } + + /** + * @param {string} workflowPermanentId + * @param {string} workflowScheduleId + * @param {Skyvern.WorkflowScheduleUpsertRequest} request + * @param {Schedules.RequestOptions} requestOptions - Request-specific configuration. + * + * @throws {@link Skyvern.UnprocessableEntityError} + * + * @example + * await client.schedules.update("workflow_permanent_id", "workflow_schedule_id", { + * cron_expression: "cron_expression", + * timezone: "timezone" + * }) + */ + public update( + workflowPermanentId: string, + workflowScheduleId: string, + request: Skyvern.WorkflowScheduleUpsertRequest, + requestOptions?: Schedules.RequestOptions, + ): core.HttpResponsePromise { + return core.HttpResponsePromise.fromPromise( + this.__update(workflowPermanentId, workflowScheduleId, request, requestOptions), + ); + } + + private async __update( + workflowPermanentId: string, + workflowScheduleId: string, + request: Skyvern.WorkflowScheduleUpsertRequest, + requestOptions?: Schedules.RequestOptions, + ): Promise> { + 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)}/schedules/${core.url.encodePathParam(workflowScheduleId)}`, + ), + 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.WorkflowScheduleResponse, 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}/schedules/{workflow_schedule_id}.", + ); + case "unknown": + throw new errors.SkyvernError({ + message: _response.error.errorMessage, + rawResponse: _response.rawResponse, + }); + } + } + + /** + * @param {string} workflowPermanentId + * @param {string} workflowScheduleId + * @param {Schedules.RequestOptions} requestOptions - Request-specific configuration. + * + * @throws {@link Skyvern.UnprocessableEntityError} + * + * @example + * await client.schedules.delete("workflow_permanent_id", "workflow_schedule_id") + */ + public delete( + workflowPermanentId: string, + workflowScheduleId: string, + requestOptions?: Schedules.RequestOptions, + ): core.HttpResponsePromise { + return core.HttpResponsePromise.fromPromise( + this.__delete(workflowPermanentId, workflowScheduleId, requestOptions), + ); + } + + private async __delete( + workflowPermanentId: string, + workflowScheduleId: string, + requestOptions?: Schedules.RequestOptions, + ): Promise> { + 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)}/schedules/${core.url.encodePathParam(workflowScheduleId)}`, + ), + method: "DELETE", + 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.DeleteScheduleResponse, 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 DELETE /v1/workflows/{workflow_permanent_id}/schedules/{workflow_schedule_id}.", + ); + case "unknown": + throw new errors.SkyvernError({ + message: _response.error.errorMessage, + rawResponse: _response.rawResponse, + }); + } + } + + /** + * @param {string} workflowPermanentId + * @param {string} workflowScheduleId + * @param {Schedules.RequestOptions} requestOptions - Request-specific configuration. + * + * @throws {@link Skyvern.UnprocessableEntityError} + * + * @example + * await client.schedules.enable("workflow_permanent_id", "workflow_schedule_id") + */ + public enable( + workflowPermanentId: string, + workflowScheduleId: string, + requestOptions?: Schedules.RequestOptions, + ): core.HttpResponsePromise { + return core.HttpResponsePromise.fromPromise( + this.__enable(workflowPermanentId, workflowScheduleId, requestOptions), + ); + } + + private async __enable( + workflowPermanentId: string, + workflowScheduleId: string, + requestOptions?: Schedules.RequestOptions, + ): Promise> { + 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)}/schedules/${core.url.encodePathParam(workflowScheduleId)}/enable`, + ), + method: "POST", + 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.WorkflowScheduleResponse, rawResponse: _response.rawResponse }; + } + + if (_response.error.reason === "status-code") { + switch (_response.error.statusCode) { + case 422: + throw new Skyvern.UnprocessableEntityError(_response.error.body as unknown, _response.rawResponse); + default: + throw new errors.SkyvernError({ + statusCode: _response.error.statusCode, + body: _response.error.body, + rawResponse: _response.rawResponse, + }); + } + } + + switch (_response.error.reason) { + case "non-json": + throw new errors.SkyvernError({ + statusCode: _response.error.statusCode, + body: _response.error.rawBody, + rawResponse: _response.rawResponse, + }); + case "timeout": + throw new errors.SkyvernTimeoutError( + "Timeout exceeded when calling POST /v1/workflows/{workflow_permanent_id}/schedules/{workflow_schedule_id}/enable.", + ); + case "unknown": + throw new errors.SkyvernError({ + message: _response.error.errorMessage, + rawResponse: _response.rawResponse, + }); + } + } + + /** + * @param {string} workflowPermanentId + * @param {string} workflowScheduleId + * @param {Schedules.RequestOptions} requestOptions - Request-specific configuration. + * + * @throws {@link Skyvern.UnprocessableEntityError} + * + * @example + * await client.schedules.disable("workflow_permanent_id", "workflow_schedule_id") + */ + public disable( + workflowPermanentId: string, + workflowScheduleId: string, + requestOptions?: Schedules.RequestOptions, + ): core.HttpResponsePromise { + return core.HttpResponsePromise.fromPromise( + this.__disable(workflowPermanentId, workflowScheduleId, requestOptions), + ); + } + + private async __disable( + workflowPermanentId: string, + workflowScheduleId: string, + requestOptions?: Schedules.RequestOptions, + ): Promise> { + 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)}/schedules/${core.url.encodePathParam(workflowScheduleId)}/disable`, + ), + method: "POST", + 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.WorkflowScheduleResponse, rawResponse: _response.rawResponse }; + } + + if (_response.error.reason === "status-code") { + switch (_response.error.statusCode) { + case 422: + throw new Skyvern.UnprocessableEntityError(_response.error.body as unknown, _response.rawResponse); + default: + throw new errors.SkyvernError({ + statusCode: _response.error.statusCode, + body: _response.error.body, + rawResponse: _response.rawResponse, + }); + } + } + + switch (_response.error.reason) { + case "non-json": + throw new errors.SkyvernError({ + statusCode: _response.error.statusCode, + body: _response.error.rawBody, + rawResponse: _response.rawResponse, + }); + case "timeout": + throw new errors.SkyvernTimeoutError( + "Timeout exceeded when calling POST /v1/workflows/{workflow_permanent_id}/schedules/{workflow_schedule_id}/disable.", + ); + case "unknown": + throw new errors.SkyvernError({ + message: _response.error.errorMessage, + rawResponse: _response.rawResponse, + }); + } + } +} diff --git a/skyvern-ts/client/src/api/resources/schedules/client/index.ts b/skyvern-ts/client/src/api/resources/schedules/client/index.ts new file mode 100644 index 000000000..195f9aa8a --- /dev/null +++ b/skyvern-ts/client/src/api/resources/schedules/client/index.ts @@ -0,0 +1 @@ +export * from "./requests/index.js"; diff --git a/skyvern-ts/client/src/api/resources/schedules/client/requests/SchedulesListAllRequest.ts b/skyvern-ts/client/src/api/resources/schedules/client/requests/SchedulesListAllRequest.ts new file mode 100644 index 000000000..7f4c8417d --- /dev/null +++ b/skyvern-ts/client/src/api/resources/schedules/client/requests/SchedulesListAllRequest.ts @@ -0,0 +1,21 @@ +// This file was auto-generated by Fern from our API Definition. + +import type * as Skyvern from "../../../../index.js"; + +/** + * @example + * { + * page: 1, + * page_size: 1, + * status: "active", + * search: "search" + * } + */ +export interface SchedulesListAllRequest { + page?: number; + page_size?: number; + /** Filter by status: 'active' or 'paused' */ + status?: Skyvern.SchedulesListAllRequestStatus; + /** Search by workflow title or schedule name */ + search?: string; +} diff --git a/skyvern-ts/client/src/api/resources/schedules/client/requests/index.ts b/skyvern-ts/client/src/api/resources/schedules/client/requests/index.ts new file mode 100644 index 000000000..ddb1d45c4 --- /dev/null +++ b/skyvern-ts/client/src/api/resources/schedules/client/requests/index.ts @@ -0,0 +1 @@ +export type { SchedulesListAllRequest } from "./SchedulesListAllRequest.js"; diff --git a/skyvern-ts/client/src/api/resources/schedules/index.ts b/skyvern-ts/client/src/api/resources/schedules/index.ts new file mode 100644 index 000000000..d9adb1af9 --- /dev/null +++ b/skyvern-ts/client/src/api/resources/schedules/index.ts @@ -0,0 +1,2 @@ +export * from "./client/index.js"; +export * from "./types/index.js"; diff --git a/skyvern-ts/client/src/api/resources/schedules/types/SchedulesListAllRequestStatus.ts b/skyvern-ts/client/src/api/resources/schedules/types/SchedulesListAllRequestStatus.ts new file mode 100644 index 000000000..78a3d3e4f --- /dev/null +++ b/skyvern-ts/client/src/api/resources/schedules/types/SchedulesListAllRequestStatus.ts @@ -0,0 +1,8 @@ +// This file was auto-generated by Fern from our API Definition. + +export const SchedulesListAllRequestStatus = { + Active: "active", + Paused: "paused", +} as const; +export type SchedulesListAllRequestStatus = + (typeof SchedulesListAllRequestStatus)[keyof typeof SchedulesListAllRequestStatus]; diff --git a/skyvern-ts/client/src/api/resources/schedules/types/index.ts b/skyvern-ts/client/src/api/resources/schedules/types/index.ts new file mode 100644 index 000000000..585fffdf9 --- /dev/null +++ b/skyvern-ts/client/src/api/resources/schedules/types/index.ts @@ -0,0 +1 @@ +export * from "./SchedulesListAllRequestStatus.js"; diff --git a/skyvern-ts/client/src/api/types/DeleteScheduleResponse.ts b/skyvern-ts/client/src/api/types/DeleteScheduleResponse.ts new file mode 100644 index 000000000..75f6bc40c --- /dev/null +++ b/skyvern-ts/client/src/api/types/DeleteScheduleResponse.ts @@ -0,0 +1,5 @@ +// This file was auto-generated by Fern from our API Definition. + +export interface DeleteScheduleResponse { + ok: boolean; +} diff --git a/skyvern-ts/client/src/api/types/OrganizationScheduleItem.ts b/skyvern-ts/client/src/api/types/OrganizationScheduleItem.ts new file mode 100644 index 000000000..958ddc874 --- /dev/null +++ b/skyvern-ts/client/src/api/types/OrganizationScheduleItem.ts @@ -0,0 +1,25 @@ +// This file was auto-generated by Fern from our API Definition. + +/** + * Compact schedule projection for the org-wide list endpoint. + * + * Intentionally omits `backend_schedule_id` — the list view is for browsing + * schedules in the dashboard, not for managing the underlying execution-backend + * binding. Callers that need the backend id should fetch the individual + * schedule via the per-workflow get endpoint. + */ +export interface OrganizationScheduleItem { + workflow_schedule_id: string; + organization_id: string; + workflow_permanent_id: string; + workflow_title: string; + cron_expression: string; + timezone: string; + enabled: boolean; + parameters?: Record; + name?: string; + description?: string; + next_run?: string; + created_at: string; + modified_at: string; +} diff --git a/skyvern-ts/client/src/api/types/OrganizationScheduleListResponse.ts b/skyvern-ts/client/src/api/types/OrganizationScheduleListResponse.ts new file mode 100644 index 000000000..4312c11e1 --- /dev/null +++ b/skyvern-ts/client/src/api/types/OrganizationScheduleListResponse.ts @@ -0,0 +1,10 @@ +// This file was auto-generated by Fern from our API Definition. + +import type * as Skyvern from "../index.js"; + +export interface OrganizationScheduleListResponse { + schedules: Skyvern.OrganizationScheduleItem[]; + total_count: number; + page: number; + page_size: number; +} diff --git a/skyvern-ts/client/src/api/types/TaskRunRequest.ts b/skyvern-ts/client/src/api/types/TaskRunRequest.ts index 4fb410433..a3bf301f4 100644 --- a/skyvern-ts/client/src/api/types/TaskRunRequest.ts +++ b/skyvern-ts/client/src/api/types/TaskRunRequest.ts @@ -12,7 +12,7 @@ export interface TaskRunRequest { */ url?: string; /** - * The engine that powers the agent task. The default value is `skyvern-2.0`, the latest Skyvern agent that performs pretty well with complex and multi-step tasks. `skyvern-1.0` is good for simple tasks like filling a form, or searching for information on Google. The `openai-cua` engine uses OpenAI's CUA model. The `anthropic-cua` uses Anthropic's Claude Sonnet 3.7 model with the computer use tool. + * The engine that powers the agent task. The default value is `skyvern-1.0`, which is good for simple tasks like filling a form, or searching for information on Google. `skyvern-2.0` is the latest Skyvern agent that performs well with complex and multi-step tasks. The `openai-cua` engine uses OpenAI's CUA model. The `anthropic-cua` uses Anthropic's Claude Sonnet 3.7 model with the computer use tool. */ engine?: Skyvern.RunEngine; /** The title for the task */ diff --git a/skyvern-ts/client/src/api/types/WorkflowSchedule.ts b/skyvern-ts/client/src/api/types/WorkflowSchedule.ts new file mode 100644 index 000000000..7f1beda0e --- /dev/null +++ b/skyvern-ts/client/src/api/types/WorkflowSchedule.ts @@ -0,0 +1,17 @@ +// This file was auto-generated by Fern from our API Definition. + +export interface WorkflowSchedule { + workflow_schedule_id: string; + organization_id: string; + workflow_permanent_id: string; + cron_expression: string; + timezone: string; + enabled: boolean; + parameters?: Record; + temporal_schedule_id?: string; + name?: string; + description?: string; + created_at: string; + modified_at: string; + deleted_at?: string; +} diff --git a/skyvern-ts/client/src/api/types/WorkflowScheduleListResponse.ts b/skyvern-ts/client/src/api/types/WorkflowScheduleListResponse.ts new file mode 100644 index 000000000..b1e2b7aee --- /dev/null +++ b/skyvern-ts/client/src/api/types/WorkflowScheduleListResponse.ts @@ -0,0 +1,7 @@ +// This file was auto-generated by Fern from our API Definition. + +import type * as Skyvern from "../index.js"; + +export interface WorkflowScheduleListResponse { + schedules: Skyvern.WorkflowSchedule[]; +} diff --git a/skyvern-ts/client/src/api/types/WorkflowScheduleResponse.ts b/skyvern-ts/client/src/api/types/WorkflowScheduleResponse.ts new file mode 100644 index 000000000..c06ec9f0e --- /dev/null +++ b/skyvern-ts/client/src/api/types/WorkflowScheduleResponse.ts @@ -0,0 +1,8 @@ +// This file was auto-generated by Fern from our API Definition. + +import type * as Skyvern from "../index.js"; + +export interface WorkflowScheduleResponse { + schedule: Skyvern.WorkflowSchedule; + next_runs?: string[]; +} diff --git a/skyvern-ts/client/src/api/types/WorkflowScheduleUpsertRequest.ts b/skyvern-ts/client/src/api/types/WorkflowScheduleUpsertRequest.ts new file mode 100644 index 000000000..c2081ac6a --- /dev/null +++ b/skyvern-ts/client/src/api/types/WorkflowScheduleUpsertRequest.ts @@ -0,0 +1,10 @@ +// This file was auto-generated by Fern from our API Definition. + +export interface WorkflowScheduleUpsertRequest { + cron_expression: string; + timezone: string; + enabled?: boolean; + parameters?: Record; + name?: string; + description?: string; +} diff --git a/skyvern-ts/client/src/api/types/index.ts b/skyvern-ts/client/src/api/types/index.ts index bfece145d..20050791f 100644 --- a/skyvern-ts/client/src/api/types/index.ts +++ b/skyvern-ts/client/src/api/types/index.ts @@ -43,6 +43,7 @@ export * from "./CredentialResponse.js"; export * from "./CredentialTypeOutput.js"; export * from "./CredentialVaultType.js"; export * from "./CreditCardCredentialResponse.js"; +export * from "./DeleteScheduleResponse.js"; export * from "./DownloadToS3Block.js"; export * from "./DownloadToS3BlockYaml.js"; export * from "./Extensions.js"; @@ -91,6 +92,8 @@ export * from "./NonEmptyCreditCardCredential.js"; export * from "./NonEmptyPasswordCredential.js"; export * from "./OnePasswordCredentialParameter.js"; export * from "./OnePasswordCredentialParameterYaml.js"; +export * from "./OrganizationScheduleItem.js"; +export * from "./OrganizationScheduleListResponse.js"; export * from "./OtpType.js"; export * from "./OutputParameter.js"; export * from "./OutputParameterYaml.js"; @@ -173,6 +176,10 @@ export * from "./WorkflowRunStatus.js"; export * from "./WorkflowRunTimeline.js"; export * from "./WorkflowRunTimelineType.js"; export * from "./WorkflowRunTriggerType.js"; +export * from "./WorkflowSchedule.js"; +export * from "./WorkflowScheduleListResponse.js"; +export * from "./WorkflowScheduleResponse.js"; +export * from "./WorkflowScheduleUpsertRequest.js"; export * from "./WorkflowStatus.js"; export * from "./WorkflowTriggerBlock.js"; export * from "./WorkflowTriggerBlockParametersItem.js"; diff --git a/skyvern-ts/client/src/version.ts b/skyvern-ts/client/src/version.ts index a88c941c5..40b56a960 100644 --- a/skyvern-ts/client/src/version.ts +++ b/skyvern-ts/client/src/version.ts @@ -1 +1 @@ -export const SDK_VERSION = "1.0.30"; +export const SDK_VERSION = "1.0.31"; diff --git a/skyvern-ts/client/tests/wire/schedules.test.ts b/skyvern-ts/client/tests/wire/schedules.test.ts new file mode 100644 index 000000000..4dac0160e --- /dev/null +++ b/skyvern-ts/client/tests/wire/schedules.test.ts @@ -0,0 +1,560 @@ +// 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("Schedules", () => { + test("listAll (1)", async () => { + const server = mockServerPool.createServer(); + const client = new SkyvernClient({ apiKey: "test", environment: server.baseUrl }); + + const rawResponseBody = { + schedules: [ + { + workflow_schedule_id: "workflow_schedule_id", + organization_id: "organization_id", + workflow_permanent_id: "workflow_permanent_id", + workflow_title: "workflow_title", + cron_expression: "cron_expression", + timezone: "timezone", + enabled: true, + parameters: { key: "value" }, + name: "name", + description: "description", + next_run: "2024-01-15T09:30:00Z", + created_at: "2024-01-15T09:30:00Z", + modified_at: "2024-01-15T09:30:00Z", + }, + ], + total_count: 1, + page: 1, + page_size: 1, + }; + server.mockEndpoint().get("/v1/schedules").respondWith().statusCode(200).jsonBody(rawResponseBody).build(); + + const response = await client.schedules.listAll({ + page: 1, + page_size: 1, + status: "active", + search: "search", + }); + expect(response).toEqual({ + schedules: [ + { + workflow_schedule_id: "workflow_schedule_id", + organization_id: "organization_id", + workflow_permanent_id: "workflow_permanent_id", + workflow_title: "workflow_title", + cron_expression: "cron_expression", + timezone: "timezone", + enabled: true, + parameters: { + key: "value", + }, + name: "name", + description: "description", + next_run: "2024-01-15T09:30:00Z", + created_at: "2024-01-15T09:30:00Z", + modified_at: "2024-01-15T09:30:00Z", + }, + ], + total_count: 1, + page: 1, + page_size: 1, + }); + }); + + test("listAll (2)", async () => { + const server = mockServerPool.createServer(); + const client = new SkyvernClient({ apiKey: "test", environment: server.baseUrl }); + + const rawResponseBody = { key: "value" }; + server.mockEndpoint().get("/v1/schedules").respondWith().statusCode(422).jsonBody(rawResponseBody).build(); + + await expect(async () => { + return await client.schedules.listAll(); + }).rejects.toThrow(Skyvern.UnprocessableEntityError); + }); + + test("list (1)", async () => { + const server = mockServerPool.createServer(); + const client = new SkyvernClient({ apiKey: "test", environment: server.baseUrl }); + + const rawResponseBody = { + schedules: [ + { + workflow_schedule_id: "workflow_schedule_id", + organization_id: "organization_id", + workflow_permanent_id: "workflow_permanent_id", + cron_expression: "cron_expression", + timezone: "timezone", + enabled: true, + parameters: { key: "value" }, + temporal_schedule_id: "temporal_schedule_id", + name: "name", + description: "description", + created_at: "2024-01-15T09:30:00Z", + modified_at: "2024-01-15T09:30:00Z", + deleted_at: "2024-01-15T09:30:00Z", + }, + ], + }; + server + .mockEndpoint() + .get("/v1/workflows/workflow_permanent_id/schedules") + .respondWith() + .statusCode(200) + .jsonBody(rawResponseBody) + .build(); + + const response = await client.schedules.list("workflow_permanent_id"); + expect(response).toEqual({ + schedules: [ + { + workflow_schedule_id: "workflow_schedule_id", + organization_id: "organization_id", + workflow_permanent_id: "workflow_permanent_id", + cron_expression: "cron_expression", + timezone: "timezone", + enabled: true, + parameters: { + key: "value", + }, + temporal_schedule_id: "temporal_schedule_id", + name: "name", + description: "description", + created_at: "2024-01-15T09:30:00Z", + modified_at: "2024-01-15T09:30:00Z", + deleted_at: "2024-01-15T09:30:00Z", + }, + ], + }); + }); + + test("list (2)", async () => { + const server = mockServerPool.createServer(); + const client = new SkyvernClient({ apiKey: "test", environment: server.baseUrl }); + + const rawResponseBody = { key: "value" }; + server + .mockEndpoint() + .get("/v1/workflows/workflow_permanent_id/schedules") + .respondWith() + .statusCode(422) + .jsonBody(rawResponseBody) + .build(); + + await expect(async () => { + return await client.schedules.list("workflow_permanent_id"); + }).rejects.toThrow(Skyvern.UnprocessableEntityError); + }); + + test("create (1)", async () => { + const server = mockServerPool.createServer(); + const client = new SkyvernClient({ apiKey: "test", environment: server.baseUrl }); + const rawRequestBody = { cron_expression: "cron_expression", timezone: "timezone" }; + const rawResponseBody = { + schedule: { + workflow_schedule_id: "workflow_schedule_id", + organization_id: "organization_id", + workflow_permanent_id: "workflow_permanent_id", + cron_expression: "cron_expression", + timezone: "timezone", + enabled: true, + parameters: { key: "value" }, + temporal_schedule_id: "temporal_schedule_id", + name: "name", + description: "description", + created_at: "2024-01-15T09:30:00Z", + modified_at: "2024-01-15T09:30:00Z", + deleted_at: "2024-01-15T09:30:00Z", + }, + next_runs: ["2024-01-15T09:30:00Z"], + }; + server + .mockEndpoint() + .post("/v1/workflows/workflow_permanent_id/schedules") + .jsonBody(rawRequestBody) + .respondWith() + .statusCode(200) + .jsonBody(rawResponseBody) + .build(); + + const response = await client.schedules.create("workflow_permanent_id", { + cron_expression: "cron_expression", + timezone: "timezone", + }); + expect(response).toEqual({ + schedule: { + workflow_schedule_id: "workflow_schedule_id", + organization_id: "organization_id", + workflow_permanent_id: "workflow_permanent_id", + cron_expression: "cron_expression", + timezone: "timezone", + enabled: true, + parameters: { + key: "value", + }, + temporal_schedule_id: "temporal_schedule_id", + name: "name", + description: "description", + created_at: "2024-01-15T09:30:00Z", + modified_at: "2024-01-15T09:30:00Z", + deleted_at: "2024-01-15T09:30:00Z", + }, + next_runs: ["2024-01-15T09:30:00Z"], + }); + }); + + test("create (2)", async () => { + const server = mockServerPool.createServer(); + const client = new SkyvernClient({ apiKey: "test", environment: server.baseUrl }); + const rawRequestBody = { cron_expression: "cron_expression", timezone: "timezone" }; + const rawResponseBody = { key: "value" }; + server + .mockEndpoint() + .post("/v1/workflows/workflow_permanent_id/schedules") + .jsonBody(rawRequestBody) + .respondWith() + .statusCode(422) + .jsonBody(rawResponseBody) + .build(); + + await expect(async () => { + return await client.schedules.create("workflow_permanent_id", { + cron_expression: "cron_expression", + timezone: "timezone", + }); + }).rejects.toThrow(Skyvern.UnprocessableEntityError); + }); + + test("get (1)", async () => { + const server = mockServerPool.createServer(); + const client = new SkyvernClient({ apiKey: "test", environment: server.baseUrl }); + + const rawResponseBody = { + schedule: { + workflow_schedule_id: "workflow_schedule_id", + organization_id: "organization_id", + workflow_permanent_id: "workflow_permanent_id", + cron_expression: "cron_expression", + timezone: "timezone", + enabled: true, + parameters: { key: "value" }, + temporal_schedule_id: "temporal_schedule_id", + name: "name", + description: "description", + created_at: "2024-01-15T09:30:00Z", + modified_at: "2024-01-15T09:30:00Z", + deleted_at: "2024-01-15T09:30:00Z", + }, + next_runs: ["2024-01-15T09:30:00Z"], + }; + server + .mockEndpoint() + .get("/v1/workflows/workflow_permanent_id/schedules/workflow_schedule_id") + .respondWith() + .statusCode(200) + .jsonBody(rawResponseBody) + .build(); + + const response = await client.schedules.get("workflow_permanent_id", "workflow_schedule_id"); + expect(response).toEqual({ + schedule: { + workflow_schedule_id: "workflow_schedule_id", + organization_id: "organization_id", + workflow_permanent_id: "workflow_permanent_id", + cron_expression: "cron_expression", + timezone: "timezone", + enabled: true, + parameters: { + key: "value", + }, + temporal_schedule_id: "temporal_schedule_id", + name: "name", + description: "description", + created_at: "2024-01-15T09:30:00Z", + modified_at: "2024-01-15T09:30:00Z", + deleted_at: "2024-01-15T09:30:00Z", + }, + next_runs: ["2024-01-15T09:30:00Z"], + }); + }); + + test("get (2)", async () => { + const server = mockServerPool.createServer(); + const client = new SkyvernClient({ apiKey: "test", environment: server.baseUrl }); + + const rawResponseBody = { key: "value" }; + server + .mockEndpoint() + .get("/v1/workflows/workflow_permanent_id/schedules/workflow_schedule_id") + .respondWith() + .statusCode(422) + .jsonBody(rawResponseBody) + .build(); + + await expect(async () => { + return await client.schedules.get("workflow_permanent_id", "workflow_schedule_id"); + }).rejects.toThrow(Skyvern.UnprocessableEntityError); + }); + + test("update (1)", async () => { + const server = mockServerPool.createServer(); + const client = new SkyvernClient({ apiKey: "test", environment: server.baseUrl }); + const rawRequestBody = { cron_expression: "cron_expression", timezone: "timezone" }; + const rawResponseBody = { + schedule: { + workflow_schedule_id: "workflow_schedule_id", + organization_id: "organization_id", + workflow_permanent_id: "workflow_permanent_id", + cron_expression: "cron_expression", + timezone: "timezone", + enabled: true, + parameters: { key: "value" }, + temporal_schedule_id: "temporal_schedule_id", + name: "name", + description: "description", + created_at: "2024-01-15T09:30:00Z", + modified_at: "2024-01-15T09:30:00Z", + deleted_at: "2024-01-15T09:30:00Z", + }, + next_runs: ["2024-01-15T09:30:00Z"], + }; + server + .mockEndpoint() + .put("/v1/workflows/workflow_permanent_id/schedules/workflow_schedule_id") + .jsonBody(rawRequestBody) + .respondWith() + .statusCode(200) + .jsonBody(rawResponseBody) + .build(); + + const response = await client.schedules.update("workflow_permanent_id", "workflow_schedule_id", { + cron_expression: "cron_expression", + timezone: "timezone", + }); + expect(response).toEqual({ + schedule: { + workflow_schedule_id: "workflow_schedule_id", + organization_id: "organization_id", + workflow_permanent_id: "workflow_permanent_id", + cron_expression: "cron_expression", + timezone: "timezone", + enabled: true, + parameters: { + key: "value", + }, + temporal_schedule_id: "temporal_schedule_id", + name: "name", + description: "description", + created_at: "2024-01-15T09:30:00Z", + modified_at: "2024-01-15T09:30:00Z", + deleted_at: "2024-01-15T09:30:00Z", + }, + next_runs: ["2024-01-15T09:30:00Z"], + }); + }); + + test("update (2)", async () => { + const server = mockServerPool.createServer(); + const client = new SkyvernClient({ apiKey: "test", environment: server.baseUrl }); + const rawRequestBody = { cron_expression: "cron_expression", timezone: "timezone" }; + const rawResponseBody = { key: "value" }; + server + .mockEndpoint() + .put("/v1/workflows/workflow_permanent_id/schedules/workflow_schedule_id") + .jsonBody(rawRequestBody) + .respondWith() + .statusCode(422) + .jsonBody(rawResponseBody) + .build(); + + await expect(async () => { + return await client.schedules.update("workflow_permanent_id", "workflow_schedule_id", { + cron_expression: "cron_expression", + timezone: "timezone", + }); + }).rejects.toThrow(Skyvern.UnprocessableEntityError); + }); + + test("delete (1)", async () => { + const server = mockServerPool.createServer(); + const client = new SkyvernClient({ apiKey: "test", environment: server.baseUrl }); + + const rawResponseBody = { ok: true }; + server + .mockEndpoint() + .delete("/v1/workflows/workflow_permanent_id/schedules/workflow_schedule_id") + .respondWith() + .statusCode(200) + .jsonBody(rawResponseBody) + .build(); + + const response = await client.schedules.delete("workflow_permanent_id", "workflow_schedule_id"); + expect(response).toEqual({ + ok: true, + }); + }); + + test("delete (2)", async () => { + const server = mockServerPool.createServer(); + const client = new SkyvernClient({ apiKey: "test", environment: server.baseUrl }); + + const rawResponseBody = { key: "value" }; + server + .mockEndpoint() + .delete("/v1/workflows/workflow_permanent_id/schedules/workflow_schedule_id") + .respondWith() + .statusCode(422) + .jsonBody(rawResponseBody) + .build(); + + await expect(async () => { + return await client.schedules.delete("workflow_permanent_id", "workflow_schedule_id"); + }).rejects.toThrow(Skyvern.UnprocessableEntityError); + }); + + test("enable (1)", async () => { + const server = mockServerPool.createServer(); + const client = new SkyvernClient({ apiKey: "test", environment: server.baseUrl }); + + const rawResponseBody = { + schedule: { + workflow_schedule_id: "workflow_schedule_id", + organization_id: "organization_id", + workflow_permanent_id: "workflow_permanent_id", + cron_expression: "cron_expression", + timezone: "timezone", + enabled: true, + parameters: { key: "value" }, + temporal_schedule_id: "temporal_schedule_id", + name: "name", + description: "description", + created_at: "2024-01-15T09:30:00Z", + modified_at: "2024-01-15T09:30:00Z", + deleted_at: "2024-01-15T09:30:00Z", + }, + next_runs: ["2024-01-15T09:30:00Z"], + }; + server + .mockEndpoint() + .post("/v1/workflows/workflow_permanent_id/schedules/workflow_schedule_id/enable") + .respondWith() + .statusCode(200) + .jsonBody(rawResponseBody) + .build(); + + const response = await client.schedules.enable("workflow_permanent_id", "workflow_schedule_id"); + expect(response).toEqual({ + schedule: { + workflow_schedule_id: "workflow_schedule_id", + organization_id: "organization_id", + workflow_permanent_id: "workflow_permanent_id", + cron_expression: "cron_expression", + timezone: "timezone", + enabled: true, + parameters: { + key: "value", + }, + temporal_schedule_id: "temporal_schedule_id", + name: "name", + description: "description", + created_at: "2024-01-15T09:30:00Z", + modified_at: "2024-01-15T09:30:00Z", + deleted_at: "2024-01-15T09:30:00Z", + }, + next_runs: ["2024-01-15T09:30:00Z"], + }); + }); + + test("enable (2)", async () => { + const server = mockServerPool.createServer(); + const client = new SkyvernClient({ apiKey: "test", environment: server.baseUrl }); + + const rawResponseBody = { key: "value" }; + server + .mockEndpoint() + .post("/v1/workflows/workflow_permanent_id/schedules/workflow_schedule_id/enable") + .respondWith() + .statusCode(422) + .jsonBody(rawResponseBody) + .build(); + + await expect(async () => { + return await client.schedules.enable("workflow_permanent_id", "workflow_schedule_id"); + }).rejects.toThrow(Skyvern.UnprocessableEntityError); + }); + + test("disable (1)", async () => { + const server = mockServerPool.createServer(); + const client = new SkyvernClient({ apiKey: "test", environment: server.baseUrl }); + + const rawResponseBody = { + schedule: { + workflow_schedule_id: "workflow_schedule_id", + organization_id: "organization_id", + workflow_permanent_id: "workflow_permanent_id", + cron_expression: "cron_expression", + timezone: "timezone", + enabled: true, + parameters: { key: "value" }, + temporal_schedule_id: "temporal_schedule_id", + name: "name", + description: "description", + created_at: "2024-01-15T09:30:00Z", + modified_at: "2024-01-15T09:30:00Z", + deleted_at: "2024-01-15T09:30:00Z", + }, + next_runs: ["2024-01-15T09:30:00Z"], + }; + server + .mockEndpoint() + .post("/v1/workflows/workflow_permanent_id/schedules/workflow_schedule_id/disable") + .respondWith() + .statusCode(200) + .jsonBody(rawResponseBody) + .build(); + + const response = await client.schedules.disable("workflow_permanent_id", "workflow_schedule_id"); + expect(response).toEqual({ + schedule: { + workflow_schedule_id: "workflow_schedule_id", + organization_id: "organization_id", + workflow_permanent_id: "workflow_permanent_id", + cron_expression: "cron_expression", + timezone: "timezone", + enabled: true, + parameters: { + key: "value", + }, + temporal_schedule_id: "temporal_schedule_id", + name: "name", + description: "description", + created_at: "2024-01-15T09:30:00Z", + modified_at: "2024-01-15T09:30:00Z", + deleted_at: "2024-01-15T09:30:00Z", + }, + next_runs: ["2024-01-15T09:30:00Z"], + }); + }); + + test("disable (2)", async () => { + const server = mockServerPool.createServer(); + const client = new SkyvernClient({ apiKey: "test", environment: server.baseUrl }); + + const rawResponseBody = { key: "value" }; + server + .mockEndpoint() + .post("/v1/workflows/workflow_permanent_id/schedules/workflow_schedule_id/disable") + .respondWith() + .statusCode(422) + .jsonBody(rawResponseBody) + .build(); + + await expect(async () => { + return await client.schedules.disable("workflow_permanent_id", "workflow_schedule_id"); + }).rejects.toThrow(Skyvern.UnprocessableEntityError); + }); +}); diff --git a/skyvern/client/__init__.py b/skyvern/client/__init__.py index 69cae3beb..5211c3a5d 100644 --- a/skyvern/client/__init__.py +++ b/skyvern/client/__init__.py @@ -94,6 +94,7 @@ if typing.TYPE_CHECKING: CredentialTypeOutput, CredentialVaultType, CreditCardCredentialResponse, + DeleteScheduleResponse, DownloadToS3Block, DownloadToS3BlockYaml, Extensions, @@ -284,6 +285,8 @@ if typing.TYPE_CHECKING: NonEmptyPasswordCredential, OnePasswordCredentialParameter, OnePasswordCredentialParameterYaml, + OrganizationScheduleItem, + OrganizationScheduleListResponse, OtpType, OutputParameter, OutputParameterYaml, @@ -530,6 +533,10 @@ if typing.TYPE_CHECKING: WorkflowRunTimeline, WorkflowRunTimelineType, WorkflowRunTriggerType, + WorkflowSchedule, + WorkflowScheduleListResponse, + WorkflowScheduleResponse, + WorkflowScheduleUpsertRequest, WorkflowStatus, WorkflowTriggerBlock, WorkflowTriggerBlockParametersItem, @@ -547,9 +554,10 @@ if typing.TYPE_CHECKING: WorkflowTriggerBlockYaml, ) from .errors import BadRequestError, ConflictError, ForbiddenError, NotFoundError, UnprocessableEntityError - from . import artifacts, scripts + from . import artifacts, schedules, scripts from .client import AsyncSkyvern, Skyvern from .environment import SkyvernEnvironment + from .schedules import SchedulesListAllRequestStatus from .version import __version__ _dynamic_imports: typing.Dict[str, str] = { "ActAction": ".types", @@ -642,6 +650,7 @@ _dynamic_imports: typing.Dict[str, str] = { "CredentialTypeOutput": ".types", "CredentialVaultType": ".types", "CreditCardCredentialResponse": ".types", + "DeleteScheduleResponse": ".types", "DownloadToS3Block": ".types", "DownloadToS3BlockYaml": ".types", "Extensions": ".types", @@ -834,6 +843,8 @@ _dynamic_imports: typing.Dict[str, str] = { "NotFoundError": ".errors", "OnePasswordCredentialParameter": ".types", "OnePasswordCredentialParameterYaml": ".types", + "OrganizationScheduleItem": ".types", + "OrganizationScheduleListResponse": ".types", "OtpType": ".types", "OutputParameter": ".types", "OutputParameterYaml": ".types", @@ -873,6 +884,7 @@ _dynamic_imports: typing.Dict[str, str] = { "RunSdkActionRequestAction_Validate": ".types", "RunSdkActionResponse": ".types", "RunStatus": ".types", + "SchedulesListAllRequestStatus": ".schedules", "Script": ".types", "ScriptFileCreate": ".types", "ScriptRunResponse": ".types", @@ -1083,6 +1095,10 @@ _dynamic_imports: typing.Dict[str, str] = { "WorkflowRunTimeline": ".types", "WorkflowRunTimelineType": ".types", "WorkflowRunTriggerType": ".types", + "WorkflowSchedule": ".types", + "WorkflowScheduleListResponse": ".types", + "WorkflowScheduleResponse": ".types", + "WorkflowScheduleUpsertRequest": ".types", "WorkflowStatus": ".types", "WorkflowTriggerBlock": ".types", "WorkflowTriggerBlockParametersItem": ".types", @@ -1100,6 +1116,7 @@ _dynamic_imports: typing.Dict[str, str] = { "WorkflowTriggerBlockYaml": ".types", "__version__": ".version", "artifacts": ".artifacts", + "schedules": ".schedules", "scripts": ".scripts", } @@ -1216,6 +1233,7 @@ __all__ = [ "CredentialTypeOutput", "CredentialVaultType", "CreditCardCredentialResponse", + "DeleteScheduleResponse", "DownloadToS3Block", "DownloadToS3BlockYaml", "Extensions", @@ -1408,6 +1426,8 @@ __all__ = [ "NotFoundError", "OnePasswordCredentialParameter", "OnePasswordCredentialParameterYaml", + "OrganizationScheduleItem", + "OrganizationScheduleListResponse", "OtpType", "OutputParameter", "OutputParameterYaml", @@ -1447,6 +1467,7 @@ __all__ = [ "RunSdkActionRequestAction_Validate", "RunSdkActionResponse", "RunStatus", + "SchedulesListAllRequestStatus", "Script", "ScriptFileCreate", "ScriptRunResponse", @@ -1657,6 +1678,10 @@ __all__ = [ "WorkflowRunTimeline", "WorkflowRunTimelineType", "WorkflowRunTriggerType", + "WorkflowSchedule", + "WorkflowScheduleListResponse", + "WorkflowScheduleResponse", + "WorkflowScheduleUpsertRequest", "WorkflowStatus", "WorkflowTriggerBlock", "WorkflowTriggerBlockParametersItem", @@ -1674,5 +1699,6 @@ __all__ = [ "WorkflowTriggerBlockYaml", "__version__", "artifacts", + "schedules", "scripts", ] diff --git a/skyvern/client/client.py b/skyvern/client/client.py index f04e31881..932b311d2 100644 --- a/skyvern/client/client.py +++ b/skyvern/client/client.py @@ -6,7 +6,6 @@ import datetime as dt import typing import httpx -from . import core from .core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from .core.request_options import RequestOptions from .environment import SkyvernEnvironment @@ -51,6 +50,7 @@ from .types.workflow_status import WorkflowStatus if typing.TYPE_CHECKING: from .artifacts.client import ArtifactsClient, AsyncArtifactsClient + from .schedules.client import AsyncSchedulesClient, SchedulesClient from .scripts.client import AsyncScriptsClient, ScriptsClient # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -124,6 +124,7 @@ class Skyvern: self._raw_client = RawSkyvern(client_wrapper=self._client_wrapper) self._artifacts: typing.Optional[ArtifactsClient] = None self._scripts: typing.Optional[ScriptsClient] = None + self._schedules: typing.Optional[SchedulesClient] = None @property def with_raw_response(self) -> RawSkyvern: @@ -178,7 +179,7 @@ class Skyvern: engine : typing.Optional[RunEngine] - The engine that powers the agent task. The default value is `skyvern-2.0`, the latest Skyvern agent that performs pretty well with complex and multi-step tasks. `skyvern-1.0` is good for simple tasks like filling a form, or searching for information on Google. The `openai-cua` engine uses OpenAI's CUA model. The `anthropic-cua` uses Anthropic's Claude Sonnet 3.7 model with the computer use tool. + The engine that powers the agent task. The default value is `skyvern-1.0`, which is good for simple tasks like filling a form, or searching for information on Google. `skyvern-2.0` is the latest Skyvern agent that performs well with complex and multi-step tasks. The `openai-cua` engine uses OpenAI's CUA model. The `anthropic-cua` uses Anthropic's Claude Sonnet 3.7 model with the computer use tool. title : typing.Optional[str] The title for the task @@ -1337,14 +1338,11 @@ class Skyvern: ) return _response.data - def upload_file( - self, *, file: core.File, request_options: typing.Optional[RequestOptions] = None - ) -> UploadFileResponse: + def upload_file(self, *, file: str, request_options: typing.Optional[RequestOptions] = None) -> UploadFileResponse: """ Parameters ---------- - file : core.File - See core.File for more documentation + file : str request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -1361,7 +1359,9 @@ class Skyvern: client = Skyvern( api_key="YOUR_API_KEY", ) - client.upload_file() + client.upload_file( + file="file", + ) """ _response = self._raw_client.upload_file(file=file, request_options=request_options) return _response.data @@ -2492,6 +2492,14 @@ class Skyvern: self._scripts = ScriptsClient(client_wrapper=self._client_wrapper) return self._scripts + @property + def schedules(self): + if self._schedules is None: + from .schedules.client import SchedulesClient # noqa: E402 + + self._schedules = SchedulesClient(client_wrapper=self._client_wrapper) + return self._schedules + class AsyncSkyvern: """ @@ -2561,6 +2569,7 @@ class AsyncSkyvern: self._raw_client = AsyncRawSkyvern(client_wrapper=self._client_wrapper) self._artifacts: typing.Optional[AsyncArtifactsClient] = None self._scripts: typing.Optional[AsyncScriptsClient] = None + self._schedules: typing.Optional[AsyncSchedulesClient] = None @property def with_raw_response(self) -> AsyncRawSkyvern: @@ -2615,7 +2624,7 @@ class AsyncSkyvern: engine : typing.Optional[RunEngine] - The engine that powers the agent task. The default value is `skyvern-2.0`, the latest Skyvern agent that performs pretty well with complex and multi-step tasks. `skyvern-1.0` is good for simple tasks like filling a form, or searching for information on Google. The `openai-cua` engine uses OpenAI's CUA model. The `anthropic-cua` uses Anthropic's Claude Sonnet 3.7 model with the computer use tool. + The engine that powers the agent task. The default value is `skyvern-1.0`, which is good for simple tasks like filling a form, or searching for information on Google. `skyvern-2.0` is the latest Skyvern agent that performs well with complex and multi-step tasks. The `openai-cua` engine uses OpenAI's CUA model. The `anthropic-cua` uses Anthropic's Claude Sonnet 3.7 model with the computer use tool. title : typing.Optional[str] The title for the task @@ -3943,13 +3952,12 @@ class AsyncSkyvern: return _response.data async def upload_file( - self, *, file: core.File, request_options: typing.Optional[RequestOptions] = None + self, *, file: str, request_options: typing.Optional[RequestOptions] = None ) -> UploadFileResponse: """ Parameters ---------- - file : core.File - See core.File for more documentation + file : str request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -3971,7 +3979,9 @@ class AsyncSkyvern: async def main() -> None: - await client.upload_file() + await client.upload_file( + file="file", + ) asyncio.run(main()) @@ -5275,6 +5285,14 @@ class AsyncSkyvern: self._scripts = AsyncScriptsClient(client_wrapper=self._client_wrapper) return self._scripts + @property + def schedules(self): + if self._schedules is None: + from .schedules.client import AsyncSchedulesClient # noqa: E402 + + self._schedules = AsyncSchedulesClient(client_wrapper=self._client_wrapper) + return self._schedules + def _get_base_url(*, base_url: typing.Optional[str] = None, environment: SkyvernEnvironment) -> str: if base_url is not None: diff --git a/skyvern/client/core/client_wrapper.py b/skyvern/client/core/client_wrapper.py index b9b5566d2..222726377 100644 --- a/skyvern/client/core/client_wrapper.py +++ b/skyvern/client/core/client_wrapper.py @@ -22,10 +22,10 @@ class BaseClientWrapper: def get_headers(self) -> typing.Dict[str, str]: headers: typing.Dict[str, str] = { - "User-Agent": "skyvern/1.0.30", + "User-Agent": "skyvern/1.0.31", "X-Fern-Language": "Python", "X-Fern-SDK-Name": "skyvern", - "X-Fern-SDK-Version": "1.0.30", + "X-Fern-SDK-Version": "1.0.31", **(self.get_custom_headers() or {}), } if self._api_key is not None: diff --git a/skyvern/client/raw_client.py b/skyvern/client/raw_client.py index 6c549a9ee..3ad0862cb 100644 --- a/skyvern/client/raw_client.py +++ b/skyvern/client/raw_client.py @@ -4,7 +4,6 @@ import datetime as dt import typing from json.decoder import JSONDecodeError -from . import core from .core.api_error import ApiError from .core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from .core.http_response import AsyncHttpResponse, HttpResponse @@ -105,7 +104,7 @@ class RawSkyvern: engine : typing.Optional[RunEngine] - The engine that powers the agent task. The default value is `skyvern-2.0`, the latest Skyvern agent that performs pretty well with complex and multi-step tasks. `skyvern-1.0` is good for simple tasks like filling a form, or searching for information on Google. The `openai-cua` engine uses OpenAI's CUA model. The `anthropic-cua` uses Anthropic's Claude Sonnet 3.7 model with the computer use tool. + The engine that powers the agent task. The default value is `skyvern-1.0`, which is good for simple tasks like filling a form, or searching for information on Google. `skyvern-2.0` is the latest Skyvern agent that performs well with complex and multi-step tasks. The `openai-cua` engine uses OpenAI's CUA model. The `anthropic-cua` uses Anthropic's Claude Sonnet 3.7 model with the computer use tool. title : typing.Optional[str] The title for the task @@ -1794,13 +1793,12 @@ class RawSkyvern: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def upload_file( - self, *, file: core.File, request_options: typing.Optional[RequestOptions] = None + self, *, file: str, request_options: typing.Optional[RequestOptions] = None ) -> HttpResponse[UploadFileResponse]: """ Parameters ---------- - file : core.File - See core.File for more documentation + file : str request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -1813,10 +1811,10 @@ class RawSkyvern: _response = self._client_wrapper.httpx_client.request( "v1/upload_file", method="POST", - data={}, - files={ + data={ "file": file, }, + files={}, request_options=request_options, omit=OMIT, force_multipart=True, @@ -3510,7 +3508,7 @@ class AsyncRawSkyvern: engine : typing.Optional[RunEngine] - The engine that powers the agent task. The default value is `skyvern-2.0`, the latest Skyvern agent that performs pretty well with complex and multi-step tasks. `skyvern-1.0` is good for simple tasks like filling a form, or searching for information on Google. The `openai-cua` engine uses OpenAI's CUA model. The `anthropic-cua` uses Anthropic's Claude Sonnet 3.7 model with the computer use tool. + The engine that powers the agent task. The default value is `skyvern-1.0`, which is good for simple tasks like filling a form, or searching for information on Google. `skyvern-2.0` is the latest Skyvern agent that performs well with complex and multi-step tasks. The `openai-cua` engine uses OpenAI's CUA model. The `anthropic-cua` uses Anthropic's Claude Sonnet 3.7 model with the computer use tool. title : typing.Optional[str] The title for the task @@ -5199,13 +5197,12 @@ class AsyncRawSkyvern: raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def upload_file( - self, *, file: core.File, request_options: typing.Optional[RequestOptions] = None + self, *, file: str, request_options: typing.Optional[RequestOptions] = None ) -> AsyncHttpResponse[UploadFileResponse]: """ Parameters ---------- - file : core.File - See core.File for more documentation + file : str request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -5218,10 +5215,10 @@ class AsyncRawSkyvern: _response = await self._client_wrapper.httpx_client.request( "v1/upload_file", method="POST", - data={}, - files={ + data={ "file": file, }, + files={}, request_options=request_options, omit=OMIT, force_multipart=True, diff --git a/skyvern/client/schedules/__init__.py b/skyvern/client/schedules/__init__.py new file mode 100644 index 000000000..12978240e --- /dev/null +++ b/skyvern/client/schedules/__init__.py @@ -0,0 +1,34 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + +import typing +from importlib import import_module + +if typing.TYPE_CHECKING: + from .types import SchedulesListAllRequestStatus +_dynamic_imports: typing.Dict[str, str] = {"SchedulesListAllRequestStatus": ".types"} + + +def __getattr__(attr_name: str) -> typing.Any: + module_name = _dynamic_imports.get(attr_name) + if module_name is None: + raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") + try: + module = import_module(module_name, __package__) + if module_name == f".{attr_name}": + return module + else: + return getattr(module, attr_name) + except ImportError as e: + raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e + except AttributeError as e: + raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e + + +def __dir__(): + lazy_attrs = list(_dynamic_imports.keys()) + return sorted(lazy_attrs) + + +__all__ = ["SchedulesListAllRequestStatus"] diff --git a/skyvern/client/schedules/client.py b/skyvern/client/schedules/client.py new file mode 100644 index 000000000..f3ad4a267 --- /dev/null +++ b/skyvern/client/schedules/client.py @@ -0,0 +1,837 @@ +# 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.delete_schedule_response import DeleteScheduleResponse +from ..types.organization_schedule_list_response import OrganizationScheduleListResponse +from ..types.workflow_schedule_list_response import WorkflowScheduleListResponse +from ..types.workflow_schedule_response import WorkflowScheduleResponse +from .raw_client import AsyncRawSchedulesClient, RawSchedulesClient +from .types.schedules_list_all_request_status import SchedulesListAllRequestStatus + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + + +class SchedulesClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._raw_client = RawSchedulesClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> RawSchedulesClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + RawSchedulesClient + """ + return self._raw_client + + def list_all( + self, + *, + page: typing.Optional[int] = None, + page_size: typing.Optional[int] = None, + status: typing.Optional[SchedulesListAllRequestStatus] = None, + search: typing.Optional[str] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> OrganizationScheduleListResponse: + """ + Parameters + ---------- + page : typing.Optional[int] + + page_size : typing.Optional[int] + + status : typing.Optional[SchedulesListAllRequestStatus] + Filter by status: 'active' or 'paused' + + search : typing.Optional[str] + Search by workflow title or schedule name + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + OrganizationScheduleListResponse + Successful Response + + Examples + -------- + from skyvern import Skyvern + + client = Skyvern( + api_key="YOUR_API_KEY", + ) + client.schedules.list_all( + page=1, + page_size=1, + status="active", + search="search", + ) + """ + _response = self._raw_client.list_all( + page=page, page_size=page_size, status=status, search=search, request_options=request_options + ) + return _response.data + + def list( + self, workflow_permanent_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> WorkflowScheduleListResponse: + """ + Parameters + ---------- + workflow_permanent_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + WorkflowScheduleListResponse + Successful Response + + Examples + -------- + from skyvern import Skyvern + + client = Skyvern( + api_key="YOUR_API_KEY", + ) + client.schedules.list( + workflow_permanent_id="workflow_permanent_id", + ) + """ + _response = self._raw_client.list(workflow_permanent_id, request_options=request_options) + return _response.data + + def create( + self, + workflow_permanent_id: str, + *, + cron_expression: str, + timezone: str, + enabled: typing.Optional[bool] = OMIT, + parameters: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT, + name: typing.Optional[str] = OMIT, + description: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> WorkflowScheduleResponse: + """ + Parameters + ---------- + workflow_permanent_id : str + + cron_expression : str + + timezone : str + + enabled : typing.Optional[bool] + + parameters : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] + + name : typing.Optional[str] + + description : typing.Optional[str] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + WorkflowScheduleResponse + Successful Response + + Examples + -------- + from skyvern import Skyvern + + client = Skyvern( + api_key="YOUR_API_KEY", + ) + client.schedules.create( + workflow_permanent_id="workflow_permanent_id", + cron_expression="cron_expression", + timezone="timezone", + ) + """ + _response = self._raw_client.create( + workflow_permanent_id, + cron_expression=cron_expression, + timezone=timezone, + enabled=enabled, + parameters=parameters, + name=name, + description=description, + request_options=request_options, + ) + return _response.data + + def get( + self, + workflow_permanent_id: str, + workflow_schedule_id: str, + *, + request_options: typing.Optional[RequestOptions] = None, + ) -> WorkflowScheduleResponse: + """ + Parameters + ---------- + workflow_permanent_id : str + + workflow_schedule_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + WorkflowScheduleResponse + Successful Response + + Examples + -------- + from skyvern import Skyvern + + client = Skyvern( + api_key="YOUR_API_KEY", + ) + client.schedules.get( + workflow_permanent_id="workflow_permanent_id", + workflow_schedule_id="workflow_schedule_id", + ) + """ + _response = self._raw_client.get(workflow_permanent_id, workflow_schedule_id, request_options=request_options) + return _response.data + + def update( + self, + workflow_permanent_id: str, + workflow_schedule_id: str, + *, + cron_expression: str, + timezone: str, + enabled: typing.Optional[bool] = OMIT, + parameters: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT, + name: typing.Optional[str] = OMIT, + description: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> WorkflowScheduleResponse: + """ + Parameters + ---------- + workflow_permanent_id : str + + workflow_schedule_id : str + + cron_expression : str + + timezone : str + + enabled : typing.Optional[bool] + + parameters : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] + + name : typing.Optional[str] + + description : typing.Optional[str] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + WorkflowScheduleResponse + Successful Response + + Examples + -------- + from skyvern import Skyvern + + client = Skyvern( + api_key="YOUR_API_KEY", + ) + client.schedules.update( + workflow_permanent_id="workflow_permanent_id", + workflow_schedule_id="workflow_schedule_id", + cron_expression="cron_expression", + timezone="timezone", + ) + """ + _response = self._raw_client.update( + workflow_permanent_id, + workflow_schedule_id, + cron_expression=cron_expression, + timezone=timezone, + enabled=enabled, + parameters=parameters, + name=name, + description=description, + request_options=request_options, + ) + return _response.data + + def delete( + self, + workflow_permanent_id: str, + workflow_schedule_id: str, + *, + request_options: typing.Optional[RequestOptions] = None, + ) -> DeleteScheduleResponse: + """ + Parameters + ---------- + workflow_permanent_id : str + + workflow_schedule_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + DeleteScheduleResponse + Successful Response + + Examples + -------- + from skyvern import Skyvern + + client = Skyvern( + api_key="YOUR_API_KEY", + ) + client.schedules.delete( + workflow_permanent_id="workflow_permanent_id", + workflow_schedule_id="workflow_schedule_id", + ) + """ + _response = self._raw_client.delete( + workflow_permanent_id, workflow_schedule_id, request_options=request_options + ) + return _response.data + + def enable( + self, + workflow_permanent_id: str, + workflow_schedule_id: str, + *, + request_options: typing.Optional[RequestOptions] = None, + ) -> WorkflowScheduleResponse: + """ + Parameters + ---------- + workflow_permanent_id : str + + workflow_schedule_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + WorkflowScheduleResponse + Successful Response + + Examples + -------- + from skyvern import Skyvern + + client = Skyvern( + api_key="YOUR_API_KEY", + ) + client.schedules.enable( + workflow_permanent_id="workflow_permanent_id", + workflow_schedule_id="workflow_schedule_id", + ) + """ + _response = self._raw_client.enable( + workflow_permanent_id, workflow_schedule_id, request_options=request_options + ) + return _response.data + + def disable( + self, + workflow_permanent_id: str, + workflow_schedule_id: str, + *, + request_options: typing.Optional[RequestOptions] = None, + ) -> WorkflowScheduleResponse: + """ + Parameters + ---------- + workflow_permanent_id : str + + workflow_schedule_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + WorkflowScheduleResponse + Successful Response + + Examples + -------- + from skyvern import Skyvern + + client = Skyvern( + api_key="YOUR_API_KEY", + ) + client.schedules.disable( + workflow_permanent_id="workflow_permanent_id", + workflow_schedule_id="workflow_schedule_id", + ) + """ + _response = self._raw_client.disable( + workflow_permanent_id, workflow_schedule_id, request_options=request_options + ) + return _response.data + + +class AsyncSchedulesClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._raw_client = AsyncRawSchedulesClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> AsyncRawSchedulesClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + AsyncRawSchedulesClient + """ + return self._raw_client + + async def list_all( + self, + *, + page: typing.Optional[int] = None, + page_size: typing.Optional[int] = None, + status: typing.Optional[SchedulesListAllRequestStatus] = None, + search: typing.Optional[str] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> OrganizationScheduleListResponse: + """ + Parameters + ---------- + page : typing.Optional[int] + + page_size : typing.Optional[int] + + status : typing.Optional[SchedulesListAllRequestStatus] + Filter by status: 'active' or 'paused' + + search : typing.Optional[str] + Search by workflow title or schedule name + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + OrganizationScheduleListResponse + Successful Response + + Examples + -------- + import asyncio + + from skyvern import AsyncSkyvern + + client = AsyncSkyvern( + api_key="YOUR_API_KEY", + ) + + + async def main() -> None: + await client.schedules.list_all( + page=1, + page_size=1, + status="active", + search="search", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.list_all( + page=page, page_size=page_size, status=status, search=search, request_options=request_options + ) + return _response.data + + async def list( + self, workflow_permanent_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> WorkflowScheduleListResponse: + """ + Parameters + ---------- + workflow_permanent_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + WorkflowScheduleListResponse + Successful Response + + Examples + -------- + import asyncio + + from skyvern import AsyncSkyvern + + client = AsyncSkyvern( + api_key="YOUR_API_KEY", + ) + + + async def main() -> None: + await client.schedules.list( + workflow_permanent_id="workflow_permanent_id", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.list(workflow_permanent_id, request_options=request_options) + return _response.data + + async def create( + self, + workflow_permanent_id: str, + *, + cron_expression: str, + timezone: str, + enabled: typing.Optional[bool] = OMIT, + parameters: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT, + name: typing.Optional[str] = OMIT, + description: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> WorkflowScheduleResponse: + """ + Parameters + ---------- + workflow_permanent_id : str + + cron_expression : str + + timezone : str + + enabled : typing.Optional[bool] + + parameters : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] + + name : typing.Optional[str] + + description : typing.Optional[str] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + WorkflowScheduleResponse + Successful Response + + Examples + -------- + import asyncio + + from skyvern import AsyncSkyvern + + client = AsyncSkyvern( + api_key="YOUR_API_KEY", + ) + + + async def main() -> None: + await client.schedules.create( + workflow_permanent_id="workflow_permanent_id", + cron_expression="cron_expression", + timezone="timezone", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.create( + workflow_permanent_id, + cron_expression=cron_expression, + timezone=timezone, + enabled=enabled, + parameters=parameters, + name=name, + description=description, + request_options=request_options, + ) + return _response.data + + async def get( + self, + workflow_permanent_id: str, + workflow_schedule_id: str, + *, + request_options: typing.Optional[RequestOptions] = None, + ) -> WorkflowScheduleResponse: + """ + Parameters + ---------- + workflow_permanent_id : str + + workflow_schedule_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + WorkflowScheduleResponse + Successful Response + + Examples + -------- + import asyncio + + from skyvern import AsyncSkyvern + + client = AsyncSkyvern( + api_key="YOUR_API_KEY", + ) + + + async def main() -> None: + await client.schedules.get( + workflow_permanent_id="workflow_permanent_id", + workflow_schedule_id="workflow_schedule_id", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.get( + workflow_permanent_id, workflow_schedule_id, request_options=request_options + ) + return _response.data + + async def update( + self, + workflow_permanent_id: str, + workflow_schedule_id: str, + *, + cron_expression: str, + timezone: str, + enabled: typing.Optional[bool] = OMIT, + parameters: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT, + name: typing.Optional[str] = OMIT, + description: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> WorkflowScheduleResponse: + """ + Parameters + ---------- + workflow_permanent_id : str + + workflow_schedule_id : str + + cron_expression : str + + timezone : str + + enabled : typing.Optional[bool] + + parameters : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] + + name : typing.Optional[str] + + description : typing.Optional[str] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + WorkflowScheduleResponse + Successful Response + + Examples + -------- + import asyncio + + from skyvern import AsyncSkyvern + + client = AsyncSkyvern( + api_key="YOUR_API_KEY", + ) + + + async def main() -> None: + await client.schedules.update( + workflow_permanent_id="workflow_permanent_id", + workflow_schedule_id="workflow_schedule_id", + cron_expression="cron_expression", + timezone="timezone", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.update( + workflow_permanent_id, + workflow_schedule_id, + cron_expression=cron_expression, + timezone=timezone, + enabled=enabled, + parameters=parameters, + name=name, + description=description, + request_options=request_options, + ) + return _response.data + + async def delete( + self, + workflow_permanent_id: str, + workflow_schedule_id: str, + *, + request_options: typing.Optional[RequestOptions] = None, + ) -> DeleteScheduleResponse: + """ + Parameters + ---------- + workflow_permanent_id : str + + workflow_schedule_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + DeleteScheduleResponse + Successful Response + + Examples + -------- + import asyncio + + from skyvern import AsyncSkyvern + + client = AsyncSkyvern( + api_key="YOUR_API_KEY", + ) + + + async def main() -> None: + await client.schedules.delete( + workflow_permanent_id="workflow_permanent_id", + workflow_schedule_id="workflow_schedule_id", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.delete( + workflow_permanent_id, workflow_schedule_id, request_options=request_options + ) + return _response.data + + async def enable( + self, + workflow_permanent_id: str, + workflow_schedule_id: str, + *, + request_options: typing.Optional[RequestOptions] = None, + ) -> WorkflowScheduleResponse: + """ + Parameters + ---------- + workflow_permanent_id : str + + workflow_schedule_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + WorkflowScheduleResponse + Successful Response + + Examples + -------- + import asyncio + + from skyvern import AsyncSkyvern + + client = AsyncSkyvern( + api_key="YOUR_API_KEY", + ) + + + async def main() -> None: + await client.schedules.enable( + workflow_permanent_id="workflow_permanent_id", + workflow_schedule_id="workflow_schedule_id", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.enable( + workflow_permanent_id, workflow_schedule_id, request_options=request_options + ) + return _response.data + + async def disable( + self, + workflow_permanent_id: str, + workflow_schedule_id: str, + *, + request_options: typing.Optional[RequestOptions] = None, + ) -> WorkflowScheduleResponse: + """ + Parameters + ---------- + workflow_permanent_id : str + + workflow_schedule_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + WorkflowScheduleResponse + Successful Response + + Examples + -------- + import asyncio + + from skyvern import AsyncSkyvern + + client = AsyncSkyvern( + api_key="YOUR_API_KEY", + ) + + + async def main() -> None: + await client.schedules.disable( + workflow_permanent_id="workflow_permanent_id", + workflow_schedule_id="workflow_schedule_id", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.disable( + workflow_permanent_id, workflow_schedule_id, request_options=request_options + ) + return _response.data diff --git a/skyvern/client/schedules/raw_client.py b/skyvern/client/schedules/raw_client.py new file mode 100644 index 000000000..cf9ebfb29 --- /dev/null +++ b/skyvern/client/schedules/raw_client.py @@ -0,0 +1,1008 @@ +# 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 +from ..types.delete_schedule_response import DeleteScheduleResponse +from ..types.organization_schedule_list_response import OrganizationScheduleListResponse +from ..types.workflow_schedule_list_response import WorkflowScheduleListResponse +from ..types.workflow_schedule_response import WorkflowScheduleResponse +from .types.schedules_list_all_request_status import SchedulesListAllRequestStatus + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + + +class RawSchedulesClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def list_all( + self, + *, + page: typing.Optional[int] = None, + page_size: typing.Optional[int] = None, + status: typing.Optional[SchedulesListAllRequestStatus] = None, + search: typing.Optional[str] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[OrganizationScheduleListResponse]: + """ + Parameters + ---------- + page : typing.Optional[int] + + page_size : typing.Optional[int] + + status : typing.Optional[SchedulesListAllRequestStatus] + Filter by status: 'active' or 'paused' + + search : typing.Optional[str] + Search by workflow title or schedule name + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[OrganizationScheduleListResponse] + Successful Response + """ + _response = self._client_wrapper.httpx_client.request( + "v1/schedules", + method="GET", + params={ + "page": page, + "page_size": page_size, + "status": status, + "search": search, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + OrganizationScheduleListResponse, + parse_obj_as( + type_=OrganizationScheduleListResponse, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 422: + raise UnprocessableEntityError( + headers=dict(_response.headers), + body=typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def list( + self, workflow_permanent_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[WorkflowScheduleListResponse]: + """ + Parameters + ---------- + workflow_permanent_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[WorkflowScheduleListResponse] + Successful Response + """ + _response = self._client_wrapper.httpx_client.request( + f"v1/workflows/{jsonable_encoder(workflow_permanent_id)}/schedules", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + WorkflowScheduleListResponse, + parse_obj_as( + type_=WorkflowScheduleListResponse, # 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( + self, + workflow_permanent_id: str, + *, + cron_expression: str, + timezone: str, + enabled: typing.Optional[bool] = OMIT, + parameters: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT, + name: typing.Optional[str] = OMIT, + description: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[WorkflowScheduleResponse]: + """ + Parameters + ---------- + workflow_permanent_id : str + + cron_expression : str + + timezone : str + + enabled : typing.Optional[bool] + + parameters : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] + + name : typing.Optional[str] + + description : typing.Optional[str] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[WorkflowScheduleResponse] + Successful Response + """ + _response = self._client_wrapper.httpx_client.request( + f"v1/workflows/{jsonable_encoder(workflow_permanent_id)}/schedules", + method="POST", + json={ + "cron_expression": cron_expression, + "timezone": timezone, + "enabled": enabled, + "parameters": parameters, + "name": name, + "description": description, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + WorkflowScheduleResponse, + parse_obj_as( + type_=WorkflowScheduleResponse, # 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 get( + self, + workflow_permanent_id: str, + workflow_schedule_id: str, + *, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[WorkflowScheduleResponse]: + """ + Parameters + ---------- + workflow_permanent_id : str + + workflow_schedule_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[WorkflowScheduleResponse] + Successful Response + """ + _response = self._client_wrapper.httpx_client.request( + f"v1/workflows/{jsonable_encoder(workflow_permanent_id)}/schedules/{jsonable_encoder(workflow_schedule_id)}", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + WorkflowScheduleResponse, + parse_obj_as( + type_=WorkflowScheduleResponse, # 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 update( + self, + workflow_permanent_id: str, + workflow_schedule_id: str, + *, + cron_expression: str, + timezone: str, + enabled: typing.Optional[bool] = OMIT, + parameters: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT, + name: typing.Optional[str] = OMIT, + description: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[WorkflowScheduleResponse]: + """ + Parameters + ---------- + workflow_permanent_id : str + + workflow_schedule_id : str + + cron_expression : str + + timezone : str + + enabled : typing.Optional[bool] + + parameters : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] + + name : typing.Optional[str] + + description : typing.Optional[str] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[WorkflowScheduleResponse] + Successful Response + """ + _response = self._client_wrapper.httpx_client.request( + f"v1/workflows/{jsonable_encoder(workflow_permanent_id)}/schedules/{jsonable_encoder(workflow_schedule_id)}", + method="PUT", + json={ + "cron_expression": cron_expression, + "timezone": timezone, + "enabled": enabled, + "parameters": parameters, + "name": name, + "description": description, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + WorkflowScheduleResponse, + parse_obj_as( + type_=WorkflowScheduleResponse, # 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 delete( + self, + workflow_permanent_id: str, + workflow_schedule_id: str, + *, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[DeleteScheduleResponse]: + """ + Parameters + ---------- + workflow_permanent_id : str + + workflow_schedule_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[DeleteScheduleResponse] + Successful Response + """ + _response = self._client_wrapper.httpx_client.request( + f"v1/workflows/{jsonable_encoder(workflow_permanent_id)}/schedules/{jsonable_encoder(workflow_schedule_id)}", + method="DELETE", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + DeleteScheduleResponse, + parse_obj_as( + type_=DeleteScheduleResponse, # 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 enable( + self, + workflow_permanent_id: str, + workflow_schedule_id: str, + *, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[WorkflowScheduleResponse]: + """ + Parameters + ---------- + workflow_permanent_id : str + + workflow_schedule_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[WorkflowScheduleResponse] + Successful Response + """ + _response = self._client_wrapper.httpx_client.request( + f"v1/workflows/{jsonable_encoder(workflow_permanent_id)}/schedules/{jsonable_encoder(workflow_schedule_id)}/enable", + method="POST", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + WorkflowScheduleResponse, + parse_obj_as( + type_=WorkflowScheduleResponse, # 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 disable( + self, + workflow_permanent_id: str, + workflow_schedule_id: str, + *, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[WorkflowScheduleResponse]: + """ + Parameters + ---------- + workflow_permanent_id : str + + workflow_schedule_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[WorkflowScheduleResponse] + Successful Response + """ + _response = self._client_wrapper.httpx_client.request( + f"v1/workflows/{jsonable_encoder(workflow_permanent_id)}/schedules/{jsonable_encoder(workflow_schedule_id)}/disable", + method="POST", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + WorkflowScheduleResponse, + parse_obj_as( + type_=WorkflowScheduleResponse, # 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 AsyncRawSchedulesClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def list_all( + self, + *, + page: typing.Optional[int] = None, + page_size: typing.Optional[int] = None, + status: typing.Optional[SchedulesListAllRequestStatus] = None, + search: typing.Optional[str] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[OrganizationScheduleListResponse]: + """ + Parameters + ---------- + page : typing.Optional[int] + + page_size : typing.Optional[int] + + status : typing.Optional[SchedulesListAllRequestStatus] + Filter by status: 'active' or 'paused' + + search : typing.Optional[str] + Search by workflow title or schedule name + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[OrganizationScheduleListResponse] + Successful Response + """ + _response = await self._client_wrapper.httpx_client.request( + "v1/schedules", + method="GET", + params={ + "page": page, + "page_size": page_size, + "status": status, + "search": search, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + OrganizationScheduleListResponse, + parse_obj_as( + type_=OrganizationScheduleListResponse, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 422: + raise UnprocessableEntityError( + headers=dict(_response.headers), + body=typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def list( + self, workflow_permanent_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[WorkflowScheduleListResponse]: + """ + Parameters + ---------- + workflow_permanent_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[WorkflowScheduleListResponse] + Successful Response + """ + _response = await self._client_wrapper.httpx_client.request( + f"v1/workflows/{jsonable_encoder(workflow_permanent_id)}/schedules", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + WorkflowScheduleListResponse, + parse_obj_as( + type_=WorkflowScheduleListResponse, # 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( + self, + workflow_permanent_id: str, + *, + cron_expression: str, + timezone: str, + enabled: typing.Optional[bool] = OMIT, + parameters: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT, + name: typing.Optional[str] = OMIT, + description: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[WorkflowScheduleResponse]: + """ + Parameters + ---------- + workflow_permanent_id : str + + cron_expression : str + + timezone : str + + enabled : typing.Optional[bool] + + parameters : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] + + name : typing.Optional[str] + + description : typing.Optional[str] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[WorkflowScheduleResponse] + Successful Response + """ + _response = await self._client_wrapper.httpx_client.request( + f"v1/workflows/{jsonable_encoder(workflow_permanent_id)}/schedules", + method="POST", + json={ + "cron_expression": cron_expression, + "timezone": timezone, + "enabled": enabled, + "parameters": parameters, + "name": name, + "description": description, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + WorkflowScheduleResponse, + parse_obj_as( + type_=WorkflowScheduleResponse, # 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 get( + self, + workflow_permanent_id: str, + workflow_schedule_id: str, + *, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[WorkflowScheduleResponse]: + """ + Parameters + ---------- + workflow_permanent_id : str + + workflow_schedule_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[WorkflowScheduleResponse] + Successful Response + """ + _response = await self._client_wrapper.httpx_client.request( + f"v1/workflows/{jsonable_encoder(workflow_permanent_id)}/schedules/{jsonable_encoder(workflow_schedule_id)}", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + WorkflowScheduleResponse, + parse_obj_as( + type_=WorkflowScheduleResponse, # 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 update( + self, + workflow_permanent_id: str, + workflow_schedule_id: str, + *, + cron_expression: str, + timezone: str, + enabled: typing.Optional[bool] = OMIT, + parameters: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT, + name: typing.Optional[str] = OMIT, + description: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[WorkflowScheduleResponse]: + """ + Parameters + ---------- + workflow_permanent_id : str + + workflow_schedule_id : str + + cron_expression : str + + timezone : str + + enabled : typing.Optional[bool] + + parameters : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] + + name : typing.Optional[str] + + description : typing.Optional[str] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[WorkflowScheduleResponse] + Successful Response + """ + _response = await self._client_wrapper.httpx_client.request( + f"v1/workflows/{jsonable_encoder(workflow_permanent_id)}/schedules/{jsonable_encoder(workflow_schedule_id)}", + method="PUT", + json={ + "cron_expression": cron_expression, + "timezone": timezone, + "enabled": enabled, + "parameters": parameters, + "name": name, + "description": description, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + WorkflowScheduleResponse, + parse_obj_as( + type_=WorkflowScheduleResponse, # 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 delete( + self, + workflow_permanent_id: str, + workflow_schedule_id: str, + *, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[DeleteScheduleResponse]: + """ + Parameters + ---------- + workflow_permanent_id : str + + workflow_schedule_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[DeleteScheduleResponse] + Successful Response + """ + _response = await self._client_wrapper.httpx_client.request( + f"v1/workflows/{jsonable_encoder(workflow_permanent_id)}/schedules/{jsonable_encoder(workflow_schedule_id)}", + method="DELETE", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + DeleteScheduleResponse, + parse_obj_as( + type_=DeleteScheduleResponse, # 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 enable( + self, + workflow_permanent_id: str, + workflow_schedule_id: str, + *, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[WorkflowScheduleResponse]: + """ + Parameters + ---------- + workflow_permanent_id : str + + workflow_schedule_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[WorkflowScheduleResponse] + Successful Response + """ + _response = await self._client_wrapper.httpx_client.request( + f"v1/workflows/{jsonable_encoder(workflow_permanent_id)}/schedules/{jsonable_encoder(workflow_schedule_id)}/enable", + method="POST", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + WorkflowScheduleResponse, + parse_obj_as( + type_=WorkflowScheduleResponse, # 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 disable( + self, + workflow_permanent_id: str, + workflow_schedule_id: str, + *, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[WorkflowScheduleResponse]: + """ + Parameters + ---------- + workflow_permanent_id : str + + workflow_schedule_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[WorkflowScheduleResponse] + Successful Response + """ + _response = await self._client_wrapper.httpx_client.request( + f"v1/workflows/{jsonable_encoder(workflow_permanent_id)}/schedules/{jsonable_encoder(workflow_schedule_id)}/disable", + method="POST", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + WorkflowScheduleResponse, + parse_obj_as( + type_=WorkflowScheduleResponse, # 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/client/schedules/types/__init__.py b/skyvern/client/schedules/types/__init__.py new file mode 100644 index 000000000..9e416f0d7 --- /dev/null +++ b/skyvern/client/schedules/types/__init__.py @@ -0,0 +1,34 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + +import typing +from importlib import import_module + +if typing.TYPE_CHECKING: + from .schedules_list_all_request_status import SchedulesListAllRequestStatus +_dynamic_imports: typing.Dict[str, str] = {"SchedulesListAllRequestStatus": ".schedules_list_all_request_status"} + + +def __getattr__(attr_name: str) -> typing.Any: + module_name = _dynamic_imports.get(attr_name) + if module_name is None: + raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") + try: + module = import_module(module_name, __package__) + if module_name == f".{attr_name}": + return module + else: + return getattr(module, attr_name) + except ImportError as e: + raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e + except AttributeError as e: + raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e + + +def __dir__(): + lazy_attrs = list(_dynamic_imports.keys()) + return sorted(lazy_attrs) + + +__all__ = ["SchedulesListAllRequestStatus"] diff --git a/skyvern/client/schedules/types/schedules_list_all_request_status.py b/skyvern/client/schedules/types/schedules_list_all_request_status.py new file mode 100644 index 000000000..dfc27397f --- /dev/null +++ b/skyvern/client/schedules/types/schedules_list_all_request_status.py @@ -0,0 +1,5 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +SchedulesListAllRequestStatus = typing.Union[typing.Literal["active", "paused"], typing.Any] diff --git a/skyvern/client/types/__init__.py b/skyvern/client/types/__init__.py index fa92f0cca..0dcb271c3 100644 --- a/skyvern/client/types/__init__.py +++ b/skyvern/client/types/__init__.py @@ -101,6 +101,7 @@ if typing.TYPE_CHECKING: from .credential_type_output import CredentialTypeOutput from .credential_vault_type import CredentialVaultType from .credit_card_credential_response import CreditCardCredentialResponse + from .delete_schedule_response import DeleteScheduleResponse from .download_to_s3block import DownloadToS3Block from .download_to_s3block_yaml import DownloadToS3BlockYaml from .extensions import Extensions @@ -311,6 +312,8 @@ if typing.TYPE_CHECKING: from .non_empty_password_credential import NonEmptyPasswordCredential from .one_password_credential_parameter import OnePasswordCredentialParameter from .one_password_credential_parameter_yaml import OnePasswordCredentialParameterYaml + from .organization_schedule_item import OrganizationScheduleItem + from .organization_schedule_list_response import OrganizationScheduleListResponse from .otp_type import OtpType from .output_parameter import OutputParameter from .output_parameter_yaml import OutputParameterYaml @@ -579,6 +582,10 @@ if typing.TYPE_CHECKING: from .workflow_run_timeline import WorkflowRunTimeline from .workflow_run_timeline_type import WorkflowRunTimelineType from .workflow_run_trigger_type import WorkflowRunTriggerType + from .workflow_schedule import WorkflowSchedule + from .workflow_schedule_list_response import WorkflowScheduleListResponse + from .workflow_schedule_response import WorkflowScheduleResponse + from .workflow_schedule_upsert_request import WorkflowScheduleUpsertRequest from .workflow_status import WorkflowStatus from .workflow_trigger_block import WorkflowTriggerBlock from .workflow_trigger_block_parameters_item import ( @@ -684,6 +691,7 @@ _dynamic_imports: typing.Dict[str, str] = { "CredentialTypeOutput": ".credential_type_output", "CredentialVaultType": ".credential_vault_type", "CreditCardCredentialResponse": ".credit_card_credential_response", + "DeleteScheduleResponse": ".delete_schedule_response", "DownloadToS3Block": ".download_to_s3block", "DownloadToS3BlockYaml": ".download_to_s3block_yaml", "Extensions": ".extensions", @@ -874,6 +882,8 @@ _dynamic_imports: typing.Dict[str, str] = { "NonEmptyPasswordCredential": ".non_empty_password_credential", "OnePasswordCredentialParameter": ".one_password_credential_parameter", "OnePasswordCredentialParameterYaml": ".one_password_credential_parameter_yaml", + "OrganizationScheduleItem": ".organization_schedule_item", + "OrganizationScheduleListResponse": ".organization_schedule_list_response", "OtpType": ".otp_type", "OutputParameter": ".output_parameter", "OutputParameterYaml": ".output_parameter_yaml", @@ -1120,6 +1130,10 @@ _dynamic_imports: typing.Dict[str, str] = { "WorkflowRunTimeline": ".workflow_run_timeline", "WorkflowRunTimelineType": ".workflow_run_timeline_type", "WorkflowRunTriggerType": ".workflow_run_trigger_type", + "WorkflowSchedule": ".workflow_schedule", + "WorkflowScheduleListResponse": ".workflow_schedule_list_response", + "WorkflowScheduleResponse": ".workflow_schedule_response", + "WorkflowScheduleUpsertRequest": ".workflow_schedule_upsert_request", "WorkflowStatus": ".workflow_status", "WorkflowTriggerBlock": ".workflow_trigger_block", "WorkflowTriggerBlockParametersItem": ".workflow_trigger_block_parameters_item", @@ -1247,6 +1261,7 @@ __all__ = [ "CredentialTypeOutput", "CredentialVaultType", "CreditCardCredentialResponse", + "DeleteScheduleResponse", "DownloadToS3Block", "DownloadToS3BlockYaml", "Extensions", @@ -1437,6 +1452,8 @@ __all__ = [ "NonEmptyPasswordCredential", "OnePasswordCredentialParameter", "OnePasswordCredentialParameterYaml", + "OrganizationScheduleItem", + "OrganizationScheduleListResponse", "OtpType", "OutputParameter", "OutputParameterYaml", @@ -1683,6 +1700,10 @@ __all__ = [ "WorkflowRunTimeline", "WorkflowRunTimelineType", "WorkflowRunTriggerType", + "WorkflowSchedule", + "WorkflowScheduleListResponse", + "WorkflowScheduleResponse", + "WorkflowScheduleUpsertRequest", "WorkflowStatus", "WorkflowTriggerBlock", "WorkflowTriggerBlockParametersItem", diff --git a/skyvern/client/types/delete_schedule_response.py b/skyvern/client/types/delete_schedule_response.py new file mode 100644 index 000000000..f56594901 --- /dev/null +++ b/skyvern/client/types/delete_schedule_response.py @@ -0,0 +1,19 @@ +# 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 DeleteScheduleResponse(UniversalBaseModel): + ok: bool + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/skyvern/client/types/organization_schedule_item.py b/skyvern/client/types/organization_schedule_item.py new file mode 100644 index 000000000..d288100ad --- /dev/null +++ b/skyvern/client/types/organization_schedule_item.py @@ -0,0 +1,41 @@ +# 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 OrganizationScheduleItem(UniversalBaseModel): + """ + Compact schedule projection for the org-wide list endpoint. + + Intentionally omits `backend_schedule_id` — the list view is for browsing + schedules in the dashboard, not for managing the underlying execution-backend + binding. Callers that need the backend id should fetch the individual + schedule via the per-workflow get endpoint. + """ + + workflow_schedule_id: str + organization_id: str + workflow_permanent_id: str + workflow_title: str + cron_expression: str + timezone: str + enabled: bool + parameters: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = None + name: typing.Optional[str] = None + description: typing.Optional[str] = None + next_run: typing.Optional[dt.datetime] = None + 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: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/skyvern/client/types/organization_schedule_list_response.py b/skyvern/client/types/organization_schedule_list_response.py new file mode 100644 index 000000000..05f63e739 --- /dev/null +++ b/skyvern/client/types/organization_schedule_list_response.py @@ -0,0 +1,23 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from .organization_schedule_item import OrganizationScheduleItem + + +class OrganizationScheduleListResponse(UniversalBaseModel): + schedules: typing.List[OrganizationScheduleItem] + total_count: int + page: int + page_size: int + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/skyvern/client/types/task_run_request.py b/skyvern/client/types/task_run_request.py index c1ad5d73b..a85b7a910 100644 --- a/skyvern/client/types/task_run_request.py +++ b/skyvern/client/types/task_run_request.py @@ -25,7 +25,7 @@ class TaskRunRequest(UniversalBaseModel): engine: typing.Optional[RunEngine] = pydantic.Field(default=None) """ - The engine that powers the agent task. The default value is `skyvern-2.0`, the latest Skyvern agent that performs pretty well with complex and multi-step tasks. `skyvern-1.0` is good for simple tasks like filling a form, or searching for information on Google. The `openai-cua` engine uses OpenAI's CUA model. The `anthropic-cua` uses Anthropic's Claude Sonnet 3.7 model with the computer use tool. + The engine that powers the agent task. The default value is `skyvern-1.0`, which is good for simple tasks like filling a form, or searching for information on Google. `skyvern-2.0` is the latest Skyvern agent that performs well with complex and multi-step tasks. The `openai-cua` engine uses OpenAI's CUA model. The `anthropic-cua` uses Anthropic's Claude Sonnet 3.7 model with the computer use tool. """ title: typing.Optional[str] = pydantic.Field(default=None) diff --git a/skyvern/client/types/workflow_schedule.py b/skyvern/client/types/workflow_schedule.py new file mode 100644 index 000000000..1f4303095 --- /dev/null +++ b/skyvern/client/types/workflow_schedule.py @@ -0,0 +1,32 @@ +# 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 WorkflowSchedule(UniversalBaseModel): + workflow_schedule_id: str + organization_id: str + workflow_permanent_id: str + cron_expression: str + timezone: str + enabled: bool + parameters: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = None + temporal_schedule_id: typing.Optional[str] = None + name: typing.Optional[str] = None + description: typing.Optional[str] = None + created_at: dt.datetime + modified_at: dt.datetime + deleted_at: typing.Optional[dt.datetime] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/skyvern/client/types/workflow_schedule_list_response.py b/skyvern/client/types/workflow_schedule_list_response.py new file mode 100644 index 000000000..63323b43a --- /dev/null +++ b/skyvern/client/types/workflow_schedule_list_response.py @@ -0,0 +1,20 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from .workflow_schedule import WorkflowSchedule + + +class WorkflowScheduleListResponse(UniversalBaseModel): + schedules: typing.List[WorkflowSchedule] + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/skyvern/client/types/workflow_schedule_response.py b/skyvern/client/types/workflow_schedule_response.py new file mode 100644 index 000000000..87d721066 --- /dev/null +++ b/skyvern/client/types/workflow_schedule_response.py @@ -0,0 +1,22 @@ +# 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 +from .workflow_schedule import WorkflowSchedule + + +class WorkflowScheduleResponse(UniversalBaseModel): + schedule: WorkflowSchedule + next_runs: typing.Optional[typing.List[dt.datetime]] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/skyvern/client/types/workflow_schedule_upsert_request.py b/skyvern/client/types/workflow_schedule_upsert_request.py new file mode 100644 index 000000000..72bbdece7 --- /dev/null +++ b/skyvern/client/types/workflow_schedule_upsert_request.py @@ -0,0 +1,24 @@ +# 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 WorkflowScheduleUpsertRequest(UniversalBaseModel): + cron_expression: str + timezone: str + enabled: typing.Optional[bool] = None + parameters: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = None + name: typing.Optional[str] = None + description: typing.Optional[str] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/uv.lock b/uv.lock index d6b75fb0b..76dd4d32c 100644 --- a/uv.lock +++ b/uv.lock @@ -14,7 +14,7 @@ resolution-markers = [ ] [options] -exclude-newer = "2026-04-01T23:52:18.918144411Z" +exclude-newer = "2026-04-07T17:49:42.509853Z" exclude-newer-span = "P7D" [manifest] @@ -5523,7 +5523,7 @@ wheels = [ [[package]] name = "skyvern" -version = "1.0.30" +version = "1.0.31" source = { editable = "." } dependencies = [ { name = "aioboto3" },