diff --git a/components/hathr_ai/actions/chat/chat.mjs b/components/hathr_ai/actions/chat/chat.mjs new file mode 100644 index 0000000000000..8bf3b7d40390a --- /dev/null +++ b/components/hathr_ai/actions/chat/chat.mjs @@ -0,0 +1,63 @@ +import hathrAi from "../../hathr_ai.app.mjs"; + +export default { + key: "hathr_ai-chat", + name: "Send Chat Message", + description: "Sends a chat message using Hathr AI. [See the documentation](https://drive.google.com/drive/folders/1jtoSXqzhe-iwf9kfUwTCVQBu4iXVJO2x?usp=sharing)", + version: "0.0.1", + type: "action", + props: { + hathrAi, + message: { + type: "string", + label: "Message", + description: "The message to send in the chat request", + }, + documents: { + propDefinition: [ + hathrAi, + "documents", + ], + }, + temperature: { + type: "string", + label: "Temperature", + description: "Controls randomness (Optional, default: 0.2, range: 0-2.0)", + optional: true, + }, + topP: { + type: "string", + label: "Top P", + description: "Controls diversity (Optional, default: 1.0, range: 0-1.0)", + optional: true, + }, + }, + async run({ $ }) { + const opts = { + $, + data: { + messages: [ + { + role: "user", + text: this.message, + }, + ], + temperature: this.temperature, + topP: this.topP, + }, + }; + const { response } = this.documents + ? await this.hathrAi.chatWithDocuments({ + ...opts, + data: { + ...opts.data, + documents: this.documents, + }, + }) + : await this.hathrAi.chat(opts); + + $.export("$summary", `Chat request sent successfully with message: "${this.message}"`); + + return response; + }, +}; diff --git a/components/hathr_ai/actions/list-documents/list-documents.mjs b/components/hathr_ai/actions/list-documents/list-documents.mjs new file mode 100644 index 0000000000000..33665ba5f61b2 --- /dev/null +++ b/components/hathr_ai/actions/list-documents/list-documents.mjs @@ -0,0 +1,21 @@ +import hathrAi from "../../hathr_ai.app.mjs"; + +export default { + key: "hathr_ai-list-documents", + name: "List Documents", + description: "Retrieves a list of all available documents. [See the documentation](https://drive.google.com/drive/folders/1jtoSXqzhe-iwf9kfUwTCVQBu4iXVJO2x?usp=sharing)", + version: "0.0.1", + type: "action", + props: { + hathrAi, + }, + async run({ $ }) { + const { response: { documents } } = await this.hathrAi.listDocuments({ + $, + }); + $.export("$summary", `Successfully retrieved ${documents.length} document${documents.length === 1 + ? "" + : "s"}`); + return documents; + }, +}; diff --git a/components/hathr_ai/actions/upload-document/upload-document.mjs b/components/hathr_ai/actions/upload-document/upload-document.mjs new file mode 100644 index 0000000000000..7fb82206f7f47 --- /dev/null +++ b/components/hathr_ai/actions/upload-document/upload-document.mjs @@ -0,0 +1,51 @@ +import hathrAi from "../../hathr_ai.app.mjs"; +import { axios } from "@pipedream/platform"; +import { checkTmp } from "../../common/utils.mjs"; +import mime from "mime-types"; +import fs from "fs"; + +export default { + key: "hathr_ai-upload-document", + name: "Upload Document", + description: "Uploads a document that can be used in future chat requests. [See the documentation](https://drive.google.com/drive/folders/1jtoSXqzhe-iwf9kfUwTCVQBu4iXVJO2x?usp=sharing)", + version: "0.0.1", + type: "action", + props: { + hathrAi, + filePath: { + type: "string", + label: "File Path", + description: "The path to a file in the `/tmp` directory. [See the documentation on working with files](https://pipedream.com/docs/code/nodejs/working-with-files/#writing-a-file-to-tmp)", + }, + filename: { + type: "string", + label: "Filename", + description: "The name of the file to be uploaded", + }, + }, + async run({ $ }) { + const filePath = checkTmp(this.filePath); + const fileBuffer = fs.readFileSync(filePath); + const mimeType = mime.lookup(filePath); + + const { response: { signedUrl } } = await this.hathrAi.getUploadUrl({ + $, + data: { + filename: this.filename, + type: mimeType, + }, + }); + + await axios($, { + method: "PUT", + url: signedUrl, + data: fileBuffer, + headers: { + "Content-Type": mimeType, + }, + }); + + $.export("$summary", "Successfully uploaded document."); + return signedUrl; + }, +}; diff --git a/components/hathr_ai/common/utils.mjs b/components/hathr_ai/common/utils.mjs new file mode 100644 index 0000000000000..1a5e36f32a603 --- /dev/null +++ b/components/hathr_ai/common/utils.mjs @@ -0,0 +1,6 @@ +export const checkTmp = (filename) => { + if (!filename.startsWith("/tmp")) { + return `/tmp/${filename}`; + } + return filename; +}; diff --git a/components/hathr_ai/hathr_ai.app.mjs b/components/hathr_ai/hathr_ai.app.mjs index e065e3312e3d7..f3c417cf29faf 100644 --- a/components/hathr_ai/hathr_ai.app.mjs +++ b/components/hathr_ai/hathr_ai.app.mjs @@ -1,11 +1,61 @@ +import { axios } from "@pipedream/platform"; + export default { type: "app", app: "hathr_ai", - propDefinitions: {}, + propDefinitions: { + documents: { + type: "string[]", + label: "Documents", + description: "Array of document names to use as context", + optional: true, + async options() { + const { response: { documents } } = await this.listDocuments(); + return documents?.map(({ name }) => name ) || []; + }, + }, + }, methods: { - // this.$auth contains connected account data - authKeys() { - console.log(Object.keys(this.$auth)); + _baseUrl() { + return "https://api.hathr.ai/v1"; + }, + _makeRequest({ + $ = this, path, ...otherOpts + }) { + return axios($, { + ...otherOpts, + url: `${this._baseUrl()}${path}`, + headers: { + Authorization: `Bearer ${this.$auth.oauth_access_token}`, + }, + }); + }, + listDocuments(opts = {}) { + return this._makeRequest({ + path: "/document/list", + ...opts, + }); + }, + chat(opts = {}) { + return this._makeRequest({ + method: "POST", + path: "/chat", + ...opts, + }); + }, + chatWithDocuments(opts = {}) { + return this._makeRequest({ + method: "POST", + path: "/document/chat", + ...opts, + }); + }, + getUploadUrl(opts = {}) { + return this._makeRequest({ + method: "POST", + path: "/document/upload", + ...opts, + }); }, }, }; diff --git a/components/hathr_ai/package.json b/components/hathr_ai/package.json index 22a2f0207e9da..7e398795871d5 100644 --- a/components/hathr_ai/package.json +++ b/components/hathr_ai/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/hathr_ai", - "version": "0.0.1", + "version": "0.1.0", "description": "Pipedream Hathr AI Components", "main": "hathr_ai.app.mjs", "keywords": [ @@ -11,5 +11,9 @@ "author": "Pipedream (https://pipedream.com/)", "publishConfig": { "access": "public" + }, + "dependencies": { + "@pipedream/platform": "^3.0.3", + "mime-types": "^3.0.1" } -} \ No newline at end of file +} diff --git a/components/hathr_ai/sources/new-document-created/new-document-created.mjs b/components/hathr_ai/sources/new-document-created/new-document-created.mjs new file mode 100644 index 0000000000000..89fbd20918432 --- /dev/null +++ b/components/hathr_ai/sources/new-document-created/new-document-created.mjs @@ -0,0 +1,37 @@ +import hathrAi from "../../hathr_ai.app.mjs"; +import { DEFAULT_POLLING_SOURCE_TIMER_INTERVAL } from "@pipedream/platform"; + +export default { + key: "hathr_ai-new-document-created", + name: "New Document Created", + description: "Emit new event when a new document is created. [See the documentation](https://drive.google.com/drive/folders/1jtoSXqzhe-iwf9kfUwTCVQBu4iXVJO2x?usp=sharing)", + version: "0.0.1", + type: "source", + dedupe: "unique", + props: { + hathrAi, + db: "$.service.db", + timer: { + type: "$.interface.timer", + default: { + intervalSeconds: DEFAULT_POLLING_SOURCE_TIMER_INTERVAL, + }, + }, + }, + methods: { + generateMeta(doc) { + return { + id: doc.name, + summary: `New Document Created: ${doc.name}`, + ts: Date.now(), + }; + }, + }, + async run() { + const { response: { documents } } = await this.hathrAi.listDocuments(); + for (const doc of documents) { + const meta = this.generateMeta(doc); + this.$emit(doc, meta); + } + }, +}; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e0e174ac54173..c3920e0e168e3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -5893,7 +5893,14 @@ importers: components/hasura: {} - components/hathr_ai: {} + components/hathr_ai: + dependencies: + '@pipedream/platform': + specifier: ^3.0.3 + version: 3.0.3 + mime-types: + specifier: ^3.0.1 + version: 3.0.1 components/have_i_been_pwned: {}