diff --git a/components/fal_ai/actions/add-request-to-queue/add-request-to-queue.mjs b/components/fal_ai/actions/add-request-to-queue/add-request-to-queue.mjs new file mode 100644 index 0000000000000..4e7370c783b83 --- /dev/null +++ b/components/fal_ai/actions/add-request-to-queue/add-request-to-queue.mjs @@ -0,0 +1,124 @@ +import app from "../../fal_ai.app.mjs"; + +export default { + key: "fal_ai-add-request-to-queue", + name: "Add Request to Queue", + description: "Adds a request to the queue for asynchronous processing, including specifying a webhook URL for receiving updates. [See the documentation](https://fal.ai/docs/model-endpoints/queue#queue-endpoints).", + version: "0.0.1", + type: "action", + props: { + app, + appId: { + propDefinition: [ + app, + "appId", + ], + }, + data: { + type: "object", + label: "Data", + description: "Additional data to include with the request. [See the documentation](https://fal.ai/models/fal-ai/lora/api#schema-input) for more input fields.", + default: { + model_name: "stabilityai/stable-diffusion-xl-base-1.0", + prompt: "Photo of a european medieval 40 year old queen, silver hair, highly detailed face, detailed eyes, head shot, intricate crown, age spots, wrinkles", + }, + }, + reRunEnabled: { + type: "boolean", + label: "Rerun Enabled", + description: "Enable the step to rerun to retrieve the request response. [See the documentation](https://pipedream.com/docs/code/nodejs/rerun/#flowrerun).", + optional: true, + reloadProps: true, + default: false, + }, + }, + additionalProps() { + if (this.reRunEnabled) { + return { + reRunTimeoutInSecs: { + type: "integer", + label: "Rerun Timeout", + description: "The time in seconds to wait before rerunning the step to retrieve the request response. Eg. `30`. [See the documentation](https://pipedream.com/docs/code/nodejs/rerun/#flowrerun).", + optional: true, + min: 10, + }, + }; + } + + return { + falWebhook: { + type: "string", + label: "Webhook URL", + description: "The URL to receive updates via webhook.", + optional: true, + }, + }; + }, + methods: { + addToQueue({ + appId, ...args + } = {}) { + return this.app.post({ + path: `/${appId}`, + ...args, + }); + }, + }, + async run({ $ }) { + const { + context: { + run: { + runs, + callback_request: callbackRequest, + }, + }, + } = $; + + const { + app, + addToQueue, + appId, + data, + falWebhook, + reRunEnabled, + reRunTimeoutInSecs, + } = this; + + if (!reRunEnabled) { + const response = await addToQueue({ + $, + appId, + params: { + fal_webhook: falWebhook, + }, + data, + }); + + $.export("$summary", `Successfully added the request to the queue with ID \`${response.request_id}\`.`); + return response; + } + + if (runs === 1) { + const timeout = 1000 * (reRunTimeoutInSecs || 10); + const { resume_url: resumeUrl } = $.flow.rerun(timeout, null, 1); + + return addToQueue({ + $, + appId, + params: { + fal_webhook: resumeUrl, + }, + data, + }); + } + + const response = await app.getRequestResponse({ + $, + appId, + requestId: callbackRequest.body?.request_id, + }); + + $.export("$summary", "Successfully retrieved the request response."); + return response; + }, +}; diff --git a/components/fal_ai/actions/cancel-request/cancel-request.mjs b/components/fal_ai/actions/cancel-request/cancel-request.mjs new file mode 100644 index 0000000000000..237e56cff93a3 --- /dev/null +++ b/components/fal_ai/actions/cancel-request/cancel-request.mjs @@ -0,0 +1,50 @@ +import app from "../../fal_ai.app.mjs"; + +export default { + key: "fal_ai-cancel-request", + name: "Cancel Request", + description: "Cancels a request in the queue. This allows you to stop a long-running task if it's no longer needed. [See the documentation](https://fal.ai/docs/model-endpoints/queue#queue-endpoints).", + version: "0.0.1", + type: "action", + props: { + app, + appId: { + propDefinition: [ + app, + "appId", + ], + }, + requestId: { + propDefinition: [ + app, + "requestId", + ], + }, + }, + methods: { + cancelRequest({ + appId, requestId, ...args + } = {}) { + return this.app.put({ + path: `/${appId}/requests/${requestId}/cancel`, + ...args, + }); + }, + }, + async run({ $ }) { + const { + cancelRequest, + appId, + requestId, + } = this; + + const response = await cancelRequest({ + $, + appId, + requestId, + }); + + $.export("$summary", "Successfully canceled request."); + return response; + }, +}; diff --git a/components/fal_ai/actions/get-request-response/get-request-response.mjs b/components/fal_ai/actions/get-request-response/get-request-response.mjs new file mode 100644 index 0000000000000..1869e9d5c2c03 --- /dev/null +++ b/components/fal_ai/actions/get-request-response/get-request-response.mjs @@ -0,0 +1,40 @@ +import app from "../../fal_ai.app.mjs"; + +export default { + key: "fal_ai-get-request-response", + name: "Get Request Response", + description: "Gets the response of a completed request in the queue. This retrieves the results of your asynchronous task. [See the documentation](https://fal.ai/docs/model-endpoints/queue#queue-endpoints).", + version: "0.0.1", + type: "action", + props: { + app, + appId: { + propDefinition: [ + app, + "appId", + ], + }, + requestId: { + propDefinition: [ + app, + "requestId", + ], + }, + }, + async run({ $ }) { + const { + app, + appId, + requestId, + } = this; + + const response = await app.getRequestResponse({ + $, + appId, + requestId, + }); + + $.export("$summary", "Successfully retrieved the request response."); + return response; + }, +}; diff --git a/components/fal_ai/actions/get-request-status/get-request-status.mjs b/components/fal_ai/actions/get-request-status/get-request-status.mjs new file mode 100644 index 0000000000000..9a96f44b7c775 --- /dev/null +++ b/components/fal_ai/actions/get-request-status/get-request-status.mjs @@ -0,0 +1,53 @@ +import app from "../../fal_ai.app.mjs"; + +export default { + key: "fal_ai-get-request-status", + name: "Get Request Status", + description: "Gets the status of a request in the queue. This allows you to monitor the progress of your asynchronous tasks. [See the documentation](https://fal.ai/docs/model-endpoints/queue#queue-endpoints).", + version: "0.0.1", + type: "action", + props: { + app, + appId: { + propDefinition: [ + app, + "appId", + ], + }, + requestId: { + propDefinition: [ + app, + "requestId", + ], + }, + logs: { + propDefinition: [ + app, + "logs", + ], + }, + }, + async run({ $ }) { + const { + app, + appId, + requestId, + logs, + } = this; + + const response = await app.getRequestStatus({ + $, + appId, + requestId, + params: { + logs: logs + ? 1 + : undefined, + }, + }); + + $.export("$summary", `Successfully retrieved status as \`${response.status}\`.`); + + return response; + }, +}; diff --git a/components/fal_ai/fal_ai.app.mjs b/components/fal_ai/fal_ai.app.mjs index 51166062647ec..b097f098ed170 100644 --- a/components/fal_ai/fal_ai.app.mjs +++ b/components/fal_ai/fal_ai.app.mjs @@ -1,11 +1,73 @@ +import { axios } from "@pipedream/platform"; + export default { type: "app", app: "fal_ai", - propDefinitions: {}, + propDefinitions: { + appId: { + type: "string", + label: "App ID", + description: "The unique identifier for the app. Eg. `lora`.", + }, + requestId: { + type: "string", + label: "Request ID", + description: "The unique identifier for the request.", + }, + logs: { + type: "boolean", + label: "Enable Logs", + description: "Specify if logs should be enabled for the request status.", + optional: true, + }, + }, methods: { - // this.$auth contains connected account data - authKeys() { - console.log(Object.keys(this.$auth)); + getUrl(path) { + return `https://queue.fal.run/fal-ai${path}`; + }, + getHeaders(headers) { + return { + ...headers, + "Authorization": `Key ${this.$auth.api_key}`, + "Content-Type": "application/json", + }; + }, + _makeRequest({ + $ = this, path, headers, ...args + } = {}) { + return axios($, { + ...args, + url: this.getUrl(path), + headers: this.getHeaders(headers), + }); + }, + post(args = {}) { + return this._makeRequest({ + method: "POST", + ...args, + }); + }, + put(args = {}) { + return this._makeRequest({ + method: "PUT", + ...args, + }); + }, + getRequestStatus({ + appId, requestId, ...args + } = {}) { + return this._makeRequest({ + path: `/${appId}/requests/${requestId}/status`, + ...args, + }); + }, + getRequestResponse({ + appId, requestId, ...args + } = {}) { + return this._makeRequest({ + path: `/${appId}/requests/${requestId}`, + ...args, + }); }, }, }; diff --git a/components/fal_ai/package.json b/components/fal_ai/package.json index 485405507250a..d0a3a59b08d02 100644 --- a/components/fal_ai/package.json +++ b/components/fal_ai/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/fal_ai", - "version": "0.0.1", + "version": "0.1.0", "description": "Pipedream fal.ai Components", "main": "fal_ai.app.mjs", "keywords": [ @@ -11,5 +11,8 @@ "author": "Pipedream (https://pipedream.com/)", "publishConfig": { "access": "public" + }, + "dependencies": { + "@pipedream/platform": "3.0.3" } -} \ No newline at end of file +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index dfc0fe9556e70..09e292c2b37f4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -3361,7 +3361,10 @@ importers: '@pipedream/platform': 3.0.3 components/fal_ai: - specifiers: {} + specifiers: + '@pipedream/platform': 3.0.3 + dependencies: + '@pipedream/platform': 3.0.3 components/faraday: specifiers: