diff --git a/components/brainbase_labs/README.md b/components/brainbase_labs/README.md new file mode 100644 index 0000000000000..e7b6fc321e178 --- /dev/null +++ b/components/brainbase_labs/README.md @@ -0,0 +1,48 @@ +# Brainbase + +Brainbase is a platform for building and deploying AI voice agents. Create intelligent workers that can handle phone calls, automate customer interactions, and integrate with your existing communication infrastructure. + +## What You Can Do + +With the Brainbase integration on Pipedream, you can: + +- **Automate Voice Agent Deployments** - Programmatically create and configure AI voice agents that can make or receive phone calls +- **Monitor Call Activity** - Track voice deployment logs, analyze sentiment, and retrieve call records for quality assurance +- **Manage Phone Numbers** - Register and configure phone numbers for your voice agents through Twilio integration +- **Build Dynamic Workflows** - Create AI workers with custom flows that adapt based on triggers from other apps in your Pipedream workflows +- **Scale Communications** - Make batch calls to multiple recipients with personalized AI interactions + +## Use Cases + +### Customer Support Automation + +Automatically deploy voice agents when support tickets are created in Zendesk or when specific keywords are detected in emails. Route calls based on customer data and log interactions back to your CRM. + +### Appointment Reminders + +Trigger AI voice calls to remind customers of upcoming appointments when calendar events approach. Collect confirmations and automatically update your scheduling system. + +### Lead Qualification + +Deploy voice agents to call leads from your sales pipeline, ask qualification questions, and route hot leads to human sales reps based on responses and sentiment analysis. + +### Outbound Notifications + +Send voice notifications for order updates, delivery alerts, or account changes by triggering calls when status changes occur in your e-commerce or SaaS platform. + +## Getting Started + +1. Connect your Brainbase account using your API key +2. Create a worker to define your AI agent's purpose +3. Build a flow to script your agent's conversation logic +4. Deploy your voice agent with a phone number +5. Integrate with other Pipedream apps to trigger or respond to voice interactions + +## Authentication + +This integration uses API Key authentication. You'll need to provide your Brainbase API key when connecting the app in Pipedream. + +## Links + +- [Brainbase Documentation](https://docs.usebrainbase.com) +- [Pipedream Community](https://pipedream.com/community) diff --git a/components/brainbase_labs/actions/create-flow/create-flow.mjs b/components/brainbase_labs/actions/create-flow/create-flow.mjs new file mode 100644 index 0000000000000..c222ac6d2080f --- /dev/null +++ b/components/brainbase_labs/actions/create-flow/create-flow.mjs @@ -0,0 +1,65 @@ +import app from "../../brainbase_labs.app.mjs"; + +export default { + key: "brainbase_labs-create-flow", + name: "Create Flow", + description: "Create a new flow for a worker. [See the documentation](https://docs.usebrainbase.com/api-reference/flows/create-a-new-flow)", + version: "0.0.1", + type: "action", + annotations: { + destructiveHint: false, + openWorldHint: true, + readOnlyHint: false, + }, + props: { + app, + workerId: { + propDefinition: [ + app, + "workerId", + ], + }, + name: { + type: "string", + label: "Name", + description: "The name of the flow", + }, + code: { + type: "string", + label: "Code", + description: "The flow code/definition", + }, + label: { + type: "string", + label: "Label", + description: "Optional label for the flow", + }, + variables: { + type: "string", + label: "Variables", + description: "Flow variables (optional)", + optional: true, + }, + validate: { + type: "boolean", + label: "Validate", + description: "Whether to validate the flow", + }, + }, + async run({ $ }) { + const response = await this.app.createFlow({ + $, + workerId: this.workerId, + data: { + name: this.name, + code: this.code, + label: this.label, + variables: this.variables, + validate: this.validate, + }, + }); + + $.export("$summary", `Successfully created flow "${this.name}"`); + return response; + }, +}; diff --git a/components/brainbase_labs/actions/create-twilio-integration/create-twilio-integration.mjs b/components/brainbase_labs/actions/create-twilio-integration/create-twilio-integration.mjs new file mode 100644 index 0000000000000..e8708dd901ee1 --- /dev/null +++ b/components/brainbase_labs/actions/create-twilio-integration/create-twilio-integration.mjs @@ -0,0 +1,40 @@ +import app from "../../brainbase_labs.app.mjs"; + +export default { + key: "brainbase_labs-create-twilio-integration", + name: "Create Twilio Integration", + description: "Create a new Twilio integration for the authenticated team. [See the documentation](https://docs.usebrainbase.com/api-reference/integrations/create-a-new-twilio-integration-for-the-authenticated-team)", + version: "0.0.1", + type: "action", + annotations: { + destructiveHint: false, + openWorldHint: true, + readOnlyHint: false, + }, + props: { + app, + accountSid: { + type: "string", + label: "Account SID", + description: "Twilio account SID", + }, + authToken: { + type: "string", + label: "Auth Token", + description: "Twilio auth token (will be encrypted before being stored)", + secret: true, + }, + }, + async run({ $ }) { + const response = await this.app.createTwilioIntegration({ + $, + data: { + accountSid: this.accountSid, + authToken: this.authToken, + }, + }); + + $.export("$summary", "Successfully created Twilio integration"); + return response; + }, +}; diff --git a/components/brainbase_labs/actions/create-voice-deployment/create-voice-deployment.mjs b/components/brainbase_labs/actions/create-voice-deployment/create-voice-deployment.mjs new file mode 100644 index 0000000000000..59e202d73a84b --- /dev/null +++ b/components/brainbase_labs/actions/create-voice-deployment/create-voice-deployment.mjs @@ -0,0 +1,118 @@ +import app from "../../brainbase_labs.app.mjs"; +import { parseObject } from "../../common/utils.mjs"; + +export default { + key: "brainbase_labs-create-voice-deployment", + name: "Create Voice Deployment", + description: "Create a new voice deployment. [See the documentation](https://docs.usebrainbase.com/api-reference/voice-deployments/create-a-new-voice-deployment)", + version: "0.0.1", + type: "action", + annotations: { + destructiveHint: false, + openWorldHint: true, + readOnlyHint: false, + }, + props: { + app, + workerId: { + propDefinition: [ + app, + "workerId", + ], + }, + name: { + type: "string", + label: "Name", + description: "Deployment name", + }, + phoneNumber: { + type: "string", + label: "Phone Number", + description: "Phone number for deployment (e.g., +1234567890)", + }, + flowId: { + propDefinition: [ + app, + "flowId", + (c) => ({ + workerId: c.workerId, + }), + ], + }, + enableVoiceSentiment: { + type: "boolean", + label: "Enable Voice Sentiment", + description: "Enable voice sentiment analysis", + default: false, + }, + externalConfig: { + type: "object", + label: "External Config", + description: + "External configuration object with voice settings, language, voiceId, etc. Example: `{\"voice\": \"alloy\", \"language\": \"en\"}`", + optional: true, + }, + extractionsKey: { + type: "string", + label: "Extractions Key", + description: "The key of the extractions to use for the deployment", + }, + extractionsType: { + type: "string", + label: "Extractions Type", + description: "The type of the extractions to use for the deployment", + options: [ + "string", + "number", + "boolean", + ], + }, + extractionsDescription: { + type: "string", + label: "Extractions Description", + description: "The description of the extractions to use for the deployment", + }, + extractionsRequired: { + type: "boolean", + label: "Extractions Required", + description: "Whether the extractions are required for the deployment", + }, + successCriteria: { + type: "string[]", + label: "Success Criteria", + description: "Deployment success measurement criteria (optional)", + optional: true, + }, + }, + async run({ $ }) { + const response = await this.app.createVoiceDeployment({ + $, + workerId: this.workerId, + data: { + name: this.name, + phoneNumber: this.phoneNumber, + flowId: this.flowId, + enableVoiceSentiment: this.enableVoiceSentiment, + ...(this.externalConfig && { + externalConfig: parseObject(this.externalConfig), + }), + extractions: { + [this.extractionsKey]: { + type: this.extractionsType, + description: this.extractionsDescription, + required: this.extractionsRequired, + }, + }, + ...(this.successCriteria && { + successCriteria: parseObject(this.successCriteria), + }), + }, + }); + + $.export( + "$summary", + `Successfully created voice deployment "${this.name}"`, + ); + return response; + }, +}; diff --git a/components/brainbase_labs/actions/create-worker/create-worker.mjs b/components/brainbase_labs/actions/create-worker/create-worker.mjs new file mode 100644 index 0000000000000..fdf0630d615f8 --- /dev/null +++ b/components/brainbase_labs/actions/create-worker/create-worker.mjs @@ -0,0 +1,50 @@ +import app from "../../brainbase_labs.app.mjs"; + +export default { + key: "brainbase_labs-create-worker", + name: "Create Worker", + description: "Create a new worker for the team. [See the documentation](https://docs.usebrainbase.com/api-reference/workers/create-a-new-worker)", + version: "0.0.1", + type: "action", + annotations: { + destructiveHint: false, + openWorldHint: true, + readOnlyHint: false, + }, + props: { + app, + name: { + type: "string", + label: "Name", + description: "The name of the worker", + }, + description: { + type: "string", + label: "Description", + description: "Worker description", + }, + status: { + type: "string", + label: "Status", + description: "Worker status", + options: [ + "active", + "inactive", + "archived", + ], + }, + }, + async run({ $ }) { + const response = await this.app.createWorker({ + $, + data: { + name: this.name, + description: this.description, + status: this.status, + }, + }); + + $.export("$summary", `Successfully created worker "${this.name}"`); + return response; + }, +}; diff --git a/components/brainbase_labs/actions/delete-flow/delete-flow.mjs b/components/brainbase_labs/actions/delete-flow/delete-flow.mjs new file mode 100644 index 0000000000000..299fa4605b6ab --- /dev/null +++ b/components/brainbase_labs/actions/delete-flow/delete-flow.mjs @@ -0,0 +1,42 @@ +import app from "../../brainbase_labs.app.mjs"; + +export default { + key: "brainbase_labs-delete-flow", + name: "Delete Flow", + description: "Delete a flow. [See the documentation](https://docs.usebrainbase.com/api-reference/flows/delete-a-flow)", + version: "0.0.1", + type: "action", + annotations: { + destructiveHint: true, + openWorldHint: true, + readOnlyHint: false, + }, + props: { + app, + workerId: { + propDefinition: [ + app, + "workerId", + ], + }, + flowId: { + propDefinition: [ + app, + "flowId", + (c) => ({ + workerId: c.workerId, + }), + ], + }, + }, + async run({ $ }) { + const response = await this.app.deleteFlow({ + $, + workerId: this.workerId, + flowId: this.flowId, + }); + + $.export("$summary", `Successfully deleted flow with ID ${this.flowId}`); + return response; + }, +}; diff --git a/components/brainbase_labs/actions/delete-integration/delete-integration.mjs b/components/brainbase_labs/actions/delete-integration/delete-integration.mjs new file mode 100644 index 0000000000000..5781798f99377 --- /dev/null +++ b/components/brainbase_labs/actions/delete-integration/delete-integration.mjs @@ -0,0 +1,35 @@ +import app from "../../brainbase_labs.app.mjs"; + +export default { + key: "brainbase_labs-delete-integration", + name: "Delete Integration", + description: "Delete an existing Twilio integration. [See the documentation](https://docs.usebrainbase.com/api-reference/integrations/delete-an-existing-twilio-integration)", + version: "0.0.1", + type: "action", + annotations: { + destructiveHint: true, + openWorldHint: true, + readOnlyHint: false, + }, + props: { + app, + integrationId: { + propDefinition: [ + app, + "integrationId", + ], + }, + }, + async run({ $ }) { + const response = await this.app.deleteIntegration({ + $, + integrationId: this.integrationId, + }); + + $.export( + "$summary", + `Successfully deleted integration with ID ${this.integrationId}`, + ); + return response; + }, +}; diff --git a/components/brainbase_labs/actions/delete-phone-number/delete-phone-number.mjs b/components/brainbase_labs/actions/delete-phone-number/delete-phone-number.mjs new file mode 100644 index 0000000000000..ee8abef879f5d --- /dev/null +++ b/components/brainbase_labs/actions/delete-phone-number/delete-phone-number.mjs @@ -0,0 +1,35 @@ +import app from "../../brainbase_labs.app.mjs"; + +export default { + key: "brainbase_labs-delete-phone-number", + name: "Delete Phone Number", + description: "Delete a registered phone number for the team. [See the documentation](https://docs.usebrainbase.com/api-reference/assets/delete-a-registered-phone-number-for-the-team)", + version: "0.0.1", + type: "action", + annotations: { + destructiveHint: true, + openWorldHint: true, + readOnlyHint: false, + }, + props: { + app, + phoneNumberId: { + propDefinition: [ + app, + "phoneNumberId", + ], + }, + }, + async run({ $ }) { + const response = await this.app.deletePhoneNumber({ + $, + phoneNumberId: this.phoneNumberId, + }); + + $.export( + "$summary", + `Successfully deleted phone number with ID ${this.phoneNumberId}`, + ); + return response; + }, +}; diff --git a/components/brainbase_labs/actions/delete-voice-deployment/delete-voice-deployment.mjs b/components/brainbase_labs/actions/delete-voice-deployment/delete-voice-deployment.mjs new file mode 100644 index 0000000000000..2e5a4a30cd1e5 --- /dev/null +++ b/components/brainbase_labs/actions/delete-voice-deployment/delete-voice-deployment.mjs @@ -0,0 +1,45 @@ +import app from "../../brainbase_labs.app.mjs"; + +export default { + key: "brainbase_labs-delete-voice-deployment", + name: "Delete Voice Deployment", + description: "Delete a voice deployment. [See the documentation](https://docs.usebrainbase.com/api-reference/voice-deployments/delete-a-voice-deployment)", + version: "0.0.1", + type: "action", + annotations: { + destructiveHint: true, + openWorldHint: true, + readOnlyHint: false, + }, + props: { + app, + workerId: { + propDefinition: [ + app, + "workerId", + ], + }, + deploymentId: { + propDefinition: [ + app, + "deploymentId", + (c) => ({ + workerId: c.workerId, + }), + ], + }, + }, + async run({ $ }) { + const response = await this.app.deleteVoiceDeployment({ + $, + workerId: this.workerId, + deploymentId: this.deploymentId, + }); + + $.export( + "$summary", + `Successfully deleted voice deployment with ID ${this.deploymentId}`, + ); + return response; + }, +}; diff --git a/components/brainbase_labs/actions/delete-worker/delete-worker.mjs b/components/brainbase_labs/actions/delete-worker/delete-worker.mjs new file mode 100644 index 0000000000000..2f6e02719610c --- /dev/null +++ b/components/brainbase_labs/actions/delete-worker/delete-worker.mjs @@ -0,0 +1,35 @@ +import app from "../../brainbase_labs.app.mjs"; + +export default { + key: "brainbase_labs-delete-worker", + name: "Delete Worker", + description: "Delete a worker. [See the documentation](https://docs.usebrainbase.com/api-reference/workers/delete-a-worker)", + version: "0.0.1", + type: "action", + annotations: { + destructiveHint: true, + openWorldHint: true, + readOnlyHint: false, + }, + props: { + app, + workerId: { + propDefinition: [ + app, + "workerId", + ], + }, + }, + async run({ $ }) { + const response = await this.app.deleteWorker({ + $, + workerId: this.workerId, + }); + + $.export( + "$summary", + `Successfully deleted worker with ID ${this.workerId}`, + ); + return response; + }, +}; diff --git a/components/brainbase_labs/actions/get-flow/get-flow.mjs b/components/brainbase_labs/actions/get-flow/get-flow.mjs new file mode 100644 index 0000000000000..fd20fd39e47cd --- /dev/null +++ b/components/brainbase_labs/actions/get-flow/get-flow.mjs @@ -0,0 +1,42 @@ +import app from "../../brainbase_labs.app.mjs"; + +export default { + key: "brainbase_labs-get-flow", + name: "Get Flow", + description: "Get a single flow by ID. [See the documentation](https://docs.usebrainbase.com/api-reference/flows/get-a-single-flow)", + version: "0.0.1", + type: "action", + annotations: { + destructiveHint: false, + openWorldHint: true, + readOnlyHint: true, + }, + props: { + app, + workerId: { + propDefinition: [ + app, + "workerId", + ], + }, + flowId: { + propDefinition: [ + app, + "flowId", + (c) => ({ + workerId: c.workerId, + }), + ], + }, + }, + async run({ $ }) { + const response = await this.app.getFlow({ + $, + workerId: this.workerId, + flowId: this.flowId, + }); + + $.export("$summary", `Successfully retrieved flow with ID ${this.flowId}`); + return response; + }, +}; diff --git a/components/brainbase_labs/actions/get-integration/get-integration.mjs b/components/brainbase_labs/actions/get-integration/get-integration.mjs new file mode 100644 index 0000000000000..7ef2d30d60e67 --- /dev/null +++ b/components/brainbase_labs/actions/get-integration/get-integration.mjs @@ -0,0 +1,35 @@ +import app from "../../brainbase_labs.app.mjs"; + +export default { + key: "brainbase_labs-get-integration", + name: "Get Integration", + description: "Get a specific integration by ID. [See the documentation](https://docs.usebrainbase.com/api-reference/integrations/get-a-specific-integration-by-id)", + version: "0.0.1", + type: "action", + annotations: { + destructiveHint: false, + openWorldHint: true, + readOnlyHint: true, + }, + props: { + app, + integrationId: { + propDefinition: [ + app, + "integrationId", + ], + }, + }, + async run({ $ }) { + const response = await this.app.getIntegration({ + $, + integrationId: this.integrationId, + }); + + $.export( + "$summary", + `Successfully retrieved integration with ID ${this.integrationId}`, + ); + return response; + }, +}; diff --git a/components/brainbase_labs/actions/get-phone-numbers/get-phone-numbers.mjs b/components/brainbase_labs/actions/get-phone-numbers/get-phone-numbers.mjs new file mode 100644 index 0000000000000..ece010a921270 --- /dev/null +++ b/components/brainbase_labs/actions/get-phone-numbers/get-phone-numbers.mjs @@ -0,0 +1,41 @@ +import app from "../../brainbase_labs.app.mjs"; + +export default { + key: "brainbase_labs-get-phone-numbers", + name: "Get Phone Numbers", + description: "Get all registered phone numbers for the team, optionally filtered by integration id. [See the documentation](https://docs.usebrainbase.com/api-reference/assets/get-all-registered-phone-numbers-for-the-team-optionally-filtered-by-integration-id)", + version: "0.0.1", + type: "action", + annotations: { + destructiveHint: false, + openWorldHint: true, + readOnlyHint: true, + }, + props: { + app, + integrationId: { + propDefinition: [ + app, + "integrationId", + ], + optional: true, + }, + }, + async run({ $ }) { + const params = {}; + if (this.integrationId) { + params.integrationId = this.integrationId; + } + + const response = await this.app.getPhoneNumbers({ + $, + params, + }); + + $.export( + "$summary", + `Successfully retrieved ${response.data?.length || 0} phone number(s)`, + ); + return response; + }, +}; diff --git a/components/brainbase_labs/actions/get-team/get-team.mjs b/components/brainbase_labs/actions/get-team/get-team.mjs new file mode 100644 index 0000000000000..6e4e548d03d47 --- /dev/null +++ b/components/brainbase_labs/actions/get-team/get-team.mjs @@ -0,0 +1,36 @@ +import app from "../../brainbase_labs.app.mjs"; + +export default { + key: "brainbase_labs-get-team", + name: "Get Team", + description: "Get the team associated with the provided API key. [See the documentation](https://docs.usebrainbase.com/api-reference/team/get-the-team-associated-with-the-provided-api-key)", + version: "0.0.1", + type: "action", + annotations: { + destructiveHint: false, + openWorldHint: true, + readOnlyHint: true, + }, + props: { + app, + includeIntegrations: { + type: "boolean", + label: "Include Integrations", + description: "Set to true to also include integrations in the response", + optional: true, + }, + }, + async run({ $ }) { + const params = { + includeIntegrations: this.includeIntegrations, + }; + + const response = await this.app.getTeam({ + $, + params, + }); + + $.export("$summary", "Successfully retrieved team information"); + return response; + }, +}; diff --git a/components/brainbase_labs/actions/get-voice-deployment-log/get-voice-deployment-log.mjs b/components/brainbase_labs/actions/get-voice-deployment-log/get-voice-deployment-log.mjs new file mode 100644 index 0000000000000..d836ea54ca7be --- /dev/null +++ b/components/brainbase_labs/actions/get-voice-deployment-log/get-voice-deployment-log.mjs @@ -0,0 +1,42 @@ +import app from "../../brainbase_labs.app.mjs"; + +export default { + key: "brainbase_labs-get-voice-deployment-log", + name: "Get Voice Deployment Log", + description: "Retrieve a single voice deployment log record. [See the documentation](https://docs.usebrainbase.com/api-reference/voice-deployment-logs/retrieve-a-single-voice-deployment-log-record)", + version: "0.0.2", + type: "action", + annotations: { + destructiveHint: false, + openWorldHint: true, + readOnlyHint: true, + }, + props: { + app, + workerId: { + propDefinition: [ + app, + "workerId", + ], + }, + logId: { + propDefinition: [ + app, + "voiceDeploymentLogId", + (c) => ({ + workerId: c.workerId, + }), + ], + }, + }, + async run({ $ }) { + const response = await this.app.getVoiceDeploymentLog({ + $, + workerId: this.workerId, + logId: this.logId, + }); + + $.export("$summary", `Successfully retrieved log with ID ${this.logId}`); + return response; + }, +}; diff --git a/components/brainbase_labs/actions/get-voice-deployment/get-voice-deployment.mjs b/components/brainbase_labs/actions/get-voice-deployment/get-voice-deployment.mjs new file mode 100644 index 0000000000000..0d7fbc2e1dd60 --- /dev/null +++ b/components/brainbase_labs/actions/get-voice-deployment/get-voice-deployment.mjs @@ -0,0 +1,45 @@ +import app from "../../brainbase_labs.app.mjs"; + +export default { + key: "brainbase_labs-get-voice-deployment", + name: "Get Voice Deployment", + description: "Get a single voice deployment by ID. [See the documentation](https://docs.usebrainbase.com/api-reference/voice-deployments/get-a-single-voice-deployment)", + version: "0.0.1", + type: "action", + annotations: { + destructiveHint: false, + openWorldHint: true, + readOnlyHint: true, + }, + props: { + app, + workerId: { + propDefinition: [ + app, + "workerId", + ], + }, + deploymentId: { + propDefinition: [ + app, + "deploymentId", + (c) => ({ + workerId: c.workerId, + }), + ], + }, + }, + async run({ $ }) { + const response = await this.app.getVoiceDeployment({ + $, + workerId: this.workerId, + deploymentId: this.deploymentId, + }); + + $.export( + "$summary", + `Successfully retrieved voice deployment with ID ${this.deploymentId}`, + ); + return response; + }, +}; diff --git a/components/brainbase_labs/actions/get-worker/get-worker.mjs b/components/brainbase_labs/actions/get-worker/get-worker.mjs new file mode 100644 index 0000000000000..69e3f647772a5 --- /dev/null +++ b/components/brainbase_labs/actions/get-worker/get-worker.mjs @@ -0,0 +1,35 @@ +import app from "../../brainbase_labs.app.mjs"; + +export default { + key: "brainbase_labs-get-worker", + name: "Get Worker", + description: "Get a single worker by ID. [See the documentation](https://docs.usebrainbase.com/api-reference/workers/get-a-single-worker)", + version: "0.0.1", + type: "action", + annotations: { + destructiveHint: false, + openWorldHint: true, + readOnlyHint: true, + }, + props: { + app, + workerId: { + propDefinition: [ + app, + "workerId", + ], + }, + }, + async run({ $ }) { + const response = await this.app.getWorker({ + $, + workerId: this.workerId, + }); + + $.export( + "$summary", + `Successfully retrieved worker with ID ${this.workerId}`, + ); + return response; + }, +}; diff --git a/components/brainbase_labs/actions/list-flows/list-flows.mjs b/components/brainbase_labs/actions/list-flows/list-flows.mjs new file mode 100644 index 0000000000000..05b79b9a1e182 --- /dev/null +++ b/components/brainbase_labs/actions/list-flows/list-flows.mjs @@ -0,0 +1,35 @@ +import app from "../../brainbase_labs.app.mjs"; + +export default { + key: "brainbase_labs-list-flows", + name: "List Flows", + description: "Get all flows for a worker. [See the documentation](https://docs.usebrainbase.com/api-reference/flows/get-all-flows-for-a-worker)", + version: "0.0.1", + type: "action", + annotations: { + destructiveHint: false, + openWorldHint: true, + readOnlyHint: true, + }, + props: { + app, + workerId: { + propDefinition: [ + app, + "workerId", + ], + }, + }, + async run({ $ }) { + const response = await this.app.listFlows({ + $, + workerId: this.workerId, + }); + + $.export( + "$summary", + `Successfully retrieved ${response?.length || 0} flow(s)`, + ); + return response; + }, +}; diff --git a/components/brainbase_labs/actions/list-integrations/list-integrations.mjs b/components/brainbase_labs/actions/list-integrations/list-integrations.mjs new file mode 100644 index 0000000000000..e805111918ae3 --- /dev/null +++ b/components/brainbase_labs/actions/list-integrations/list-integrations.mjs @@ -0,0 +1,28 @@ +import app from "../../brainbase_labs.app.mjs"; + +export default { + key: "brainbase_labs-list-integrations", + name: "List Integrations", + description: "Get all integrations for the authenticated team. [See the documentation](https://docs.usebrainbase.com/api-reference/integrations/get-all-integrations-for-the-authenticated-team)", + version: "0.0.1", + type: "action", + annotations: { + destructiveHint: false, + openWorldHint: true, + readOnlyHint: true, + }, + props: { + app, + }, + async run({ $ }) { + const response = await this.app.listIntegrations({ + $, + }); + + $.export( + "$summary", + `Successfully retrieved ${response?.length || 0} integration(s)`, + ); + return response; + }, +}; diff --git a/components/brainbase_labs/actions/list-voice-deployment-logs/list-voice-deployment-logs.mjs b/components/brainbase_labs/actions/list-voice-deployment-logs/list-voice-deployment-logs.mjs new file mode 100644 index 0000000000000..7a9e96328f5d5 --- /dev/null +++ b/components/brainbase_labs/actions/list-voice-deployment-logs/list-voice-deployment-logs.mjs @@ -0,0 +1,83 @@ +import app from "../../brainbase_labs.app.mjs"; + +export default { + key: "brainbase_labs-list-voice-deployment-logs", + name: "List Voice Deployment Logs", + description: "List voice deployment logs for a worker with optional filtering and pagination. [See the documentation](https://docs.usebrainbase.com/api-reference/voice-deployment-logs/list-voice-deployment-logs-for-a-worker-with-optional-filtering-and-pagination)", + version: "0.0.1", + type: "action", + annotations: { + destructiveHint: false, + openWorldHint: true, + readOnlyHint: true, + }, + props: { + app, + workerId: { + propDefinition: [ + app, + "workerId", + ], + }, + deploymentId: { + propDefinition: [ + app, + "deploymentId", + (c) => ({ + workerId: c.workerId, + }), + ], + description: "Filter logs by deployment ID (optional)", + optional: true, + }, + flowId: { + propDefinition: [ + app, + "flowId", + (c) => ({ + workerId: c.workerId, + }), + ], + description: "Filter logs by flow ID (optional)", + optional: true, + }, + page: { + type: "integer", + label: "Page", + description: "Page number for pagination (default: 1, minimum: 1)", + optional: true, + min: 1, + default: 1, + }, + limit: { + type: "integer", + label: "Limit", + description: "Number of items per page (default: 100, minimum: 1, maximum: 100)", + optional: true, + min: 1, + max: 100, + default: 100, + }, + }, + async run({ $ }) { + const params = { + page: this.page, + limit: this.limit, + }; + + if (this.deploymentId) params.deploymentId = this.deploymentId; + if (this.flowId) params.flowId = this.flowId; + + const response = await this.app.listVoiceDeploymentLogs({ + $, + workerId: this.workerId, + params, + }); + + $.export( + "$summary", + `Successfully retrieved ${response?.length || 0} log(s)`, + ); + return response; + }, +}; diff --git a/components/brainbase_labs/actions/list-voice-deployments/list-voice-deployments.mjs b/components/brainbase_labs/actions/list-voice-deployments/list-voice-deployments.mjs new file mode 100644 index 0000000000000..77327e3fad99f --- /dev/null +++ b/components/brainbase_labs/actions/list-voice-deployments/list-voice-deployments.mjs @@ -0,0 +1,35 @@ +import app from "../../brainbase_labs.app.mjs"; + +export default { + key: "brainbase_labs-list-voice-deployments", + name: "List Voice Deployments", + description: "Get all voice deployments for a worker. [See the documentation](https://docs.usebrainbase.com/api-reference/voice-deployments/get-all-voice-deployments-for-a-worker)", + version: "0.0.1", + type: "action", + annotations: { + destructiveHint: false, + openWorldHint: true, + readOnlyHint: true, + }, + props: { + app, + workerId: { + propDefinition: [ + app, + "workerId", + ], + }, + }, + async run({ $ }) { + const response = await this.app.listVoiceDeployments({ + $, + workerId: this.workerId, + }); + + $.export( + "$summary", + `Successfully retrieved ${response?.length || 0} voice deployment(s)`, + ); + return response; + }, +}; diff --git a/components/brainbase_labs/actions/list-workers/list-workers.mjs b/components/brainbase_labs/actions/list-workers/list-workers.mjs new file mode 100644 index 0000000000000..b89d1fdc956f5 --- /dev/null +++ b/components/brainbase_labs/actions/list-workers/list-workers.mjs @@ -0,0 +1,28 @@ +import app from "../../brainbase_labs.app.mjs"; + +export default { + key: "brainbase_labs-list-workers", + name: "List Workers", + description: "Get all workers for the team. [See the documentation](https://docs.usebrainbase.com/api-reference/workers/get-all-workers-for-the-team)", + version: "0.0.1", + type: "action", + annotations: { + destructiveHint: false, + openWorldHint: true, + readOnlyHint: true, + }, + props: { + app, + }, + async run({ $ }) { + const response = await this.app.listWorkers({ + $, + }); + + $.export( + "$summary", + `Successfully retrieved ${response?.length || 0} worker(s)`, + ); + return response; + }, +}; diff --git a/components/brainbase_labs/actions/make-voice-batch-calls/make-voice-batch-calls.mjs b/components/brainbase_labs/actions/make-voice-batch-calls/make-voice-batch-calls.mjs new file mode 100644 index 0000000000000..cef74b62ebd73 --- /dev/null +++ b/components/brainbase_labs/actions/make-voice-batch-calls/make-voice-batch-calls.mjs @@ -0,0 +1,101 @@ +import app from "../../brainbase_labs.app.mjs"; +import { parseObject } from "../../common/utils.mjs"; + +export default { + key: "brainbase_labs-make-voice-batch-calls", + name: "Make Voice Batch Calls", + description: "Make batch calls for a voice deployment. [See the documentation](https://docs.usebrainbase.com/api-reference/voice-deployments/make-batch-calls-for-a-voice-deployment)", + version: "0.0.1", + type: "action", + annotations: { + destructiveHint: false, + openWorldHint: true, + readOnlyHint: false, + }, + props: { + app, + workerId: { + propDefinition: [ + app, + "workerId", + ], + }, + deploymentId: { + propDefinition: [ + app, + "deploymentId", + (c) => ({ + workerId: c.workerId, + }), + ], + }, + data: { + type: "object", + label: "Data", + description: "Array of data objects with string key-value pairs for each call. Example: `[{\"name\": \"John\", \"phone\": \"+1234567890\"}, {\"name\": \"Jane\", \"phone\": \"+0987654321\"}]`", + }, + batchSize: { + type: "integer", + label: "Batch Size", + description: "Number of calls to process in each batch", + min: 1, + optional: true, + }, + batchIntervalMinutes: { + type: "integer", + label: "Batch Interval (Minutes)", + description: "Time interval between batches in minutes", + min: 1, + optional: true, + }, + wsUrl: { + type: "string", + label: "WebSocket URL", + description: "WebSocket URL for real-time updates", + optional: true, + }, + condition: { + type: "string", + label: "Condition", + description: "Optional condition filter for the batch calls", + optional: true, + }, + extractions: { + type: "string", + label: "Extractions", + description: "Optional extractions configuration", + optional: true, + }, + additionalData: { + type: "string", + label: "Additional Data", + description: "Optional additional data for the batch calls", + optional: true, + }, + }, + async run({ $ }) { + const requestData = { + data: parseObject(this.data), + batch_size: this.batchSize, + batch_interval_minutes: this.batchIntervalMinutes, + wsUrl: this.wsUrl, + }; + + if (this.condition) requestData.condition = this.condition; + if (this.extractions) requestData.extractions = this.extractions; + if (this.additionalData) requestData.additional_data = this.additionalData; + + const response = await this.app.makeVoiceBatchCalls({ + $, + workerId: this.workerId, + deploymentId: this.deploymentId, + data: requestData, + }); + + $.export( + "$summary", + `Successfully initiated batch calls for ${this.data.length} recipient(s)`, + ); + return response; + }, +}; diff --git a/components/brainbase_labs/actions/register-phone-number/register-phone-number.mjs b/components/brainbase_labs/actions/register-phone-number/register-phone-number.mjs new file mode 100644 index 0000000000000..a4385e4559ca1 --- /dev/null +++ b/components/brainbase_labs/actions/register-phone-number/register-phone-number.mjs @@ -0,0 +1,44 @@ +import app from "../../brainbase_labs.app.mjs"; + +export default { + key: "brainbase_labs-register-phone-number", + name: "Register Phone Number", + description: "Register a phone number for the team via Twilio integration. [See the documentation](https://docs.usebrainbase.com/api-reference/assets/register-a-phone-number-for-the-team-via-twilio-integration)", + version: "0.0.1", + type: "action", + annotations: { + destructiveHint: false, + openWorldHint: true, + readOnlyHint: false, + }, + props: { + app, + phoneNumber: { + type: "string", + label: "Phone Number", + description: "Phone number to register (e.g., +1234567890)", + }, + integrationId: { + propDefinition: [ + app, + "integrationId", + ], + description: "Twilio integration identifier", + }, + }, + async run({ $ }) { + const response = await this.app.registerPhoneNumber({ + $, + data: { + phoneNumber: this.phoneNumber, + integrationId: this.integrationId, + }, + }); + + $.export( + "$summary", + `Successfully registered phone number ${this.phoneNumber}`, + ); + return response; + }, +}; diff --git a/components/brainbase_labs/actions/update-flow/update-flow.mjs b/components/brainbase_labs/actions/update-flow/update-flow.mjs new file mode 100644 index 0000000000000..d4caa2b31b4f4 --- /dev/null +++ b/components/brainbase_labs/actions/update-flow/update-flow.mjs @@ -0,0 +1,79 @@ +import app from "../../brainbase_labs.app.mjs"; + +export default { + key: "brainbase_labs-update-flow", + name: "Update Flow", + description: "Update an existing flow. [See the documentation](https://docs.usebrainbase.com/api-reference/flows/update-a-flow)", + version: "0.0.1", + type: "action", + annotations: { + destructiveHint: false, + openWorldHint: true, + readOnlyHint: false, + }, + props: { + app, + workerId: { + propDefinition: [ + app, + "workerId", + ], + }, + flowId: { + propDefinition: [ + app, + "flowId", + (c) => ({ + workerId: c.workerId, + }), + ], + }, + name: { + type: "string", + label: "Name", + description: "The name of the flow", + optional: true, + }, + code: { + type: "string", + label: "Code", + description: "The flow code/definition", + optional: true, + }, + variables: { + type: "string", + label: "Variables", + description: "Flow variables", + optional: true, + }, + validate: { + type: "boolean", + label: "Validate", + description: "Whether to validate the flow", + optional: true, + }, + label: { + type: "string", + label: "Label", + description: "Optional label for the flow", + optional: true, + }, + }, + async run({ $ }) { + const response = await this.app.updateFlow({ + $, + workerId: this.workerId, + flowId: this.flowId, + data: { + name: this.name, + code: this.code, + variables: this.variables, + validate: this.validate, + label: this.label, + }, + }); + + $.export("$summary", `Successfully updated flow with ID: "${this.flowId}"`); + return response; + }, +}; diff --git a/components/brainbase_labs/actions/update-voice-deployment/update-voice-deployment.mjs b/components/brainbase_labs/actions/update-voice-deployment/update-voice-deployment.mjs new file mode 100644 index 0000000000000..cc6c35b668c09 --- /dev/null +++ b/components/brainbase_labs/actions/update-voice-deployment/update-voice-deployment.mjs @@ -0,0 +1,108 @@ +import app from "../../brainbase_labs.app.mjs"; +import { parseObject } from "../../common/utils.mjs"; + +export default { + key: "brainbase_labs-update-voice-deployment", + name: "Update Voice Deployment", + description: "Update an existing voice deployment. [See the documentation](https://docs.usebrainbase.com/api-reference/voice-deployments/update-a-voice-deployment)", + version: "0.0.1", + type: "action", + annotations: { + destructiveHint: false, + openWorldHint: true, + readOnlyHint: false, + }, + props: { + app, + workerId: { + propDefinition: [ + app, + "workerId", + ], + }, + deploymentId: { + propDefinition: [ + app, + "deploymentId", + (c) => ({ + workerId: c.workerId, + }), + ], + }, + name: { + type: "string", + label: "Name", + description: "Deployment name", + optional: true, + }, + phoneNumber: { + type: "string", + label: "Phone Number", + description: "Phone number for deployment", + optional: true, + }, + flowId: { + propDefinition: [ + app, + "flowId", + (c) => ({ + workerId: c.workerId, + }), + ], + optional: true, + }, + externalConfig: { + type: "object", + label: "External Config", + description: "External configuration object", + optional: true, + }, + enableVoiceSentiment: { + type: "boolean", + label: "Enable Voice Sentiment", + description: "Enable voice sentiment analysis", + optional: true, + }, + extractions: { + type: "object", + label: "Extractions", + description: "Extractions configuration", + optional: true, + }, + customWebhooks: { + type: "string[]", + label: "Custom Webhooks", + description: "Custom webhooks array", + optional: true, + }, + successCriteria: { + type: "string[]", + label: "Success Criteria", + description: "Success criteria array", + optional: true, + }, + }, + async run({ $ }) { + const response = await this.app.updateVoiceDeployment({ + $, + workerId: this.workerId, + deploymentId: this.deploymentId, + data: { + name: this.name, + phoneNumber: this.phoneNumber, + flowId: this.flowId, + externalConfig: parseObject(this.externalConfig), + enableVoiceSentiment: this.enableVoiceSentiment, + extractions: parseObject(this.extractions), + customWebhooks: this.customWebhooks, + successCriteria: this.successCriteria, + }, + }); + + $.export( + "$summary", + `Successfully updated voice deployment with ID ${this.deploymentId}`, + ); + return response; + }, +}; diff --git a/components/brainbase_labs/actions/update-worker/update-worker.mjs b/components/brainbase_labs/actions/update-worker/update-worker.mjs new file mode 100644 index 0000000000000..f56d4b775bb37 --- /dev/null +++ b/components/brainbase_labs/actions/update-worker/update-worker.mjs @@ -0,0 +1,60 @@ +import app from "../../brainbase_labs.app.mjs"; + +export default { + key: "brainbase_labs-update-worker", + name: "Update Worker", + description: "Update an existing worker. [See the documentation](https://docs.usebrainbase.com/api-reference/workers/update-a-worker)", + version: "0.0.1", + type: "action", + annotations: { + destructiveHint: false, + openWorldHint: true, + readOnlyHint: false, + }, + props: { + app, + workerId: { + propDefinition: [ + app, + "workerId", + ], + }, + name: { + type: "string", + label: "Name", + description: "The name of the worker", + optional: true, + }, + description: { + type: "string", + label: "Description", + description: "Worker description", + optional: true, + }, + status: { + type: "string", + label: "Status", + description: "Worker status", + optional: true, + options: [ + "active", + "inactive", + "archived", + ], + }, + }, + async run({ $ }) { + const response = await this.app.updateWorker({ + $, + workerId: this.workerId, + data: { + name: this.name, + description: this.description, + status: this.status, + }, + }); + + $.export("$summary", `Successfully updated worker with ID: "${this.workerId}"`); + return response; + }, +}; diff --git a/components/brainbase_labs/brainbase_labs.app.mjs b/components/brainbase_labs/brainbase_labs.app.mjs index c389f6f82b436..37ba5af7400c2 100644 --- a/components/brainbase_labs/brainbase_labs.app.mjs +++ b/components/brainbase_labs/brainbase_labs.app.mjs @@ -1,11 +1,355 @@ +import { axios } from "@pipedream/platform"; + export default { type: "app", app: "brainbase_labs", - propDefinitions: {}, + propDefinitions: { + workerId: { + type: "string", + label: "Worker ID", + description: "The unique identifier for the worker", + async options() { + const data = await this.listWorkers(); + return ( + data?.map(({ + id: value, name: label, + }) => ({ + label, + value, + })) || [] + ); + }, + }, + flowId: { + type: "string", + label: "Flow ID", + description: "The unique identifier for the flow", + async options({ workerId }) { + const data = await this.listFlows({ + workerId, + }); + return ( + data?.map(({ + id: value, name: label, + }) => ({ + label, + value, + })) || [] + ); + }, + }, + deploymentId: { + type: "string", + label: "Deployment ID", + description: "The unique identifier for the voice deployment", + async options({ workerId }) { + const data = await this.listVoiceDeployments({ + workerId, + }); + return ( + data?.map(({ + id: value, name: label, + }) => ({ + label, + value, + })) || [] + ); + }, + }, + integrationId: { + type: "string", + label: "Integration ID", + description: "The unique identifier for the integration", + async options() { + const data = await this.listIntegrations(); + return ( + data?.map(({ + id: value, type: label, + }) => ({ + label: `${label} - ${value}`, + value, + })) || [] + ); + }, + }, + phoneNumberId: { + type: "string", + label: "Phone Number ID", + description: "The unique identifier for the phone number", + async options({ integrationId }) { + const params = {}; + if (integrationId) { + params.integrationId = integrationId; + } + const data = await this.getPhoneNumbers({ + params, + }); + return ( + data?.map(({ + id: value, phoneNumber: label, + }) => ({ + label, + value, + })) || [] + ); + }, + }, + voiceDeploymentLogId: { + type: "string", + label: "Voice Deployment Log ID", + description: "The unique identifier for the voice deployment log entry", + async options({ workerId }) { + const { data } = await this.listVoiceDeploymentLogs({ + workerId, + }); + return data?.map(({ id }) => id) || []; + }, + }, + }, methods: { - // this.$auth contains connected account data - authKeys() { - console.log(Object.keys(this.$auth)); + getUrl(path) { + return `https://brainbase-monorepo-api.onrender.com${path}`; + }, + getHeaders(headers) { + return { + ...headers, + "x-api-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, + }); + }, + patch(args = {}) { + return this._makeRequest({ + method: "PATCH", + ...args, + }); + }, + put(args = {}) { + return this._makeRequest({ + method: "PUT", + ...args, + }); + }, + delete(args = {}) { + return this._makeRequest({ + method: "DELETE", + ...args, + }); + }, + // Assets + deletePhoneNumber({ + phoneNumberId, ...args + } = {}) { + return this.delete({ + path: `/api/team/assets/phone_numbers/${phoneNumberId}/delete`, + ...args, + }); + }, + getPhoneNumbers(args = {}) { + return this._makeRequest({ + path: "/api/team/assets/phone_numbers", + ...args, + }); + }, + registerPhoneNumber(args = {}) { + return this.post({ + path: "/api/team/assets/register_phone_number", + ...args, + }); + }, + // Flows + createFlow({ + workerId, ...args + } = {}) { + return this.post({ + path: `/api/workers/${workerId}/flows`, + ...args, + }); + }, + deleteFlow({ + workerId, flowId, ...args + } = {}) { + return this.delete({ + path: `/api/workers/${workerId}/flows/${flowId}`, + ...args, + }); + }, + getFlow({ + workerId, flowId, ...args + } = {}) { + return this._makeRequest({ + path: `/api/workers/${workerId}/flows/${flowId}`, + ...args, + }); + }, + listFlows({ + workerId, ...args + } = {}) { + return this._makeRequest({ + path: `/api/workers/${workerId}/flows`, + ...args, + }); + }, + updateFlow({ + workerId, flowId, ...args + } = {}) { + return this.patch({ + path: `/api/workers/${workerId}/flows/${flowId}`, + ...args, + }); + }, + // Integrations + createTwilioIntegration(args = {}) { + return this.post({ + path: "/api/team/integrations/twilio/create", + ...args, + }); + }, + deleteIntegration({ + integrationId, ...args + } = {}) { + return this.delete({ + path: `/api/team/integrations/twilio/${integrationId}/delete`, + ...args, + }); + }, + getIntegration({ + integrationId, ...args + } = {}) { + return this._makeRequest({ + path: `/api/team/integrations/${integrationId}`, + ...args, + }); + }, + listIntegrations(args = {}) { + return this._makeRequest({ + path: "/api/team/integrations", + ...args, + }); + }, + // Team + getTeam(args = {}) { + return this._makeRequest({ + path: "/api/team", + ...args, + }); + }, + // Voice Deployment Logs + listVoiceDeploymentLogs({ + workerId, ...args + } = {}) { + return this._makeRequest({ + path: `/api/workers/${workerId}/deploymentLogs/voice`, + ...args, + }); + }, + getVoiceDeploymentLog({ + workerId, logId, ...args + } = {}) { + return this._makeRequest({ + path: `/api/workers/${workerId}/deploymentLogs/voice/${logId}`, + ...args, + }); + }, + // Voice Deployments + createVoiceDeployment({ + workerId, ...args + } = {}) { + return this.post({ + path: `/api/workers/${workerId}/deployments/voice`, + ...args, + }); + }, + deleteVoiceDeployment({ + workerId, deploymentId, ...args + } = {}) { + return this.delete({ + path: `/api/workers/${workerId}/deployments/voice/${deploymentId}`, + ...args, + }); + }, + getVoiceDeployment({ + workerId, deploymentId, ...args + } = {}) { + return this._makeRequest({ + path: `/api/workers/${workerId}/deployments/voice/${deploymentId}`, + ...args, + }); + }, + listVoiceDeployments({ + workerId, ...args + } = {}) { + return this._makeRequest({ + path: `/api/workers/${workerId}/deployments/voice`, + ...args, + }); + }, + makeVoiceBatchCalls({ + workerId, deploymentId, ...args + } = {}) { + return this.post({ + path: `/api/workers/${workerId}/deployments/voice/${deploymentId}/make-batch-calls`, + ...args, + }); + }, + updateVoiceDeployment({ + workerId, deploymentId, ...args + } = {}) { + return this.patch({ + path: `/api/workers/${workerId}/deployments/voice/${deploymentId}`, + ...args, + }); + }, + // Workers + createWorker(args = {}) { + return this.post({ + path: "/api/workers", + ...args, + }); + }, + deleteWorker({ + workerId, ...args + } = {}) { + return this.delete({ + path: `/api/workers/${workerId}`, + ...args, + }); + }, + getWorker({ + workerId, ...args + } = {}) { + return this._makeRequest({ + path: `/api/workers/${workerId}`, + ...args, + }); + }, + listWorkers(args = {}) { + return this._makeRequest({ + path: "/api/workers", + ...args, + }); + }, + updateWorker({ + workerId, ...args + } = {}) { + return this.patch({ + path: `/api/workers/${workerId}`, + ...args, + }); }, }, -}; \ No newline at end of file +}; diff --git a/components/brainbase_labs/common/utils.mjs b/components/brainbase_labs/common/utils.mjs new file mode 100644 index 0000000000000..9667a394c825e --- /dev/null +++ b/components/brainbase_labs/common/utils.mjs @@ -0,0 +1,23 @@ +export const parseObject = (obj) => { + if (!obj) return undefined; + if (typeof obj === "string") { + try { + return JSON.parse(obj); + } catch (e) { + return obj; + } + } + if (Array.isArray(obj)) { + return obj.map(parseObject); + } + if (typeof obj === "object" && obj !== null) { + return Object.fromEntries(Object.entries(obj).map(([ + key, + value, + ]) => [ + key, + parseObject(value), + ])); + } + return obj; +}; diff --git a/components/brainbase_labs/package.json b/components/brainbase_labs/package.json index 759581823680b..dee94b908c6a2 100644 --- a/components/brainbase_labs/package.json +++ b/components/brainbase_labs/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/brainbase_labs", - "version": "0.0.1", + "version": "0.1.0", "description": "Pipedream Brainbase Labs Components", "main": "brainbase_labs.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/brainbase_labs/sources/new-deployment-log-created/new-deployment-log-created.mjs b/components/brainbase_labs/sources/new-deployment-log-created/new-deployment-log-created.mjs new file mode 100644 index 0000000000000..edaef90b4de58 --- /dev/null +++ b/components/brainbase_labs/sources/new-deployment-log-created/new-deployment-log-created.mjs @@ -0,0 +1,121 @@ +import app from "../../brainbase_labs.app.mjs"; +import { DEFAULT_POLLING_SOURCE_TIMER_INTERVAL } from "@pipedream/platform"; + +export default { + key: "brainbase_labs-new-deployment-log-created", + name: "New Deployment Log Created", + description: "Emit new event when a new deployment log is created. [See the documentation](https://docs.usebrainbase.com/api-reference/voice-deployment-logs/list-voice-deployment-logs-for-a-worker-with-optional-filtering-and-pagination)", + version: "0.0.1", + type: "source", + dedupe: "unique", + props: { + app, + db: "$.service.db", + timer: { + type: "$.interface.timer", + default: { + intervalSeconds: DEFAULT_POLLING_SOURCE_TIMER_INTERVAL, + }, + }, + workerId: { + propDefinition: [ + app, + "workerId", + ], + }, + deploymentId: { + propDefinition: [ + app, + "deploymentId", + (c) => ({ + workerId: c.workerId, + }), + ], + description: "Filter logs by deployment ID", + optional: true, + }, + flowId: { + propDefinition: [ + app, + "flowId", + (c) => ({ + workerId: c.workerId, + }), + ], + description: "Filter logs by flow ID", + optional: true, + }, + }, + methods: { + _getLastStartTs() { + return this.db.get("lastStartTs") || 0; + }, + _setLastStartTs(startTs) { + this.db.set("lastStartTs", startTs); + }, + async *paginateLogs() { + let page = 1, hasMore = true; + do { + const { + data, pagination, + } = await this.app.listVoiceDeploymentLogs({ + workerId: this.workerId, + params: { + deploymentId: this.deploymentId, + flowId: this.flowId, + page, + limit: 100, + }, + }); + for (const log of data) { + yield log; + } + hasMore = pagination.hasNext; + page++; + } while (hasMore); + }, + async processEvent(max) { + const lastStartTs = this._getLastStartTs(); + let maxStartTs = lastStartTs; + let logs = []; + + const results = this.paginateLogs(); + for await (const log of results) { + const ts = Date.parse(log.startTime); + if (ts > lastStartTs) { + maxStartTs = Math.max(maxStartTs, ts); + logs.push(log); + } + } + + this._setLastStartTs(maxStartTs); + + if (!logs.length) { + return; + } + + if (max && logs.length > max) { + logs = logs.slice(0, max); + } + + logs.forEach((log) => { + this.$emit(log, this.generateMeta(log)); + }); + }, + generateMeta(log) { + return { + id: log.id, + summary: `New Deployment Log: ${log.id}`, + ts: Date.parse(log.startTime), + }; + }, + }, + hooks: { + async deploy() { + await this.processEvent(10); + }, + }, + async run() { + await this.processEvent(); + }, +}; diff --git a/package.json b/package.json index d4b9376b11d83..66bbe0a14afe3 100644 --- a/package.json +++ b/package.json @@ -56,7 +56,7 @@ "eslint-config-next": "^15", "eslint-plugin-import": "^2.31.0", "eslint-plugin-jest": "^28", - "eslint-plugin-jsonc": "^1.6.0", + "eslint-plugin-jsonc": "^1.7.0", "eslint-plugin-putout": "^23", "globals": "^15.12.0", "graphql": "14 - 16", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6b0ba1d111a8c..009e85e5119d2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -79,7 +79,7 @@ importers: specifier: ^28 version: 28.9.0(@typescript-eslint/eslint-plugin@8.15.0(@typescript-eslint/parser@8.15.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1)(jest@29.7.0(@types/node@20.17.6)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.17.6)(typescript@5.6.3)))(typescript@5.6.3) eslint-plugin-jsonc: - specifier: ^1.6.0 + specifier: ^1.7.0 version: 1.7.0(eslint@8.57.1) eslint-plugin-putout: specifier: ^23 @@ -1977,7 +1977,11 @@ importers: specifier: ^1.5.1 version: 1.6.6 - components/brainbase_labs: {} + components/brainbase_labs: + dependencies: + '@pipedream/platform': + specifier: 3.0.3 + version: 3.0.3 components/brainshop: {}