diff --git a/components/twin/actions/browse/browse.mjs b/components/twin/actions/browse/browse.mjs new file mode 100644 index 0000000000000..9f3aab2ad61c3 --- /dev/null +++ b/components/twin/actions/browse/browse.mjs @@ -0,0 +1,70 @@ +import twin from "../../twin.app.mjs"; + +export default { + key: "twin-browse", + name: "Browse", + description: "Browse the internet with an AI web navigation agent that can find information for you. [See the documentation](https://docs.twin.so/api-reference/endpoint/browse)", + version: "0.0.1", + type: "action", + props: { + twin, + startUrl: { + type: "string", + label: "Start URL", + description: "The URL where the browsing task should begin", + }, + goal: { + type: "string", + label: "Goal", + description: "The goal or objective of the browsing task. Example: \"Find the latest price of AAPL stock.\"", + }, + outputType: { + type: "string", + label: "Output Type", + description: "The type of output expected from the task", + options: [ + "string", + "url", + "list[url]", + ], + default: "string", + optional: true, + }, + callbackWithRerun: { + type: "boolean", + label: "Callback With Rerun", + description: "Use the `$.flow.rerun` Node.js helper to rerun the step when the search is completed. This will increase execution time and credit usage as a result. [See the documentation](https://pipedream.com/docs/code/nodejs/rerun/#flow-rerun)", + optional: true, + }, + }, + async run({ $ }) { + let response, completionCallbackUrl; + const { run } = $.context; + if (run.runs === 1) { + if (this.callbackWithRerun) { + ({ resume_url: completionCallbackUrl } = $.flow.rerun(600000, null, 1)); + } + response = await this.twin.browse({ + $, + data: { + startUrl: this.startUrl, + goal: this.goal, + outputType: this.outputType, + completionCallbackUrl, + }, + }); + } + + if (run.callback_request) { + const { task_id: taskId } = run.callback_request.body; + response = await this.twin.getTask({ + taskId, + }); + } + + if (response.status === "COMPLETED") { + $.export("$summary", "Successfully completed browsing"); + } + return response; + }, +}; diff --git a/components/twin/actions/get-task-details/get-task-details.mjs b/components/twin/actions/get-task-details/get-task-details.mjs new file mode 100644 index 0000000000000..4d6ca1db3504c --- /dev/null +++ b/components/twin/actions/get-task-details/get-task-details.mjs @@ -0,0 +1,26 @@ +import twin from "../../twin.app.mjs"; + +export default { + key: "twin-get-task-details", + name: "Get Task Details", + description: "Retrieve details of a specific task. [See the documentation](https://docs.twin.so/api-reference/endpoint/get-task)", + version: "0.0.1", + type: "action", + props: { + twin, + taskId: { + propDefinition: [ + twin, + "taskId", + ], + }, + }, + async run({ $ }) { + const response = await this.twin.getTask({ + $, + taskId: this.taskId, + }); + $.export("$summary", `Successfully retrieved details for task with ID: ${this.taskId}`); + return response; + }, +}; diff --git a/components/twin/package.json b/components/twin/package.json index 892a1f353efe4..8529cbe13f51e 100644 --- a/components/twin/package.json +++ b/components/twin/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/twin", - "version": "0.0.1", + "version": "0.1.0", "description": "Pipedream Twin Components", "main": "twin.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/components/twin/twin.app.mjs b/components/twin/twin.app.mjs index a527eab498981..2b5ee9af7b0a6 100644 --- a/components/twin/twin.app.mjs +++ b/components/twin/twin.app.mjs @@ -1,11 +1,64 @@ +import { axios } from "@pipedream/platform"; + export default { type: "app", app: "twin", - propDefinitions: {}, + propDefinitions: { + taskId: { + type: "string", + label: "Task ID", + description: "Identifier of a task", + async options() { + const tasks = await this.listTasks(); + return tasks?.map(({ + id: value, goal, + }) => ({ + value, + label: `${goal.slice(0, 50)}...`, + })) || []; + }, + }, + }, methods: { - // this.$auth contains connected account data - authKeys() { - console.log(Object.keys(this.$auth)); + _baseUrl() { + return "https://api.twin.so"; + }, + _headers() { + return { + "x-api-key": this.$auth.api_key, + }; + }, + _makeRequest({ + $ = this, + path, + ...args + }) { + return axios($, { + url: `${this._baseUrl()}${path}`, + headers: this._headers(), + ...args, + }); + }, + browse(args = {}) { + return this._makeRequest({ + method: "POST", + path: "/browse", + ...args, + }); + }, + getTask({ + taskId, ...args + }) { + return this._makeRequest({ + path: `/task/${taskId}`, + ...args, + }); + }, + listTasks(args = {}) { + return this._makeRequest({ + path: "/tasks", + ...args, + }); }, }, -}; \ No newline at end of file +}; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0f3c69520a9f9..2036fd0f4e56a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -10338,7 +10338,10 @@ importers: twilio: 3.84.1 components/twin: - specifiers: {} + specifiers: + '@pipedream/platform': ^3.0.3 + dependencies: + '@pipedream/platform': 3.0.3 components/twist: specifiers: