diff --git a/.gitignore b/.gitignore index 1d854768ceef9..9bb517100444a 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,5 @@ components/**/package-lock.json /packages/sdk/examples/.next/ **/.claude/settings.local.json + +.cursor \ No newline at end of file diff --git a/components/rumi_ai/actions/add-session-access/add-session-access.mjs b/components/rumi_ai/actions/add-session-access/add-session-access.mjs new file mode 100644 index 0000000000000..5bfa27372083f --- /dev/null +++ b/components/rumi_ai/actions/add-session-access/add-session-access.mjs @@ -0,0 +1,66 @@ +import app from "../../rumi_ai.app.mjs"; + +export default { + key: "rumi_ai-add-session-access", + name: "Add Session Access", + description: "Add access to a session for specific email addresses or domains. [See the documentation](https://rumiai.notion.site/Rumi-Public-API-Authentication-02055b7286874bd7b355862f1abe48d9)", + version: "0.0.1", + type: "action", + props: { + app, + sessionId: { + propDefinition: [ + app, + "sessionId", + ], + }, + sessionRecurrenceId: { + propDefinition: [ + app, + "sessionRecurrenceId", + ], + }, + emails: { + propDefinition: [ + app, + "emails", + ], + }, + domains: { + propDefinition: [ + app, + "domains", + ], + }, + message: { + propDefinition: [ + app, + "message", + ], + }, + }, + async run({ $ }) { + const { + app, + sessionId, + sessionRecurrenceId, + emails, + domains, + message, + } = this; + + const response = await app.addSessionAccess({ + $, + data: { + sessionID: sessionId, + sessionRecurrenceID: sessionRecurrenceId, + emails, + domains, + message, + }, + }); + + $.export("$summary", `Successfully added access to session \`${sessionId}\``); + return response; + }, +}; diff --git a/components/rumi_ai/actions/ai-stream-query/ai-stream-query.mjs b/components/rumi_ai/actions/ai-stream-query/ai-stream-query.mjs new file mode 100644 index 0000000000000..ef2831403a025 --- /dev/null +++ b/components/rumi_ai/actions/ai-stream-query/ai-stream-query.mjs @@ -0,0 +1,50 @@ +import app from "../../rumi_ai.app.mjs"; + +export default { + key: "rumi_ai-ai-stream-query", + name: "AI Stream Query", + description: "Stream an AI query against session memories. [See the documentation](https://rumiai.notion.site/Rumi-Public-API-Authentication-02055b7286874bd7b355862f1abe48d9)", + version: "0.0.1", + type: "action", + props: { + app, + query: { + propDefinition: [ + app, + "query", + ], + }, + requestId: { + propDefinition: [ + app, + "requestId", + ], + }, + tz: { + propDefinition: [ + app, + "tz", + ], + }, + }, + async run({ $ }) { + const { + app, + query, + requestId, + tz, + } = this; + + const response = await app.streamAiQuery({ + $, + data: { + query, + requestId, + tz, + }, + }); + + $.export("$summary", "Successfully executed AI stream query"); + return response; + }, +}; diff --git a/components/rumi_ai/actions/create-session/create-session.mjs b/components/rumi_ai/actions/create-session/create-session.mjs new file mode 100644 index 0000000000000..5eb14ab0549dd --- /dev/null +++ b/components/rumi_ai/actions/create-session/create-session.mjs @@ -0,0 +1,105 @@ +import { ConfigurationError } from "@pipedream/platform"; +import app from "../../rumi_ai.app.mjs"; + +export default { + key: "rumi_ai-create-session", + name: "Create Session", + description: "Create a new session/meeting. [See the documentation](https://rumiai.notion.site/Rumi-Public-API-Authentication-02055b7286874bd7b355862f1abe48d9)", + version: "0.0.1", + type: "action", + props: { + app, + sessionTitle: { + propDefinition: [ + app, + "sessionTitle", + ], + }, + about: { + description: "A brief description of the session.", + propDefinition: [ + app, + "about", + ], + }, + startDateTime: { + propDefinition: [ + app, + "startDateTime", + ], + }, + endDateTime: { + propDefinition: [ + app, + "endDateTime", + ], + }, + enableRecording: { + propDefinition: [ + app, + "enableRecording", + ], + }, + summaAI: { + propDefinition: [ + app, + "summaAI", + ], + }, + }, + async run({ $ }) { + const { + app, + sessionTitle, + about, + startDateTime, + endDateTime, + enableRecording, + summaAI, + } = this; + + const startDateTimeObj = new Date(startDateTime); + const endDateTimeObj = new Date(endDateTime); + + if (isNaN(startDateTimeObj.getTime())) { + throw new ConfigurationError("Invalid **Start Date Time** provided"); + } + if (isNaN(endDateTimeObj.getTime())) { + throw new ConfigurationError("Invalid **End Date Time** provided"); + } + if (endDateTimeObj <= startDateTimeObj) { + throw new ConfigurationError("**End Date Time** must be after **Start Date Time**"); + } + + const startTimestamp = Math.floor(startDateTimeObj.getTime() / 1000); + const endTimestamp = Math.floor(endDateTimeObj.getTime() / 1000); + + const response = await app.createSession({ + $, + data: { + sessionTitle, + about, + dataVisibility: "team-visible", + accessStatus: "unlocked", + startTimestamp, + endTimestamp, + sessionSettings: { + enableRecording, + summaAI, + preferredLanguages: [ + "en-US", + ], + recurring: 0, + postSessionSummaries: { + recipients: { + email: "everyone", + }, + }, + }, + }, + }); + + $.export("$summary", `Successfully created session: ${sessionTitle}`); + return response; + }, +}; diff --git a/components/rumi_ai/actions/get-current-user/get-current-user.mjs b/components/rumi_ai/actions/get-current-user/get-current-user.mjs new file mode 100644 index 0000000000000..c8ece7479dab0 --- /dev/null +++ b/components/rumi_ai/actions/get-current-user/get-current-user.mjs @@ -0,0 +1,22 @@ +import app from "../../rumi_ai.app.mjs"; + +export default { + key: "rumi_ai-get-current-user", + name: "Get Current User", + description: "Get information about the current authenticated user. [See the documentation](https://rumiai.notion.site/Rumi-Public-API-Authentication-02055b7286874bd7b355862f1abe48d9)", + version: "0.0.1", + type: "action", + props: { + app, + }, + async run({ $ }) { + const { app } = this; + + const response = await app.getCurrentUser({ + $, + }); + + $.export("$summary", "Successfully retrieved current user information"); + return response; + }, +}; diff --git a/components/rumi_ai/actions/get-future-sessions/get-future-sessions.mjs b/components/rumi_ai/actions/get-future-sessions/get-future-sessions.mjs new file mode 100644 index 0000000000000..f07c148543cb7 --- /dev/null +++ b/components/rumi_ai/actions/get-future-sessions/get-future-sessions.mjs @@ -0,0 +1,22 @@ +import app from "../../rumi_ai.app.mjs"; + +export default { + key: "rumi_ai-get-future-sessions", + name: "Get Future Sessions", + description: "Retrieve upcoming/future sessions. [See the documentation](https://rumiai.notion.site/Rumi-Public-API-Authentication-02055b7286874bd7b355862f1abe48d9)", + version: "0.0.1", + type: "action", + props: { + app, + }, + async run({ $ }) { + const { app } = this; + + const response = await app.getFutureSessions({ + $, + }); + + $.export("$summary", `Successfully retrieved \`${response?.data?.sessions?.length}\` future session(s)`); + return response; + }, +}; diff --git a/components/rumi_ai/actions/get-meeting-types/get-meeting-types.mjs b/components/rumi_ai/actions/get-meeting-types/get-meeting-types.mjs new file mode 100644 index 0000000000000..527506758aa7a --- /dev/null +++ b/components/rumi_ai/actions/get-meeting-types/get-meeting-types.mjs @@ -0,0 +1,22 @@ +import app from "../../rumi_ai.app.mjs"; + +export default { + key: "rumi_ai-get-meeting-types", + name: "Get Meeting Types", + description: "Retrieve available meeting types. [See the documentation](https://rumiai.notion.site/Rumi-Public-API-Authentication-02055b7286874bd7b355862f1abe48d9)", + version: "0.0.1", + type: "action", + props: { + app, + }, + async run({ $ }) { + const { app } = this; + + const response = await app.getMeetingTypes({ + $, + }); + + $.export("$summary", `Successfully retrieved \`${response?.data?.meetingTypes?.length}\` meeting type(s)`); + return response; + }, +}; diff --git a/components/rumi_ai/actions/get-memory-threads/get-memory-threads.mjs b/components/rumi_ai/actions/get-memory-threads/get-memory-threads.mjs new file mode 100644 index 0000000000000..2baea26d79c52 --- /dev/null +++ b/components/rumi_ai/actions/get-memory-threads/get-memory-threads.mjs @@ -0,0 +1,34 @@ +import app from "../../rumi_ai.app.mjs"; + +export default { + key: "rumi_ai-get-memory-threads", + name: "Get Memory Threads", + description: "Retrieve memory threads. [See the documentation](https://rumiai.notion.site/Rumi-Public-API-Authentication-02055b7286874bd7b355862f1abe48d9)", + version: "0.0.1", + type: "action", + props: { + app, + limit: { + propDefinition: [ + app, + "limit", + ], + }, + }, + async run({ $ }) { + const { + app, + limit, + } = this; + + const response = await app.getMemoryThreads({ + $, + params: { + limit, + }, + }); + + $.export("$summary", `Successfully retrieved \`${response?.data?.threads?.length}\` memory thread(s)`); + return response; + }, +}; diff --git a/components/rumi_ai/actions/get-past-sessions/get-past-sessions.mjs b/components/rumi_ai/actions/get-past-sessions/get-past-sessions.mjs new file mode 100644 index 0000000000000..fb41a94e35ac8 --- /dev/null +++ b/components/rumi_ai/actions/get-past-sessions/get-past-sessions.mjs @@ -0,0 +1,33 @@ +import app from "../../rumi_ai.app.mjs"; + +export default { + key: "rumi_ai-get-past-sessions", + name: "Get Past Sessions", + description: "Retrieve past sessions/meetings. [See the documentation](https://rumiai.notion.site/Rumi-Public-API-Authentication-02055b7286874bd7b355862f1abe48d9)", + version: "0.0.1", + type: "action", + props: { + app, + limit: { + propDefinition: [ + app, + "limit", + ], + }, + }, + async run({ $ }) { + const { + app, limit, + } = this; + + const response = await app.getPastSessions({ + $, + params: { + limit, + }, + }); + + $.export("$summary", `Successfully retrieved \`${response?.data?.sessions?.length}\` past session(s)`); + return response; + }, +}; diff --git a/components/rumi_ai/actions/remove-session-access/remove-session-access.mjs b/components/rumi_ai/actions/remove-session-access/remove-session-access.mjs new file mode 100644 index 0000000000000..05e4dae072faa --- /dev/null +++ b/components/rumi_ai/actions/remove-session-access/remove-session-access.mjs @@ -0,0 +1,52 @@ +import app from "../../rumi_ai.app.mjs"; + +export default { + key: "rumi_ai-remove-session-access", + name: "Remove Session Access", + description: "Remove user access from a session. [See the documentation](https://rumiai.notion.site/Rumi-Public-API-Authentication-02055b7286874bd7b355862f1abe48d9)", + version: "0.0.1", + type: "action", + props: { + app, + sessionId: { + propDefinition: [ + app, + "sessionId", + ], + }, + sessionRecurrenceId: { + propDefinition: [ + app, + "sessionRecurrenceId", + ], + }, + accessRuleId: { + type: "string", + label: "Access Rule ID", + description: "The ID of the access rule to remove. This is given when you add access to a session.", + }, + }, + async run({ $ }) { + const { + app, + accessRuleId, + sessionId, + sessionRecurrenceId, + } = this; + + await app.removeSessionAccess({ + $, + data: { + id: accessRuleId, + sessionID: sessionId, + sessionRecurrenceID: sessionRecurrenceId, + type: "email", + }, + }); + + $.export("$summary", "Successfully removed user from session"); + return { + success: true, + }; + }, +}; diff --git a/components/rumi_ai/common/constants.mjs b/components/rumi_ai/common/constants.mjs new file mode 100644 index 0000000000000..7f4081138acc1 --- /dev/null +++ b/components/rumi_ai/common/constants.mjs @@ -0,0 +1,5 @@ +const DEFAULT_LIMIT = 20; + +export default { + DEFAULT_LIMIT, +}; diff --git a/components/rumi_ai/package.json b/components/rumi_ai/package.json index 8bd5c7217fd90..0383a89673ede 100644 --- a/components/rumi_ai/package.json +++ b/components/rumi_ai/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/rumi_ai", - "version": "0.0.1", + "version": "0.1.0", "description": "Pipedream Rumi AI Components", "main": "rumi_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/components/rumi_ai/rumi_ai.app.mjs b/components/rumi_ai/rumi_ai.app.mjs index 0e32ac3a25801..13997aba4fa91 100644 --- a/components/rumi_ai/rumi_ai.app.mjs +++ b/components/rumi_ai/rumi_ai.app.mjs @@ -1,11 +1,211 @@ +import { axios } from "@pipedream/platform"; +import constants from "./common/constants.mjs"; + export default { type: "app", app: "rumi_ai", - propDefinitions: {}, + propDefinitions: { + sessionId: { + type: "string", + label: "Session ID", + description: "The ID of the session", + }, + sessionRecurrenceId: { + type: "string", + label: "Session Recurrence ID", + description: "The recurrence ID of the session", + }, + emails: { + type: "string[]", + label: "Email Addresses", + description: "Array of email addresses to grant access to", + optional: true, + }, + domains: { + type: "string[]", + label: "Domains", + description: "Array of domain names to grant access to", + optional: true, + }, + message: { + type: "string", + label: "Invitation Message", + description: "Optional invitation message to include", + optional: true, + }, + userId: { + type: "string", + label: "User ID", + description: "The ID of the user to add/remove access", + }, + sessionTitle: { + type: "string", + label: "Session Title", + description: "The title of the session", + }, + about: { + type: "string", + label: "About", + description: "Meeting description", + optional: true, + }, + startDateTime: { + type: "string", + label: "Start Date Time", + description: "Session start date and time in ISO format (e.g., `2025-06-15T14:30:00`)", + default: "2025-06-15T09:00:00", + }, + endDateTime: { + type: "string", + label: "End Date Time", + description: "Session end date and time in ISO format (e.g., `2025-06-15T15:30:00`)", + default: "2025-06-15T10:00:00", + }, + enableRecording: { + type: "boolean", + label: "Enable Recording", + description: "Enable call recording for this session", + }, + summaAI: { + type: "boolean", + label: "Enable SummaAI", + description: "Enable transcriptions and AI feed", + }, + recurring: { + type: "integer", + label: "Recurring", + description: "Recurring session setting (0 for non-recurring)", + default: 0, + }, + query: { + type: "string", + label: "Query", + description: "The AI query to stream", + }, + requestId: { + type: "string", + label: "Request ID", + description: "Unique request identifier", + optional: true, + }, + tz: { + type: "string", + label: "Timezone", + description: "Timezone for the query (e.g., Europe/Paris, America/New_York)", + options: [ + "Europe/Paris", + "America/New_York", + "America/Los_Angeles", + "Asia/Tokyo", + "Asia/Kolkata", + "Australia/Sydney", + "UTC", + ], + }, + sessions: { + type: "string[]", + label: "Sessions", + description: "Array of session objects in JSON format. Each entry should be a JSON string like: `{\"id\": \"session_id\", \"recurrenceIds\": [\"recurrence_id_1\", \"recurrence_id_2\"]}`", + optional: true, + }, + limit: { + type: "integer", + label: "Limit", + description: "Maximum number of resources to retrieve", + default: constants.DEFAULT_LIMIT, + optional: true, + }, + }, methods: { - // this.$auth contains connected account data - authKeys() { - console.log(Object.keys(this.$auth)); + getUrl(path) { + return `https://api.rumi.ai/v1.0${path}`; + }, + getHeaders(headers) { + return { + ...headers, + "Authorization": `Bearer ${this.$auth.oauth_access_token}`, + }; + }, + _makeRequest({ + $ = this, path, headers, ...args + }) { + return axios($, { + ...args, + url: this.getUrl(path), + headers: this.getHeaders(headers), + }); + }, + post(args = {}) { + return this._makeRequest({ + ...args, + method: "POST", + }); + }, + delete(args = {}) { + return this._makeRequest({ + ...args, + method: "DELETE", + }); + }, + put(args = {}) { + return this._makeRequest({ + ...args, + method: "PUT", + }); + }, + getCurrentUser(args) { + return this._makeRequest({ + path: "/users/me", + ...args, + }); + }, + getPastSessions(args) { + return this._makeRequest({ + path: "/sessions/past", + ...args, + }); + }, + getFutureSessions(args) { + return this._makeRequest({ + path: "/sessions/future", + ...args, + }); + }, + createSession(args = {}) { + return this.post({ + path: "/sessions", + ...args, + }); + }, + addSessionAccess(args = {}) { + return this.put({ + path: "/sessions/access/add", + ...args, + }); + }, + removeSessionAccess(args = {}) { + return this.delete({ + path: "/sessions/access/remove", + ...args, + }); + }, + streamAiQuery(args = {}) { + return this.post({ + path: "/memory/ai-stream", + ...args, + }); + }, + getMemoryThreads(args = {}) { + return this._makeRequest({ + path: "/memory/threads", + ...args, + }); + }, + getMeetingTypes(args) { + return this._makeRequest({ + path: "/meeting-types", + ...args, + }); }, }, }; diff --git a/components/rumi_ai/sources/new-session-completed/new-session-completed.mjs b/components/rumi_ai/sources/new-session-completed/new-session-completed.mjs new file mode 100644 index 0000000000000..6a767d034ed31 --- /dev/null +++ b/components/rumi_ai/sources/new-session-completed/new-session-completed.mjs @@ -0,0 +1,38 @@ +import { DEFAULT_POLLING_SOURCE_TIMER_INTERVAL } from "@pipedream/platform"; +import app from "../../rumi_ai.app.mjs"; + +export default { + key: "rumi_ai-new-session-completed", + name: "New Session Completed", + description: "Emit new events when a session is completed. [See the documentation](https://rumiai.notion.site/Rumi-Public-API-Authentication-02055b7286874bd7b355862f1abe48d9)", + version: "0.0.1", + type: "source", + dedupe: "unique", + props: { + app, + timer: { + type: "$.interface.timer", + default: { + intervalSeconds: DEFAULT_POLLING_SOURCE_TIMER_INTERVAL, + }, + }, + }, + async run({ $ }) { + const { app } = this; + + const response = await app.getPastSessions({ + $, + debug: true, + }); + + const sessions = response?.data?.sessions || []; + + sessions.forEach((session) => { + this.$emit(session, { + id: session.sessionID, + summary: `New Session Completed ${session.sessionTitle || "Untitled"}`, + ts: session.createTimestamp, + }); + }); + }, +}; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 57e31305818d9..d14e6445ee3e3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -11416,7 +11416,11 @@ importers: specifier: ^3.0.3 version: 3.0.3 - components/rumi_ai: {} + components/rumi_ai: + dependencies: + '@pipedream/platform': + specifier: ^3.0.3 + version: 3.0.3 components/runpod: {} @@ -15639,14 +15643,6 @@ importers: specifier: ^6.0.0 version: 6.2.0 - modelcontextprotocol/node_modules2/@modelcontextprotocol/sdk/dist/cjs: {} - - modelcontextprotocol/node_modules2/@modelcontextprotocol/sdk/dist/esm: {} - - modelcontextprotocol/node_modules2/zod-to-json-schema/dist/cjs: {} - - modelcontextprotocol/node_modules2/zod-to-json-schema/dist/esm: {} - packages/ai: dependencies: '@pipedream/sdk': @@ -36066,8 +36062,6 @@ snapshots: '@putout/operator-filesystem': 5.0.0(putout@36.13.1(eslint@8.57.1)(typescript@5.6.3)) '@putout/operator-json': 2.2.0 putout: 36.13.1(eslint@8.57.1)(typescript@5.6.3) - transitivePeerDependencies: - - supports-color '@putout/operator-regexp@1.0.0(putout@36.13.1(eslint@8.57.1)(typescript@5.6.3))': dependencies: