From 7bf9251db16a7a8f546d73793a1f2dc9000850b1 Mon Sep 17 00:00:00 2001 From: Waleed Date: Sat, 29 Nov 2025 17:58:42 -0800 Subject: [PATCH 01/16] feat(tools): added smtp, sendgrid, mailgun, linkedin, fixed permissions in context menu (#2133) * feat(tools): added twilio sendgrid integration * feat(tools): added smtp, sendgrid, mailgun, fixed permissions in context menu * added top level mocks for sporadically failing tests * incr type safety --- apps/docs/components/icons.tsx | 94 +++- apps/docs/components/ui/icon-mapping.ts | 8 + apps/docs/content/docs/en/tools/linkedin.mdx | 88 ++++ apps/docs/content/docs/en/tools/mailgun.mdx | 221 ++++++++ apps/docs/content/docs/en/tools/meta.json | 4 + apps/docs/content/docs/en/tools/sendgrid.mdx | 396 +++++++++++++++ apps/docs/content/docs/en/tools/smtp.mdx | 78 +++ .../app/api/chat/[identifier]/route.test.ts | 90 ++-- apps/sim/app/api/tools/smtp/send/route.ts | 227 +++++++++ .../components/oauth-required-modal.tsx | 1 + .../w/[workflowId]/components/panel/panel.tsx | 2 +- .../components/folder-item/folder-item.tsx | 5 + .../workflow-item/workflow-item.tsx | 6 + apps/sim/blocks/blocks/linkedin.ts | 112 ++++ apps/sim/blocks/blocks/mailgun.ts | 293 +++++++++++ apps/sim/blocks/blocks/sendgrid.ts | 478 ++++++++++++++++++ apps/sim/blocks/blocks/smtp.ts | 209 ++++++++ apps/sim/blocks/registry.ts | 8 + apps/sim/components/icons.tsx | 94 +++- apps/sim/lib/auth.ts | 49 ++ apps/sim/lib/env.ts | 2 + apps/sim/lib/oauth/oauth.ts | 33 ++ apps/sim/tools/linkedin/get_profile.ts | 56 ++ apps/sim/tools/linkedin/index.ts | 2 + apps/sim/tools/linkedin/share_post.ts | 157 ++++++ apps/sim/tools/linkedin/types.ts | 89 ++++ apps/sim/tools/mailchimp/add_member.ts | 6 +- .../tools/mailchimp/add_or_update_member.ts | 6 +- .../sim/tools/mailchimp/add_segment_member.ts | 4 +- .../mailchimp/add_subscriber_to_automation.ts | 3 +- apps/sim/tools/mailchimp/create_audience.ts | 5 +- .../tools/mailchimp/create_batch_operation.ts | 3 +- apps/sim/tools/mailchimp/create_campaign.ts | 6 +- apps/sim/tools/mailchimp/create_interest.ts | 3 +- .../mailchimp/create_interest_category.ts | 3 +- .../tools/mailchimp/create_landing_page.ts | 5 +- .../sim/tools/mailchimp/create_merge_field.ts | 3 +- apps/sim/tools/mailchimp/create_segment.ts | 5 +- apps/sim/tools/mailchimp/get_audience.ts | 3 +- apps/sim/tools/mailchimp/get_audiences.ts | 3 +- apps/sim/tools/mailchimp/get_automation.ts | 3 +- apps/sim/tools/mailchimp/get_automations.ts | 3 +- .../tools/mailchimp/get_batch_operation.ts | 3 +- .../tools/mailchimp/get_batch_operations.ts | 3 +- apps/sim/tools/mailchimp/get_campaign.ts | 4 +- .../tools/mailchimp/get_campaign_content.ts | 4 +- .../tools/mailchimp/get_campaign_report.ts | 4 +- .../tools/mailchimp/get_campaign_reports.ts | 4 +- apps/sim/tools/mailchimp/get_campaigns.ts | 4 +- apps/sim/tools/mailchimp/get_interest.ts | 3 +- .../tools/mailchimp/get_interest_category.ts | 3 +- apps/sim/tools/mailchimp/get_landing_page.ts | 3 +- apps/sim/tools/mailchimp/get_landing_pages.ts | 3 +- apps/sim/tools/mailchimp/get_member.ts | 4 +- apps/sim/tools/mailchimp/get_member_tags.ts | 4 +- apps/sim/tools/mailchimp/get_members.ts | 4 +- apps/sim/tools/mailchimp/get_merge_fields.ts | 3 +- apps/sim/tools/mailchimp/get_segment.ts | 3 +- .../tools/mailchimp/get_segment_members.ts | 3 +- apps/sim/tools/mailchimp/get_template.ts | 3 +- apps/sim/tools/mailchimp/get_templates.ts | 3 +- .../tools/mailchimp/set_campaign_content.ts | 6 +- apps/sim/tools/mailchimp/types.ts | 373 +++++++++++++- apps/sim/tools/mailchimp/unarchive_member.ts | 4 +- apps/sim/tools/mailchimp/update_audience.ts | 5 +- apps/sim/tools/mailchimp/update_campaign.ts | 6 +- apps/sim/tools/mailchimp/update_interest.ts | 5 +- .../mailchimp/update_interest_category.ts | 5 +- .../tools/mailchimp/update_landing_page.ts | 5 +- apps/sim/tools/mailchimp/update_member.ts | 6 +- .../sim/tools/mailchimp/update_merge_field.ts | 5 +- apps/sim/tools/mailchimp/update_segment.ts | 5 +- apps/sim/tools/mailchimp/update_template.ts | 5 +- apps/sim/tools/mailgun/add_list_member.ts | 101 ++++ apps/sim/tools/mailgun/create_mailing_list.ts | 99 ++++ apps/sim/tools/mailgun/get_domain.ts | 62 +++ apps/sim/tools/mailgun/get_mailing_list.ts | 61 +++ apps/sim/tools/mailgun/get_message.ts | 83 +++ apps/sim/tools/mailgun/index.ts | 11 + apps/sim/tools/mailgun/list_domains.ts | 50 ++ apps/sim/tools/mailgun/list_messages.ts | 81 +++ apps/sim/tools/mailgun/send_message.ts | 129 +++++ apps/sim/tools/mailgun/types.ts | 201 ++++++++ apps/sim/tools/registry.ts | 57 +++ apps/sim/tools/sendgrid/add_contact.ts | 118 +++++ .../tools/sendgrid/add_contacts_to_list.ts | 74 +++ apps/sim/tools/sendgrid/create_list.ts | 64 +++ apps/sim/tools/sendgrid/create_template.ts | 75 +++ .../tools/sendgrid/create_template_version.ts | 121 +++++ apps/sim/tools/sendgrid/delete_contacts.ts | 58 +++ apps/sim/tools/sendgrid/delete_list.ts | 51 ++ apps/sim/tools/sendgrid/delete_template.ts | 46 ++ apps/sim/tools/sendgrid/get_contact.ts | 66 +++ apps/sim/tools/sendgrid/get_list.ts | 56 ++ apps/sim/tools/sendgrid/get_template.ts | 60 +++ apps/sim/tools/sendgrid/index.ts | 23 + apps/sim/tools/sendgrid/list_all_lists.ts | 58 +++ apps/sim/tools/sendgrid/list_templates.ts | 70 +++ .../sendgrid/remove_contacts_from_list.ts | 67 +++ apps/sim/tools/sendgrid/search_contacts.ts | 66 +++ apps/sim/tools/sendgrid/send_mail.ts | 212 ++++++++ apps/sim/tools/sendgrid/types.ts | 270 ++++++++++ apps/sim/tools/smtp/index.ts | 2 + apps/sim/tools/smtp/send_mail.ts | 177 +++++++ apps/sim/tools/smtp/types.ts | 34 ++ bun.lock | 440 ++++++++++++++++ package.json | 2 + 107 files changed, 6379 insertions(+), 127 deletions(-) create mode 100644 apps/docs/content/docs/en/tools/linkedin.mdx create mode 100644 apps/docs/content/docs/en/tools/mailgun.mdx create mode 100644 apps/docs/content/docs/en/tools/sendgrid.mdx create mode 100644 apps/docs/content/docs/en/tools/smtp.mdx create mode 100644 apps/sim/app/api/tools/smtp/send/route.ts create mode 100644 apps/sim/blocks/blocks/linkedin.ts create mode 100644 apps/sim/blocks/blocks/mailgun.ts create mode 100644 apps/sim/blocks/blocks/sendgrid.ts create mode 100644 apps/sim/blocks/blocks/smtp.ts create mode 100644 apps/sim/tools/linkedin/get_profile.ts create mode 100644 apps/sim/tools/linkedin/index.ts create mode 100644 apps/sim/tools/linkedin/share_post.ts create mode 100644 apps/sim/tools/linkedin/types.ts create mode 100644 apps/sim/tools/mailgun/add_list_member.ts create mode 100644 apps/sim/tools/mailgun/create_mailing_list.ts create mode 100644 apps/sim/tools/mailgun/get_domain.ts create mode 100644 apps/sim/tools/mailgun/get_mailing_list.ts create mode 100644 apps/sim/tools/mailgun/get_message.ts create mode 100644 apps/sim/tools/mailgun/index.ts create mode 100644 apps/sim/tools/mailgun/list_domains.ts create mode 100644 apps/sim/tools/mailgun/list_messages.ts create mode 100644 apps/sim/tools/mailgun/send_message.ts create mode 100644 apps/sim/tools/mailgun/types.ts create mode 100644 apps/sim/tools/sendgrid/add_contact.ts create mode 100644 apps/sim/tools/sendgrid/add_contacts_to_list.ts create mode 100644 apps/sim/tools/sendgrid/create_list.ts create mode 100644 apps/sim/tools/sendgrid/create_template.ts create mode 100644 apps/sim/tools/sendgrid/create_template_version.ts create mode 100644 apps/sim/tools/sendgrid/delete_contacts.ts create mode 100644 apps/sim/tools/sendgrid/delete_list.ts create mode 100644 apps/sim/tools/sendgrid/delete_template.ts create mode 100644 apps/sim/tools/sendgrid/get_contact.ts create mode 100644 apps/sim/tools/sendgrid/get_list.ts create mode 100644 apps/sim/tools/sendgrid/get_template.ts create mode 100644 apps/sim/tools/sendgrid/index.ts create mode 100644 apps/sim/tools/sendgrid/list_all_lists.ts create mode 100644 apps/sim/tools/sendgrid/list_templates.ts create mode 100644 apps/sim/tools/sendgrid/remove_contacts_from_list.ts create mode 100644 apps/sim/tools/sendgrid/search_contacts.ts create mode 100644 apps/sim/tools/sendgrid/send_mail.ts create mode 100644 apps/sim/tools/sendgrid/types.ts create mode 100644 apps/sim/tools/smtp/index.ts create mode 100644 apps/sim/tools/smtp/send_mail.ts create mode 100644 apps/sim/tools/smtp/types.ts diff --git a/apps/docs/components/icons.tsx b/apps/docs/components/icons.tsx index 3c70935669..c848e36eb6 100644 --- a/apps/docs/components/icons.tsx +++ b/apps/docs/components/icons.tsx @@ -1464,11 +1464,17 @@ export function DiscordIcon(props: SVGProps) { export function LinkedInIcon(props: SVGProps) { return ( - - + + + + + ) } @@ -4344,3 +4350,81 @@ export function PylonIcon(props: SVGProps) { ) } + +export function SendgridIcon(props: SVGProps) { + return ( + + + + + + + + + + + ) +} + +export function MailgunIcon(props: SVGProps) { + return ( + + + + ) +} + +export function SmtpIcon(props: SVGProps) { + return ( + + + + + ) +} diff --git a/apps/docs/components/ui/icon-mapping.ts b/apps/docs/components/ui/icon-mapping.ts index ad748928c5..3ace0e3907 100644 --- a/apps/docs/components/ui/icon-mapping.ts +++ b/apps/docs/components/ui/icon-mapping.ts @@ -37,8 +37,10 @@ import { JinaAIIcon, JiraIcon, LinearIcon, + LinkedInIcon, LinkupIcon, MailchimpIcon, + MailgunIcon, Mem0Icon, MicrosoftExcelIcon, MicrosoftOneDriveIcon, @@ -65,9 +67,11 @@ import { ResendIcon, S3Icon, SalesforceIcon, + SendgridIcon, SentryIcon, SerperIcon, SlackIcon, + SmtpIcon, STTIcon, StagehandIcon, StripeIcon, @@ -117,10 +121,12 @@ export const blockTypeToIconMap: Record = { stripe: StripeIcon, stagehand_agent: StagehandIcon, stagehand: StagehandIcon, + smtp: SmtpIcon, slack: SlackIcon, sharepoint: MicrosoftSharepointIcon, serper: SerperIcon, sentry: SentryIcon, + sendgrid: SendgridIcon, salesforce: SalesforceIcon, s3: S3Icon, resend: ResendIcon, @@ -146,8 +152,10 @@ export const blockTypeToIconMap: Record = { microsoft_excel: MicrosoftExcelIcon, memory: BrainIcon, mem0: Mem0Icon, + mailgun: MailgunIcon, mailchimp: MailchimpIcon, linkup: LinkupIcon, + linkedin: LinkedInIcon, linear: LinearIcon, knowledge: PackageSearchIcon, jira: JiraIcon, diff --git a/apps/docs/content/docs/en/tools/linkedin.mdx b/apps/docs/content/docs/en/tools/linkedin.mdx new file mode 100644 index 0000000000..78d5374357 --- /dev/null +++ b/apps/docs/content/docs/en/tools/linkedin.mdx @@ -0,0 +1,88 @@ +--- +title: LinkedIn +description: Share posts and manage your LinkedIn presence +--- + +import { BlockInfoCard } from "@/components/ui/block-info-card" + + + +{/* MANUAL-CONTENT-START:intro */} +[LinkedIn](https://www.linkedin.com) is the world’s largest professional networking platform, empowering users to build their careers, connect with their network, and share professional content. LinkedIn is widely used by professionals across industries for personal branding, recruiting, job search, and business development. + +With LinkedIn, you can easily share posts to your personal feed to engage with your network, and access information about your profile to highlight your professional achievements. Automated integration with Sim allows you to leverage LinkedIn functionality programmatically—enabling agents and workflows to post updates, report on your professional presence, and keep your feed active without manual effort. + +Key LinkedIn features available through this integration include: + +- **Share Posts:** Automatically publish professional updates, articles, or announcements to your LinkedIn personal feed. +- **Profile Information:** Retrieve detailed information about your LinkedIn profile to monitor or use in downstream tasks within your workflows. + +These capabilities make it easy to keep your LinkedIn network engaged and to extend your professional reach efficiently as part of your AI or workflow automation strategy. +{/* MANUAL-CONTENT-END */} + + +## Usage Instructions + +Integrate LinkedIn into workflows. Share posts to your personal feed and access your LinkedIn profile information. + + + +## Tools + +### `linkedin_share_post` + +Share a post to your personal LinkedIn feed + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `text` | string | Yes | The text content of your LinkedIn post | +| `visibility` | string | No | Who can see this post: "PUBLIC" or "CONNECTIONS" \(default: "PUBLIC"\) | +| `request` | string | No | No description | +| `output` | string | No | No description | +| `output` | string | No | No description | +| `specificContent` | string | No | No description | +| `shareCommentary` | string | No | No description | +| `visibility` | string | No | No description | +| `headers` | string | No | No description | +| `output` | string | No | No description | +| `output` | string | No | No description | +| `output` | string | No | No description | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `success` | boolean | Operation success status | +| `postId` | string | Created post ID | +| `profile` | json | LinkedIn profile information | +| `error` | string | Error message if operation failed | + +### `linkedin_get_profile` + +Retrieve your LinkedIn profile information + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `success` | boolean | Operation success status | +| `postId` | string | Created post ID | +| `profile` | json | LinkedIn profile information | +| `error` | string | Error message if operation failed | + + + +## Notes + +- Category: `tools` +- Type: `linkedin` diff --git a/apps/docs/content/docs/en/tools/mailgun.mdx b/apps/docs/content/docs/en/tools/mailgun.mdx new file mode 100644 index 0000000000..450576219a --- /dev/null +++ b/apps/docs/content/docs/en/tools/mailgun.mdx @@ -0,0 +1,221 @@ +--- +title: Mailgun +description: Send emails and manage mailing lists with Mailgun +--- + +import { BlockInfoCard } from "@/components/ui/block-info-card" + + + +{/* MANUAL-CONTENT-START:intro */} +[Mailgun](https://www.mailgun.com) is a powerful email delivery service designed for developers and businesses to send, receive, and track emails effortlessly. Mailgun enables you to leverage robust APIs for reliable transactional and marketing email, flexible mailing list management, and advanced event tracking. + +With Mailgun's comprehensive feature set, you can automate key email operations and closely monitor deliverability and recipient engagement. This makes it an ideal solution for workflow automation where communications, notifications, and campaign mails are core parts of your processes. + +Key features of Mailgun include: + +- **Transactional Email Sending:** Deliver high-volume emails such as account notifications, receipts, alerts, and password resets. +- **Rich Email Content:** Send both plain text and HTML emails, and use tags for categorizing and tracking your messages. +- **Mailing List Management:** Create, update, and manage mailing lists and members to send grouped communications efficiently. +- **Domain Information:** Retrieve details about your sending domains to monitor configuration and health. +- **Event Tracking:** Analyze email deliverability and engagement with detailed event data on sent messages. +- **Message Retrieval:** Access stored messages for compliance, analysis, or troubleshooting needs. + +By integrating Mailgun into Sim, your agents are empowered to programmatically send emails, manage email lists, access domain information, and monitor real-time events as part of automated workflows. This allows for intelligent, data-driven engagement with your users directly from your AI-powered processes. +{/* MANUAL-CONTENT-END */} + + +## Usage Instructions + +Integrate Mailgun into your workflow. Send transactional emails, manage mailing lists and members, view domain information, and track email events. Supports text and HTML emails, tags for tracking, and comprehensive list management. + + + +## Tools + +### `mailgun_send_message` + +Send an email using Mailgun API + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Mailgun API key | +| `domain` | string | Yes | Mailgun domain \(e.g., mg.example.com\) | +| `from` | string | Yes | Sender email address | +| `to` | string | Yes | Recipient email address \(comma-separated for multiple\) | +| `subject` | string | Yes | Email subject | +| `text` | string | No | Plain text body of the email | +| `html` | string | No | HTML body of the email | +| `cc` | string | No | CC email address \(comma-separated for multiple\) | +| `bcc` | string | No | BCC email address \(comma-separated for multiple\) | +| `tags` | string | No | Tags for the email \(comma-separated\) | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `success` | boolean | Whether the message was sent successfully | +| `id` | string | Message ID | +| `message` | string | Response message from Mailgun | + +### `mailgun_get_message` + +Retrieve a stored message by its key + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Mailgun API key | +| `domain` | string | Yes | Mailgun domain | +| `messageKey` | string | Yes | Message storage key | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `success` | boolean | Whether the request was successful | +| `recipients` | string | Message recipients | +| `from` | string | Sender email | +| `subject` | string | Message subject | +| `bodyPlain` | string | Plain text body | +| `strippedText` | string | Stripped text | +| `strippedSignature` | string | Stripped signature | +| `bodyHtml` | string | HTML body | +| `strippedHtml` | string | Stripped HTML | +| `attachmentCount` | number | Number of attachments | +| `timestamp` | number | Message timestamp | +| `messageHeaders` | json | Message headers | +| `contentIdMap` | json | Content ID map | + +### `mailgun_list_messages` + +List events (logs) for messages sent through Mailgun + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Mailgun API key | +| `domain` | string | Yes | Mailgun domain | +| `event` | string | No | Filter by event type \(accepted, delivered, failed, opened, clicked, etc.\) | +| `limit` | number | No | Maximum number of events to return \(default: 100\) | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `success` | boolean | Whether the request was successful | +| `items` | json | Array of event items | +| `paging` | json | Paging information | + +### `mailgun_create_mailing_list` + +Create a new mailing list + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Mailgun API key | +| `address` | string | Yes | Mailing list address \(e.g., list@example.com\) | +| `name` | string | No | Mailing list name | +| `description` | string | No | Mailing list description | +| `accessLevel` | string | No | Access level: readonly, members, or everyone | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `success` | boolean | Whether the list was created successfully | +| `message` | string | Response message | +| `list` | json | Created mailing list details | + +### `mailgun_get_mailing_list` + +Get details of a mailing list + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Mailgun API key | +| `address` | string | Yes | Mailing list address | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `success` | boolean | Whether the request was successful | +| `list` | json | Mailing list details | + +### `mailgun_add_list_member` + +Add a member to a mailing list + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Mailgun API key | +| `listAddress` | string | Yes | Mailing list address | +| `address` | string | Yes | Member email address | +| `name` | string | No | Member name | +| `vars` | string | No | JSON string of custom variables | +| `subscribed` | boolean | No | Whether the member is subscribed | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `success` | boolean | Whether the member was added successfully | +| `message` | string | Response message | +| `member` | json | Added member details | + +### `mailgun_list_domains` + +List all domains for your Mailgun account + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Mailgun API key | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `success` | boolean | Whether the request was successful | +| `totalCount` | number | Total number of domains | +| `items` | json | Array of domain objects | + +### `mailgun_get_domain` + +Get details of a specific domain + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Mailgun API key | +| `domain` | string | Yes | Domain name | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `success` | boolean | Whether the request was successful | +| `domain` | json | Domain details | + + + +## Notes + +- Category: `tools` +- Type: `mailgun` diff --git a/apps/docs/content/docs/en/tools/meta.json b/apps/docs/content/docs/en/tools/meta.json index 6f83cb4500..e8a4b7478a 100644 --- a/apps/docs/content/docs/en/tools/meta.json +++ b/apps/docs/content/docs/en/tools/meta.json @@ -33,8 +33,10 @@ "jira", "knowledge", "linear", + "linkedin", "linkup", "mailchimp", + "mailgun", "mem0", "memory", "microsoft_excel", @@ -60,10 +62,12 @@ "resend", "s3", "salesforce", + "sendgrid", "sentry", "serper", "sharepoint", "slack", + "smtp", "stagehand", "stagehand_agent", "stripe", diff --git a/apps/docs/content/docs/en/tools/sendgrid.mdx b/apps/docs/content/docs/en/tools/sendgrid.mdx new file mode 100644 index 0000000000..6bff00fae3 --- /dev/null +++ b/apps/docs/content/docs/en/tools/sendgrid.mdx @@ -0,0 +1,396 @@ +--- +title: SendGrid +description: Send emails and manage contacts, lists, and templates with SendGrid +--- + +import { BlockInfoCard } from "@/components/ui/block-info-card" + + + +{/* MANUAL-CONTENT-START:intro */} +[SendGrid](https://sendgrid.com) is a leading cloud-based email delivery platform trusted by developers and businesses to send reliable transactional and marketing emails at scale. With its robust APIs and powerful tools, SendGrid enables you to manage all aspects of your email communication, from sending notifications and receipts to managing complex marketing campaigns. + +SendGrid empowers users with a full suite of email operations, allowing you to automate critical email workflows and closely manage contact lists, templates, and recipient engagement. Its seamless integration with Sim enables agents and workflows to deliver targeted messages, maintain dynamic contact and recipient lists, trigger personalized emails through templates, and track the results in real time. + +Key features of SendGrid include: + +- **Transactional Email:** Send automated and high-volume transactional emails (like notifications, receipts, and password resets). +- **Dynamic Templates:** Use rich HTML or text templates with dynamic data for highly personalized communication at scale. +- **Contact Management:** Add and update marketing contacts, manage recipient lists, and target segments for campaigns. +- **Attachments Support:** Include one or more file attachments in your emails. +- **Comprehensive API Coverage:** Programmatically manage emails, contacts, lists, templates, suppression groups, and more. + +By connecting SendGrid with Sim, your agents can: + +- Send both simple and advanced (templated or multi-recipient) emails as part of any workflow. +- Manage and segment contacts and lists automatically. +- Leverage templates for consistency and dynamic personalization. +- Track and respond to email engagement within your automated processes. + +This integration allows you to automate all critical communication flows, ensure messages reach the right audience, and maintain control over your organization’s email strategy, directly from Sim workflows. +{/* MANUAL-CONTENT-END */} + + +## Usage Instructions + +Integrate SendGrid into your workflow. Send transactional emails, manage marketing contacts and lists, and work with email templates. Supports dynamic templates, attachments, and comprehensive contact management. + + + +## Tools + +### `sendgrid_send_mail` + +Send an email using SendGrid API + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | SendGrid API key | +| `from` | string | Yes | Sender email address \(must be verified in SendGrid\) | +| `fromName` | string | No | Sender name | +| `to` | string | Yes | Recipient email address | +| `toName` | string | No | Recipient name | +| `subject` | string | No | Email subject \(required unless using a template with pre-defined subject\) | +| `content` | string | No | Email body content \(required unless using a template with pre-defined content\) | +| `contentType` | string | No | Content type \(text/plain or text/html\) | +| `cc` | string | No | CC email address | +| `bcc` | string | No | BCC email address | +| `replyTo` | string | No | Reply-to email address | +| `replyToName` | string | No | Reply-to name | +| `attachments` | file[] | No | Files to attach to the email | +| `templateId` | string | No | SendGrid template ID to use | +| `dynamicTemplateData` | json | No | JSON object of dynamic template data | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `success` | boolean | Whether the email was sent successfully | +| `messageId` | string | SendGrid message ID | +| `to` | string | Recipient email address | +| `subject` | string | Email subject | + +### `sendgrid_add_contact` + +Add a new contact to SendGrid + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | SendGrid API key | +| `email` | string | Yes | Contact email address | +| `firstName` | string | No | Contact first name | +| `lastName` | string | No | Contact last name | +| `customFields` | json | No | JSON object of custom field key-value pairs \(use field IDs like e1_T, e2_N, e3_D, not field names\) | +| `listIds` | string | No | Comma-separated list IDs to add the contact to | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `jobId` | string | Job ID for tracking the async contact creation | +| `email` | string | Contact email address | +| `firstName` | string | Contact first name | +| `lastName` | string | Contact last name | +| `message` | string | Status message | + +### `sendgrid_get_contact` + +Get a specific contact by ID from SendGrid + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | SendGrid API key | +| `contactId` | string | Yes | Contact ID | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `id` | string | Contact ID | +| `email` | string | Contact email address | +| `firstName` | string | Contact first name | +| `lastName` | string | Contact last name | +| `createdAt` | string | Creation timestamp | +| `updatedAt` | string | Last update timestamp | +| `listIds` | json | Array of list IDs the contact belongs to | +| `customFields` | json | Custom field values | + +### `sendgrid_search_contacts` + +Search for contacts in SendGrid using a query + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | SendGrid API key | +| `query` | string | Yes | Search query \(e.g., \"email LIKE '%example.com%' AND CONTAINS\(list_ids, 'list-id'\)\"\) | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `contacts` | json | Array of matching contacts | +| `contactCount` | number | Total number of contacts found | + +### `sendgrid_delete_contacts` + +Delete one or more contacts from SendGrid + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | SendGrid API key | +| `contactIds` | string | Yes | Comma-separated contact IDs to delete | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `jobId` | string | Job ID for the deletion request | + +### `sendgrid_create_list` + +Create a new contact list in SendGrid + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | SendGrid API key | +| `name` | string | Yes | List name | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `id` | string | List ID | +| `name` | string | List name | +| `contactCount` | number | Number of contacts in the list | + +### `sendgrid_get_list` + +Get a specific list by ID from SendGrid + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | SendGrid API key | +| `listId` | string | Yes | List ID | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `id` | string | List ID | +| `name` | string | List name | +| `contactCount` | number | Number of contacts in the list | + +### `sendgrid_list_all_lists` + +Get all contact lists from SendGrid + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | SendGrid API key | +| `pageSize` | number | No | Number of lists to return per page \(default: 100\) | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `lists` | json | Array of lists | + +### `sendgrid_delete_list` + +Delete a contact list from SendGrid + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | SendGrid API key | +| `listId` | string | Yes | List ID to delete | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `message` | string | Success message | + +### `sendgrid_add_contacts_to_list` + +Add or update contacts and assign them to a list in SendGrid (uses PUT /v3/marketing/contacts) + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | SendGrid API key | +| `listId` | string | Yes | List ID to add contacts to | +| `contacts` | json | Yes | JSON array of contact objects. Each contact must have at least: email \(or phone_number_id/external_id/anonymous_id\). Example: \[\{"email": "user@example.com", "first_name": "John"\}\] | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `jobId` | string | Job ID for tracking the async operation | +| `message` | string | Status message | + +### `sendgrid_remove_contacts_from_list` + +Remove contacts from a specific list in SendGrid + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | SendGrid API key | +| `listId` | string | Yes | List ID | +| `contactIds` | string | Yes | Comma-separated contact IDs to remove from the list | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `jobId` | string | Job ID for the request | + +### `sendgrid_create_template` + +Create a new email template in SendGrid + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | SendGrid API key | +| `name` | string | Yes | Template name | +| `generation` | string | No | Template generation type \(legacy or dynamic, default: dynamic\) | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `id` | string | Template ID | +| `name` | string | Template name | +| `generation` | string | Template generation | +| `updatedAt` | string | Last update timestamp | +| `versions` | json | Array of template versions | + +### `sendgrid_get_template` + +Get a specific template by ID from SendGrid + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | SendGrid API key | +| `templateId` | string | Yes | Template ID | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `id` | string | Template ID | +| `name` | string | Template name | +| `generation` | string | Template generation | +| `updatedAt` | string | Last update timestamp | +| `versions` | json | Array of template versions | + +### `sendgrid_list_templates` + +Get all email templates from SendGrid + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | SendGrid API key | +| `generations` | string | No | Filter by generation \(legacy, dynamic, or both\) | +| `pageSize` | number | No | Number of templates to return per page \(default: 20\) | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `templates` | json | Array of templates | + +### `sendgrid_delete_template` + +Delete an email template from SendGrid + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | SendGrid API key | +| `templateId` | string | Yes | Template ID to delete | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `success` | boolean | Operation success status | +| `messageId` | string | Email message ID \(send_mail\) | +| `id` | string | Resource ID | +| `jobId` | string | Job ID for async operations | +| `email` | string | Email address | +| `firstName` | string | First name | +| `lastName` | string | Last name | +| `contacts` | json | Array of contacts | +| `contactCount` | number | Number of contacts | +| `lists` | json | Array of lists | +| `templates` | json | Array of templates | +| `message` | string | Status or success message | +| `name` | string | Resource name | +| `generation` | string | Template generation | + +### `sendgrid_create_template_version` + +Create a new version of an email template in SendGrid + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | SendGrid API key | +| `templateId` | string | Yes | Template ID | +| `name` | string | Yes | Version name | +| `subject` | string | Yes | Email subject line | +| `htmlContent` | string | No | HTML content of the template | +| `plainContent` | string | No | Plain text content of the template | +| `active` | boolean | No | Whether this version is active \(default: true\) | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `id` | string | Version ID | +| `templateId` | string | Template ID | +| `name` | string | Version name | +| `subject` | string | Email subject | +| `active` | boolean | Whether this version is active | +| `htmlContent` | string | HTML content | +| `plainContent` | string | Plain text content | +| `updatedAt` | string | Last update timestamp | + + + +## Notes + +- Category: `tools` +- Type: `sendgrid` diff --git a/apps/docs/content/docs/en/tools/smtp.mdx b/apps/docs/content/docs/en/tools/smtp.mdx new file mode 100644 index 0000000000..5c7197fc55 --- /dev/null +++ b/apps/docs/content/docs/en/tools/smtp.mdx @@ -0,0 +1,78 @@ +--- +title: SMTP +description: Send emails via any SMTP mail server +--- + +import { BlockInfoCard } from "@/components/ui/block-info-card" + + + +{/* MANUAL-CONTENT-START:intro */} +[SMTP (Simple Mail Transfer Protocol)](https://en.wikipedia.org/wiki/Simple_Mail_Transfer_Protocol) is the foundational standard for email transmission across the Internet. By connecting to any SMTP-compatible server—such as Gmail, Outlook, or your organization's own mail infrastructure—you can send emails programmatically and automate your outbound communications. + +SMTP integration allows you to fully customize email sending through direct server connectivity, supporting both basic and advanced email use cases. With SMTP, you can control every aspect of message delivery, recipient management, and content formatting, making it suitable for transactional notifications, bulk mailings, and any automated workflow requiring robust outbound email delivery. + +**Key features available via SMTP integration include:** + +- **Universal Email Delivery:** Send emails using any SMTP server by configuring standard server connection parameters. +- **Customizable Sender and Recipients:** Specify sender address, display name, primary recipients, as well as CC and BCC fields. +- **Rich Content Support:** Send plain text or richly formatted HTML emails according to your requirements. +- **Attachments:** Include multiple files as attachments in outgoing emails. +- **Flexible Security:** Connect using TLS, SSL, or standard (unencrypted) protocols as supported by your SMTP provider. +- **Advanced Headers:** Set reply-to headers and other advanced email options to cater for complex mailflows and user interactions. + +By integrating SMTP with Sim, agents and workflows can programmatically send emails as part of any automated process—ranging from sending notifications and confirmations, to automating external communications, reporting, and document delivery. This offers a highly flexible, provider-agnostic approach to managing email directly within your AI-driven processes. +{/* MANUAL-CONTENT-END */} + + +## Usage Instructions + +Send emails using any SMTP server (Gmail, Outlook, custom servers, etc.). Configure SMTP connection settings and send emails with full control over content, recipients, and attachments. + + + +## Tools + +### `smtp_send_mail` + +Send emails via SMTP server + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `smtpHost` | string | Yes | SMTP server hostname \(e.g., smtp.gmail.com\) | +| `smtpPort` | number | Yes | SMTP server port \(587 for TLS, 465 for SSL\) | +| `smtpUsername` | string | Yes | SMTP authentication username | +| `smtpPassword` | string | Yes | SMTP authentication password | +| `smtpSecure` | string | Yes | Security protocol \(TLS, SSL, or None\) | +| `from` | string | Yes | Sender email address | +| `to` | string | Yes | Recipient email address | +| `subject` | string | Yes | Email subject | +| `body` | string | Yes | Email body content | +| `contentType` | string | No | Content type \(text or html\) | +| `fromName` | string | No | Display name for sender | +| `cc` | string | No | CC recipients \(comma-separated\) | +| `bcc` | string | No | BCC recipients \(comma-separated\) | +| `replyTo` | string | No | Reply-to email address | +| `attachments` | file[] | No | Files to attach to the email | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `success` | boolean | Whether the email was sent successfully | +| `messageId` | string | Message ID from SMTP server | +| `to` | string | Recipient email address | +| `subject` | string | Email subject | +| `error` | string | Error message if sending failed | + + + +## Notes + +- Category: `tools` +- Type: `smtp` diff --git a/apps/sim/app/api/chat/[identifier]/route.test.ts b/apps/sim/app/api/chat/[identifier]/route.test.ts index f872e35ee6..c7cc5754e4 100644 --- a/apps/sim/app/api/chat/[identifier]/route.test.ts +++ b/apps/sim/app/api/chat/[identifier]/route.test.ts @@ -6,6 +6,23 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' import { createMockRequest } from '@/app/api/__test-utils__/utils' +const createMockStream = () => { + return new ReadableStream({ + start(controller) { + controller.enqueue( + new TextEncoder().encode('data: {"blockId":"agent-1","chunk":"Hello"}\n\n') + ) + controller.enqueue( + new TextEncoder().encode('data: {"blockId":"agent-1","chunk":" world"}\n\n') + ) + controller.enqueue( + new TextEncoder().encode('data: {"event":"final","data":{"success":true}}\n\n') + ) + controller.close() + }, + }) +} + vi.mock('@/lib/execution/preprocessing', () => ({ preprocessExecution: vi.fn().mockResolvedValue({ success: true, @@ -36,28 +53,37 @@ vi.mock('@/lib/logs/execution/logging-session', () => ({ })), })) -describe('Chat Identifier API Route', () => { - const createMockStream = () => { - return new ReadableStream({ - start(controller) { - controller.enqueue( - new TextEncoder().encode('data: {"blockId":"agent-1","chunk":"Hello"}\n\n') - ) - controller.enqueue( - new TextEncoder().encode('data: {"blockId":"agent-1","chunk":" world"}\n\n') - ) - controller.enqueue( - new TextEncoder().encode('data: {"event":"final","data":{"success":true}}\n\n') - ) - controller.close() - }, - }) - } +vi.mock('@/lib/workflows/streaming', () => ({ + createStreamingResponse: vi.fn().mockImplementation(async () => createMockStream()), +})) + +vi.mock('@/lib/utils', () => ({ + SSE_HEADERS: { + 'Content-Type': 'text/event-stream', + 'Cache-Control': 'no-cache', + Connection: 'keep-alive', + 'X-Accel-Buffering': 'no', + }, + generateRequestId: vi.fn().mockReturnValue('test-request-id'), +})) + +vi.mock('@/app/api/workflows/[id]/execute/route', () => ({ + createFilteredResult: vi.fn().mockImplementation((result: any) => ({ + ...result, + logs: undefined, + metadata: result.metadata + ? { + ...result.metadata, + workflowConnections: undefined, + } + : undefined, + })), +})) +describe('Chat Identifier API Route', () => { const mockAddCorsHeaders = vi.fn().mockImplementation((response) => response) const mockValidateChatAuth = vi.fn().mockResolvedValue({ authorized: true }) const mockSetChatAuthCookie = vi.fn() - const mockCreateStreamingResponse = vi.fn().mockResolvedValue(createMockStream()) const mockChatResult = [ { @@ -104,16 +130,6 @@ describe('Chat Identifier API Route', () => { validateAuthToken: vi.fn().mockReturnValue(true), })) - vi.doMock('@/lib/workflows/streaming', () => ({ - createStreamingResponse: mockCreateStreamingResponse, - SSE_HEADERS: { - 'Content-Type': 'text/event-stream', - 'Cache-Control': 'no-cache', - Connection: 'keep-alive', - 'X-Accel-Buffering': 'no', - }, - })) - vi.doMock('@/lib/logs/console/logger', () => ({ createLogger: vi.fn().mockReturnValue({ debug: vi.fn(), @@ -372,6 +388,7 @@ describe('Chat Identifier API Route', () => { const params = Promise.resolve({ identifier: 'test-chat' }) const { POST } = await import('@/app/api/chat/[identifier]/route') + const { createStreamingResponse } = await import('@/lib/workflows/streaming') const response = await POST(req, { params }) @@ -380,7 +397,7 @@ describe('Chat Identifier API Route', () => { expect(response.headers.get('Cache-Control')).toBe('no-cache') expect(response.headers.get('Connection')).toBe('keep-alive') - expect(mockCreateStreamingResponse).toHaveBeenCalledWith( + expect(createStreamingResponse).toHaveBeenCalledWith( expect.objectContaining({ workflow: expect.objectContaining({ id: 'workflow-id', @@ -396,7 +413,7 @@ describe('Chat Identifier API Route', () => { }), }) ) - }) + }, 10000) it('should handle streaming response body correctly', async () => { const req = createMockRequest('POST', { input: 'Hello world' }) @@ -423,8 +440,9 @@ describe('Chat Identifier API Route', () => { }) it('should handle workflow execution errors gracefully', async () => { - const originalStreamingResponse = mockCreateStreamingResponse.getMockImplementation() - mockCreateStreamingResponse.mockImplementationOnce(async () => { + const { createStreamingResponse } = await import('@/lib/workflows/streaming') + const originalStreamingResponse = vi.mocked(createStreamingResponse).getMockImplementation() + vi.mocked(createStreamingResponse).mockImplementationOnce(async () => { throw new Error('Execution failed') }) @@ -442,7 +460,7 @@ describe('Chat Identifier API Route', () => { expect(data).toHaveProperty('message', 'Execution failed') if (originalStreamingResponse) { - mockCreateStreamingResponse.mockImplementation(originalStreamingResponse) + vi.mocked(createStreamingResponse).mockImplementation(originalStreamingResponse) } }) @@ -474,10 +492,11 @@ describe('Chat Identifier API Route', () => { const params = Promise.resolve({ identifier: 'test-chat' }) const { POST } = await import('@/app/api/chat/[identifier]/route') + const { createStreamingResponse } = await import('@/lib/workflows/streaming') await POST(req, { params }) - expect(mockCreateStreamingResponse).toHaveBeenCalledWith( + expect(createStreamingResponse).toHaveBeenCalledWith( expect.objectContaining({ input: expect.objectContaining({ input: 'Hello world', @@ -492,10 +511,11 @@ describe('Chat Identifier API Route', () => { const params = Promise.resolve({ identifier: 'test-chat' }) const { POST } = await import('@/app/api/chat/[identifier]/route') + const { createStreamingResponse } = await import('@/lib/workflows/streaming') await POST(req, { params }) - expect(mockCreateStreamingResponse).toHaveBeenCalledWith( + expect(createStreamingResponse).toHaveBeenCalledWith( expect.objectContaining({ input: expect.objectContaining({ input: 'Hello world', diff --git a/apps/sim/app/api/tools/smtp/send/route.ts b/apps/sim/app/api/tools/smtp/send/route.ts new file mode 100644 index 0000000000..49c4eb9b13 --- /dev/null +++ b/apps/sim/app/api/tools/smtp/send/route.ts @@ -0,0 +1,227 @@ +import { type NextRequest, NextResponse } from 'next/server' +import nodemailer from 'nodemailer' +import { z } from 'zod' +import { checkHybridAuth } from '@/lib/auth/hybrid' +import { createLogger } from '@/lib/logs/console/logger' +import { processFilesToUserFiles } from '@/lib/uploads/utils/file-utils' +import { downloadFileFromStorage } from '@/lib/uploads/utils/file-utils.server' +import { generateRequestId } from '@/lib/utils' + +export const dynamic = 'force-dynamic' + +const logger = createLogger('SmtpSendAPI') + +const SmtpSendSchema = z.object({ + smtpHost: z.string().min(1, 'SMTP host is required'), + smtpPort: z.number().min(1).max(65535, 'Port must be between 1 and 65535'), + smtpUsername: z.string().min(1, 'SMTP username is required'), + smtpPassword: z.string().min(1, 'SMTP password is required'), + smtpSecure: z.enum(['TLS', 'SSL', 'None']), + + from: z.string().email('Invalid from email address').min(1, 'From address is required'), + to: z.string().min(1, 'To email is required'), + subject: z.string().min(1, 'Subject is required'), + body: z.string().min(1, 'Email body is required'), + contentType: z.enum(['text', 'html']).optional().nullable(), + + fromName: z.string().optional().nullable(), + cc: z.string().optional().nullable(), + bcc: z.string().optional().nullable(), + replyTo: z.string().optional().nullable(), + attachments: z.array(z.any()).optional().nullable(), +}) + +export async function POST(request: NextRequest) { + const requestId = generateRequestId() + + try { + const authResult = await checkHybridAuth(request, { requireWorkflowId: false }) + + if (!authResult.success) { + logger.warn(`[${requestId}] Unauthorized SMTP send attempt: ${authResult.error}`) + return NextResponse.json( + { + success: false, + error: authResult.error || 'Authentication required', + }, + { status: 401 } + ) + } + + logger.info(`[${requestId}] Authenticated SMTP request via ${authResult.authType}`, { + userId: authResult.userId, + }) + + const body = await request.json() + const validatedData = SmtpSendSchema.parse(body) + + logger.info(`[${requestId}] Sending email via SMTP`, { + host: validatedData.smtpHost, + port: validatedData.smtpPort, + to: validatedData.to, + subject: validatedData.subject, + secure: validatedData.smtpSecure, + }) + + const transporter = nodemailer.createTransport({ + host: validatedData.smtpHost, + port: validatedData.smtpPort, + secure: validatedData.smtpSecure === 'SSL', + auth: { + user: validatedData.smtpUsername, + pass: validatedData.smtpPassword, + }, + tls: + validatedData.smtpSecure === 'None' + ? { + rejectUnauthorized: false, + } + : { + rejectUnauthorized: true, + }, + }) + + const contentType = validatedData.contentType || 'text' + const fromAddress = validatedData.fromName + ? `"${validatedData.fromName}" <${validatedData.from}>` + : validatedData.from + + const mailOptions: nodemailer.SendMailOptions = { + from: fromAddress, + to: validatedData.to, + subject: validatedData.subject, + [contentType === 'html' ? 'html' : 'text']: validatedData.body, + } + + if (validatedData.cc) { + mailOptions.cc = validatedData.cc + } + if (validatedData.bcc) { + mailOptions.bcc = validatedData.bcc + } + if (validatedData.replyTo) { + mailOptions.replyTo = validatedData.replyTo + } + + if (validatedData.attachments && validatedData.attachments.length > 0) { + const rawAttachments = validatedData.attachments + logger.info(`[${requestId}] Processing ${rawAttachments.length} attachment(s)`) + + const attachments = processFilesToUserFiles(rawAttachments, requestId, logger) + + if (attachments.length > 0) { + const totalSize = attachments.reduce((sum, file) => sum + file.size, 0) + const maxSize = 25 * 1024 * 1024 + + if (totalSize > maxSize) { + const sizeMB = (totalSize / (1024 * 1024)).toFixed(2) + return NextResponse.json( + { + success: false, + error: `Total attachment size (${sizeMB}MB) exceeds SMTP limit of 25MB`, + }, + { status: 400 } + ) + } + + const attachmentBuffers = await Promise.all( + attachments.map(async (file) => { + try { + logger.info( + `[${requestId}] Downloading attachment: ${file.name} (${file.size} bytes)` + ) + + const buffer = await downloadFileFromStorage(file, requestId, logger) + + return { + filename: file.name, + content: buffer, + contentType: file.type || 'application/octet-stream', + } + } catch (error) { + logger.error(`[${requestId}] Failed to download attachment ${file.name}:`, error) + throw new Error( + `Failed to download attachment "${file.name}": ${error instanceof Error ? error.message : 'Unknown error'}` + ) + } + }) + ) + + logger.info(`[${requestId}] Processed ${attachmentBuffers.length} attachment(s)`) + mailOptions.attachments = attachmentBuffers + } + } + + const result = await transporter.sendMail(mailOptions) + + logger.info(`[${requestId}] Email sent successfully via SMTP`, { + messageId: result.messageId, + to: validatedData.to, + }) + + return NextResponse.json({ + success: true, + messageId: result.messageId, + to: validatedData.to, + subject: validatedData.subject, + }) + } catch (error: unknown) { + if (error instanceof z.ZodError) { + logger.warn(`[${requestId}] Invalid request data`, { errors: error.errors }) + return NextResponse.json( + { + success: false, + error: 'Invalid request data', + details: error.errors, + }, + { status: 400 } + ) + } + + // Type guard for error objects with code property + const isNodeError = (err: unknown): err is NodeJS.ErrnoException => { + return err instanceof Error && 'code' in err + } + + let errorMessage = 'Failed to send email via SMTP' + + if (isNodeError(error)) { + if (error.code === 'EAUTH') { + errorMessage = 'SMTP authentication failed - check username and password' + } else if (error.code === 'ECONNECTION' || error.code === 'ECONNREFUSED') { + errorMessage = 'Could not connect to SMTP server - check host and port' + } else if (error.code === 'ECONNRESET') { + errorMessage = 'Connection was reset by SMTP server' + } else if (error.code === 'ETIMEDOUT') { + errorMessage = 'SMTP server connection timeout' + } + } + + // Check for SMTP response codes + const hasResponseCode = (err: unknown): err is { responseCode: number } => { + return typeof err === 'object' && err !== null && 'responseCode' in err + } + + if (hasResponseCode(error)) { + if (error.responseCode >= 500) { + errorMessage = 'SMTP server error - please try again later' + } else if (error.responseCode >= 400) { + errorMessage = 'Email rejected by SMTP server - check recipient addresses' + } + } + + logger.error(`[${requestId}] Error sending email via SMTP:`, { + error: error instanceof Error ? error.message : String(error), + code: isNodeError(error) ? error.code : undefined, + responseCode: hasResponseCode(error) ? error.responseCode : undefined, + }) + + return NextResponse.json( + { + success: false, + error: errorMessage, + }, + { status: 500 } + ) + } +} diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/credential-selector/components/oauth-required-modal.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/credential-selector/components/oauth-required-modal.tsx index 34530ab9c0..21b3892423 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/credential-selector/components/oauth-required-modal.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/credential-selector/components/oauth-required-modal.tsx @@ -231,6 +231,7 @@ const SCOPE_DESCRIPTIONS: Record = { 'projects:full': 'Full access to manage your Pipedrive projects', 'webhooks:read': 'Read your Pipedrive webhooks', 'webhooks:full': 'Full access to manage your Pipedrive webhooks', + w_member_social: 'Access your LinkedIn profile', } function getScopeDescription(scope: string): string { diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/panel.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/panel.tsx index 8f2ed8bea0..bee0688e43 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/panel.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/panel.tsx @@ -411,7 +411,7 @@ export function Panel() { */} Export workflow diff --git a/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components-new/workflow-list/components/folder-item/folder-item.tsx b/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components-new/workflow-list/components/folder-item/folder-item.tsx index 1cf02a1453..3eedbf4059 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components-new/workflow-list/components/folder-item/folder-item.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components-new/workflow-list/components/folder-item/folder-item.tsx @@ -4,6 +4,7 @@ import { useCallback, useState } from 'react' import clsx from 'clsx' import { ChevronRight, Folder, FolderOpen } from 'lucide-react' import { useParams, useRouter } from 'next/navigation' +import { useUserPermissionsContext } from '@/app/workspace/[workspaceId]/providers/workspace-permissions-provider' import { ContextMenu } from '@/app/workspace/[workspaceId]/w/components/sidebar/components-new/workflow-list/components/context-menu/context-menu' import { DeleteModal } from '@/app/workspace/[workspaceId]/w/components/sidebar/components-new/workflow-list/components/delete-modal/delete-modal' import { @@ -40,6 +41,7 @@ export function FolderItem({ folder, level, hoverHandlers }: FolderItemProps) { const workspaceId = params.workspaceId as string const updateFolderMutation = useUpdateFolder() const createWorkflowMutation = useCreateWorkflow() + const userPermissions = useUserPermissionsContext() // Delete modal state const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false) @@ -260,6 +262,9 @@ export function FolderItem({ folder, level, hoverHandlers }: FolderItemProps) { onDuplicate={handleDuplicateFolder} onDelete={() => setIsDeleteModalOpen(true)} showCreate={true} + disableRename={!userPermissions.canEdit} + disableDuplicate={!userPermissions.canEdit} + disableDelete={!userPermissions.canEdit} /> {/* Delete Modal */} diff --git a/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components-new/workflow-list/components/workflow-item/workflow-item.tsx b/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components-new/workflow-list/components/workflow-item/workflow-item.tsx index f559033757..5e272d8e64 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components-new/workflow-list/components/workflow-item/workflow-item.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components-new/workflow-list/components/workflow-item/workflow-item.tsx @@ -4,6 +4,7 @@ import { useCallback, useRef, useState } from 'react' import clsx from 'clsx' import Link from 'next/link' import { useParams } from 'next/navigation' +import { useUserPermissionsContext } from '@/app/workspace/[workspaceId]/providers/workspace-permissions-provider' import { ContextMenu } from '@/app/workspace/[workspaceId]/w/components/sidebar/components-new/workflow-list/components/context-menu/context-menu' import { DeleteModal } from '@/app/workspace/[workspaceId]/w/components/sidebar/components-new/workflow-list/components/delete-modal/delete-modal' import { Avatars } from '@/app/workspace/[workspaceId]/w/components/sidebar/components-new/workflow-list/components/workflow-item/avatars/avatars' @@ -40,6 +41,7 @@ export function WorkflowItem({ workflow, active, level, onWorkflowClick }: Workf const workspaceId = params.workspaceId as string const { selectedWorkflows } = useFolderStore() const { updateWorkflow, workflows } = useWorkflowRegistry() + const userPermissions = useUserPermissionsContext() const isSelected = selectedWorkflows.has(workflow.id) // Delete modal state @@ -309,6 +311,10 @@ export function WorkflowItem({ workflow, active, level, onWorkflowClick }: Workf showRename={selectedWorkflows.size <= 1} showDuplicate={true} showExport={true} + disableRename={!userPermissions.canEdit} + disableDuplicate={!userPermissions.canEdit} + disableExport={!userPermissions.canEdit} + disableDelete={!userPermissions.canEdit} /> {/* Delete Confirmation Modal */} diff --git a/apps/sim/blocks/blocks/linkedin.ts b/apps/sim/blocks/blocks/linkedin.ts new file mode 100644 index 0000000000..9d9e3208d1 --- /dev/null +++ b/apps/sim/blocks/blocks/linkedin.ts @@ -0,0 +1,112 @@ +import { LinkedInIcon } from '@/components/icons' +import type { BlockConfig } from '@/blocks/types' +import { AuthMode } from '@/blocks/types' +import type { LinkedInResponse } from '@/tools/linkedin/types' + +export const LinkedInBlock: BlockConfig = { + type: 'linkedin', + name: 'LinkedIn', + description: 'Share posts and manage your LinkedIn presence', + authMode: AuthMode.OAuth, + longDescription: + 'Integrate LinkedIn into workflows. Share posts to your personal feed and access your LinkedIn profile information.', + docsLink: 'https://docs.sim.ai/tools/linkedin', + category: 'tools', + bgColor: '#0072B1', + icon: LinkedInIcon, + subBlocks: [ + // Operation selection + { + id: 'operation', + title: 'Operation', + type: 'dropdown', + options: [ + { label: 'Share Post', id: 'share_post' }, + { label: 'Get Profile', id: 'get_profile' }, + ], + value: () => 'share_post', + }, + + // LinkedIn OAuth Authentication + { + id: 'credential', + title: 'LinkedIn Account', + type: 'oauth-input', + provider: 'linkedin', + serviceId: 'linkedin', + requiredScopes: ['profile', 'openid', 'email', 'w_member_social'], + placeholder: 'Select LinkedIn account', + required: true, + }, + + // Share Post specific fields + { + id: 'text', + title: 'Post Text', + type: 'long-input', + placeholder: 'What do you want to share on LinkedIn?', + condition: { + field: 'operation', + value: 'share_post', + }, + required: true, + }, + { + id: 'visibility', + title: 'Visibility', + type: 'dropdown', + options: [ + { label: 'Public', id: 'PUBLIC' }, + { label: 'Connections Only', id: 'CONNECTIONS' }, + ], + condition: { + field: 'operation', + value: 'share_post', + }, + value: () => 'PUBLIC', + required: true, + }, + ], + tools: { + access: ['linkedin_share_post', 'linkedin_get_profile'], + config: { + tool: (inputs) => { + const operation = inputs.operation || 'share_post' + + if (operation === 'get_profile') { + return 'linkedin_get_profile' + } + + return 'linkedin_share_post' + }, + params: (inputs) => { + const operation = inputs.operation || 'share_post' + const { credential, ...rest } = inputs + + if (operation === 'get_profile') { + return { + accessToken: credential, + } + } + + return { + text: rest.text, + visibility: rest.visibility || 'PUBLIC', + accessToken: credential, + } + }, + }, + }, + inputs: { + operation: { type: 'string', description: 'Operation to perform' }, + credential: { type: 'string', description: 'LinkedIn access token' }, + text: { type: 'string', description: 'Post text content' }, + visibility: { type: 'string', description: 'Post visibility (PUBLIC or CONNECTIONS)' }, + }, + outputs: { + success: { type: 'boolean', description: 'Operation success status' }, + postId: { type: 'string', description: 'Created post ID' }, + profile: { type: 'json', description: 'LinkedIn profile information' }, + error: { type: 'string', description: 'Error message if operation failed' }, + }, +} diff --git a/apps/sim/blocks/blocks/mailgun.ts b/apps/sim/blocks/blocks/mailgun.ts new file mode 100644 index 0000000000..1fdeb3b629 --- /dev/null +++ b/apps/sim/blocks/blocks/mailgun.ts @@ -0,0 +1,293 @@ +import { MailgunIcon } from '@/components/icons' +import type { BlockConfig } from '@/blocks/types' +import type { SendMessageResult } from '@/tools/mailgun/types' + +export const MailgunBlock: BlockConfig = { + type: 'mailgun', + name: 'Mailgun', + description: 'Send emails and manage mailing lists with Mailgun', + longDescription: + 'Integrate Mailgun into your workflow. Send transactional emails, manage mailing lists and members, view domain information, and track email events. Supports text and HTML emails, tags for tracking, and comprehensive list management.', + docsLink: 'https://docs.sim.ai/tools/mailgun', + category: 'tools', + bgColor: '#F06248', + icon: MailgunIcon, + + subBlocks: [ + { + id: 'operation', + title: 'Operation', + type: 'dropdown', + options: [ + // Message Operations + { label: 'Send Message', id: 'send_message' }, + { label: 'Get Message', id: 'get_message' }, + { label: 'List Messages', id: 'list_messages' }, + // Mailing List Operations + { label: 'Create Mailing List', id: 'create_mailing_list' }, + { label: 'Get Mailing List', id: 'get_mailing_list' }, + { label: 'Add List Member', id: 'add_list_member' }, + // Domain Operations + { label: 'List Domains', id: 'list_domains' }, + { label: 'Get Domain', id: 'get_domain' }, + ], + value: () => 'send_message', + }, + { + id: 'apiKey', + title: 'Mailgun API Key', + type: 'short-input', + password: true, + placeholder: 'Enter your Mailgun API key', + required: true, + }, + { + id: 'domain', + title: 'Domain', + type: 'short-input', + placeholder: 'mg.example.com', + condition: { + field: 'operation', + value: ['send_message', 'get_message', 'list_messages', 'get_domain'], + }, + required: true, + }, + // Send Message fields + { + id: 'from', + title: 'From Email', + type: 'short-input', + placeholder: 'sender@example.com', + condition: { field: 'operation', value: 'send_message' }, + required: true, + }, + { + id: 'to', + title: 'To Email', + type: 'short-input', + placeholder: 'recipient@example.com', + condition: { field: 'operation', value: 'send_message' }, + required: true, + }, + { + id: 'subject', + title: 'Subject', + type: 'short-input', + placeholder: 'Email subject', + condition: { field: 'operation', value: 'send_message' }, + required: true, + }, + { + id: 'text', + title: 'Text Body', + type: 'long-input', + placeholder: 'Plain text email body', + condition: { field: 'operation', value: 'send_message' }, + }, + { + id: 'html', + title: 'HTML Body', + type: 'code', + placeholder: 'HTML email body', + condition: { field: 'operation', value: 'send_message' }, + }, + { + id: 'cc', + title: 'CC', + type: 'short-input', + placeholder: 'cc@example.com', + condition: { field: 'operation', value: 'send_message' }, + }, + { + id: 'bcc', + title: 'BCC', + type: 'short-input', + placeholder: 'bcc@example.com', + condition: { field: 'operation', value: 'send_message' }, + }, + { + id: 'tags', + title: 'Tags', + type: 'short-input', + placeholder: 'tag1, tag2', + condition: { field: 'operation', value: 'send_message' }, + }, + // Get Message fields + { + id: 'messageKey', + title: 'Message Key', + type: 'short-input', + placeholder: 'Message storage key', + condition: { field: 'operation', value: 'get_message' }, + required: true, + }, + // List Messages fields + { + id: 'event', + title: 'Event Type', + type: 'dropdown', + options: [ + { label: 'All Events', id: '' }, + { label: 'Accepted', id: 'accepted' }, + { label: 'Delivered', id: 'delivered' }, + { label: 'Failed', id: 'failed' }, + { label: 'Opened', id: 'opened' }, + { label: 'Clicked', id: 'clicked' }, + { label: 'Unsubscribed', id: 'unsubscribed' }, + { label: 'Complained', id: 'complained' }, + { label: 'Stored', id: 'stored' }, + ], + value: () => '', + condition: { field: 'operation', value: 'list_messages' }, + }, + { + id: 'limit', + title: 'Limit', + type: 'short-input', + placeholder: '100', + condition: { field: 'operation', value: 'list_messages' }, + }, + // Create Mailing List fields + { + id: 'address', + title: 'List Address', + type: 'short-input', + placeholder: 'list@example.com', + condition: { + field: 'operation', + value: ['create_mailing_list', 'get_mailing_list', 'add_list_member'], + }, + required: true, + }, + { + id: 'name', + title: 'List Name', + type: 'short-input', + placeholder: 'My Mailing List', + condition: { field: 'operation', value: 'create_mailing_list' }, + }, + { + id: 'description', + title: 'Description', + type: 'long-input', + placeholder: 'Description of the mailing list', + condition: { field: 'operation', value: 'create_mailing_list' }, + }, + { + id: 'accessLevel', + title: 'Access Level', + type: 'dropdown', + options: [ + { label: 'Read Only', id: 'readonly' }, + { label: 'Members', id: 'members' }, + { label: 'Everyone', id: 'everyone' }, + ], + value: () => 'readonly', + condition: { field: 'operation', value: 'create_mailing_list' }, + }, + // Add List Member fields (reuse address from above for listAddress) + { + id: 'memberAddress', + title: 'Member Email', + type: 'short-input', + placeholder: 'member@example.com', + condition: { field: 'operation', value: 'add_list_member' }, + required: true, + }, + { + id: 'memberName', + title: 'Member Name', + type: 'short-input', + placeholder: 'John Doe', + condition: { field: 'operation', value: 'add_list_member' }, + }, + { + id: 'vars', + title: 'Custom Variables', + type: 'code', + placeholder: '{"key": "value"}', + condition: { field: 'operation', value: 'add_list_member' }, + }, + { + id: 'subscribed', + title: 'Subscribed', + type: 'dropdown', + options: [ + { label: 'Yes', id: 'true' }, + { label: 'No', id: 'false' }, + ], + value: () => 'true', + condition: { field: 'operation', value: 'add_list_member' }, + }, + ], + + tools: { + access: [ + 'mailgun_send_message', + 'mailgun_get_message', + 'mailgun_list_messages', + 'mailgun_create_mailing_list', + 'mailgun_get_mailing_list', + 'mailgun_add_list_member', + 'mailgun_list_domains', + 'mailgun_get_domain', + ], + config: { + tool: (params) => `mailgun_${params.operation}`, + params: (params) => { + const { operation, memberAddress, memberName, ...rest } = params + + // Handle special field mappings for add_list_member + if (operation === 'add_list_member') { + return { + ...rest, + listAddress: params.address, + address: memberAddress, + name: memberName, + subscribed: params.subscribed === 'true', + } + } + + return rest + }, + }, + }, + + inputs: { + operation: { type: 'string', description: 'Operation to perform' }, + apiKey: { type: 'string', description: 'Mailgun API key' }, + domain: { type: 'string', description: 'Mailgun domain' }, + // Message inputs + from: { type: 'string', description: 'Sender email address' }, + to: { type: 'string', description: 'Recipient email address' }, + subject: { type: 'string', description: 'Email subject' }, + text: { type: 'string', description: 'Plain text body' }, + html: { type: 'string', description: 'HTML body' }, + cc: { type: 'string', description: 'CC email address' }, + bcc: { type: 'string', description: 'BCC email address' }, + tags: { type: 'string', description: 'Tags for the email' }, + messageKey: { type: 'string', description: 'Message storage key' }, + event: { type: 'string', description: 'Event type filter' }, + limit: { type: 'number', description: 'Number of events to return' }, + // Mailing list inputs + address: { type: 'string', description: 'Mailing list address' }, + name: { type: 'string', description: 'List or member name' }, + description: { type: 'string', description: 'List description' }, + accessLevel: { type: 'string', description: 'List access level' }, + memberAddress: { type: 'string', description: 'Member email address' }, + memberName: { type: 'string', description: 'Member name' }, + vars: { type: 'string', description: 'Custom variables JSON' }, + subscribed: { type: 'string', description: 'Member subscription status' }, + }, + + outputs: { + success: { type: 'boolean', description: 'Operation success status' }, + id: { type: 'string', description: 'Message ID' }, + message: { type: 'string', description: 'Response message' }, + items: { type: 'json', description: 'Array of items (messages, domains)' }, + list: { type: 'json', description: 'Mailing list details' }, + member: { type: 'json', description: 'Member details' }, + domain: { type: 'json', description: 'Domain details' }, + totalCount: { type: 'number', description: 'Total count of items' }, + }, +} diff --git a/apps/sim/blocks/blocks/sendgrid.ts b/apps/sim/blocks/blocks/sendgrid.ts new file mode 100644 index 0000000000..130ef13156 --- /dev/null +++ b/apps/sim/blocks/blocks/sendgrid.ts @@ -0,0 +1,478 @@ +import { SendgridIcon } from '@/components/icons' +import type { BlockConfig } from '@/blocks/types' +import type { SendMailResult } from '@/tools/sendgrid/types' + +export const SendGridBlock: BlockConfig = { + type: 'sendgrid', + name: 'SendGrid', + description: 'Send emails and manage contacts, lists, and templates with SendGrid', + longDescription: + 'Integrate SendGrid into your workflow. Send transactional emails, manage marketing contacts and lists, and work with email templates. Supports dynamic templates, attachments, and comprehensive contact management.', + docsLink: 'https://docs.sim.ai/tools/sendgrid', + category: 'tools', + bgColor: '#1A82E2', + icon: SendgridIcon, + + subBlocks: [ + { + id: 'operation', + title: 'Operation', + type: 'dropdown', + options: [ + // Mail Operations + { label: 'Send Mail', id: 'send_mail' }, + // Contact Operations + { label: 'Add Contact', id: 'add_contact' }, + { label: 'Get Contact', id: 'get_contact' }, + { label: 'Search Contacts', id: 'search_contacts' }, + { label: 'Delete Contacts', id: 'delete_contacts' }, + // List Operations + { label: 'Create List', id: 'create_list' }, + { label: 'Get List', id: 'get_list' }, + { label: 'List All Lists', id: 'list_all_lists' }, + { label: 'Delete List', id: 'delete_list' }, + { label: 'Add Contacts to List', id: 'add_contacts_to_list' }, + { label: 'Remove Contacts from List', id: 'remove_contacts_from_list' }, + // Template Operations + { label: 'Create Template', id: 'create_template' }, + { label: 'Get Template', id: 'get_template' }, + { label: 'List Templates', id: 'list_templates' }, + { label: 'Delete Template', id: 'delete_template' }, + { label: 'Create Template Version', id: 'create_template_version' }, + ], + value: () => 'send_mail', + }, + { + id: 'apiKey', + title: 'SendGrid API Key', + type: 'short-input', + password: true, + placeholder: 'Enter your SendGrid API key', + required: true, + }, + // Send Mail fields + { + id: 'from', + title: 'From Email', + type: 'short-input', + placeholder: 'sender@yourdomain.com', + condition: { field: 'operation', value: 'send_mail' }, + required: true, + }, + { + id: 'fromName', + title: 'From Name', + type: 'short-input', + placeholder: 'Sender Name', + condition: { field: 'operation', value: 'send_mail' }, + }, + { + id: 'to', + title: 'To Email', + type: 'short-input', + placeholder: 'recipient@example.com', + condition: { field: 'operation', value: 'send_mail' }, + required: true, + }, + { + id: 'toName', + title: 'To Name', + type: 'short-input', + placeholder: 'Recipient Name', + condition: { field: 'operation', value: 'send_mail' }, + }, + { + id: 'mailSubject', + title: 'Subject', + type: 'short-input', + placeholder: 'Email subject (required unless using template)', + condition: { field: 'operation', value: 'send_mail' }, + }, + { + id: 'content', + title: 'Content', + type: 'long-input', + placeholder: 'Email body content (required unless using template)', + condition: { field: 'operation', value: 'send_mail' }, + }, + { + id: 'contentType', + title: 'Content Type', + type: 'dropdown', + options: [ + { label: 'Plain Text', id: 'text/plain' }, + { label: 'HTML', id: 'text/html' }, + ], + value: () => 'text/plain', + condition: { field: 'operation', value: 'send_mail' }, + }, + { + id: 'cc', + title: 'CC', + type: 'short-input', + placeholder: 'cc@example.com', + condition: { field: 'operation', value: 'send_mail' }, + }, + { + id: 'bcc', + title: 'BCC', + type: 'short-input', + placeholder: 'bcc@example.com', + condition: { field: 'operation', value: 'send_mail' }, + }, + { + id: 'replyTo', + title: 'Reply To', + type: 'short-input', + placeholder: 'replyto@example.com', + condition: { field: 'operation', value: 'send_mail' }, + }, + { + id: 'replyToName', + title: 'Reply To Name', + type: 'short-input', + placeholder: 'Reply To Name', + condition: { field: 'operation', value: 'send_mail' }, + }, + { + id: 'mailTemplateId', + title: 'Template ID', + type: 'short-input', + placeholder: 'SendGrid template ID', + condition: { field: 'operation', value: 'send_mail' }, + }, + { + id: 'dynamicTemplateData', + title: 'Dynamic Template Data', + type: 'code', + placeholder: '{"name": "John", "order_id": "12345"}', + condition: { field: 'operation', value: 'send_mail' }, + }, + // File upload (basic mode) + { + id: 'attachmentFiles', + title: 'Attachments', + type: 'file-upload', + canonicalParamId: 'attachments', + placeholder: 'Upload files to attach', + condition: { field: 'operation', value: 'send_mail' }, + mode: 'basic', + multiple: true, + required: false, + }, + // Variable reference (advanced mode) + { + id: 'attachments', + title: 'Attachments', + type: 'short-input', + canonicalParamId: 'attachments', + placeholder: 'Reference files from previous blocks', + condition: { field: 'operation', value: 'send_mail' }, + mode: 'advanced', + required: false, + }, + // Contact fields + { + id: 'email', + title: 'Email', + type: 'short-input', + placeholder: 'contact@example.com', + condition: { field: 'operation', value: ['add_contact'] }, + required: true, + }, + { + id: 'firstName', + title: 'First Name', + type: 'short-input', + placeholder: 'John', + condition: { field: 'operation', value: ['add_contact'] }, + }, + { + id: 'lastName', + title: 'Last Name', + type: 'short-input', + placeholder: 'Doe', + condition: { field: 'operation', value: ['add_contact'] }, + }, + { + id: 'customFields', + title: 'Custom Fields', + type: 'code', + placeholder: '{"custom_field_1": "value1"}', + condition: { field: 'operation', value: ['add_contact'] }, + }, + { + id: 'contactListIds', + title: 'List IDs', + type: 'short-input', + placeholder: 'Comma-separated list IDs', + condition: { field: 'operation', value: ['add_contact'] }, + }, + { + id: 'contactId', + title: 'Contact ID', + type: 'short-input', + placeholder: 'Contact ID', + condition: { field: 'operation', value: ['get_contact'] }, + required: true, + }, + { + id: 'query', + title: 'Search Query', + type: 'long-input', + placeholder: "email LIKE '%example.com%'", + condition: { field: 'operation', value: ['search_contacts'] }, + required: true, + }, + { + id: 'contactIds', + title: 'Contact IDs', + type: 'short-input', + placeholder: 'Comma-separated contact IDs', + condition: { + field: 'operation', + value: ['delete_contacts', 'remove_contacts_from_list'], + }, + required: true, + }, + { + id: 'contacts', + title: 'Contacts (JSON Array)', + type: 'code', + placeholder: '[{"email": "user@example.com", "first_name": "John"}]', + condition: { field: 'operation', value: 'add_contacts_to_list' }, + required: true, + }, + // List fields + { + id: 'listName', + title: 'List Name', + type: 'short-input', + placeholder: 'List name', + condition: { field: 'operation', value: ['create_list'] }, + required: true, + }, + { + id: 'listId', + title: 'List ID', + type: 'short-input', + placeholder: 'List ID', + condition: { + field: 'operation', + value: ['get_list', 'delete_list', 'add_contacts_to_list', 'remove_contacts_from_list'], + }, + required: true, + }, + { + id: 'listPageSize', + title: 'Page Size', + type: 'short-input', + placeholder: '100', + condition: { field: 'operation', value: 'list_all_lists' }, + }, + // Template fields + { + id: 'templateName', + title: 'Template Name', + type: 'short-input', + placeholder: 'Template name', + condition: { field: 'operation', value: ['create_template'] }, + required: true, + }, + { + id: 'templateId', + title: 'Template ID', + type: 'short-input', + placeholder: 'Template ID', + condition: { + field: 'operation', + value: ['get_template', 'delete_template', 'create_template_version'], + }, + required: true, + }, + { + id: 'generation', + title: 'Template Generation', + type: 'dropdown', + options: [ + { label: 'Dynamic', id: 'dynamic' }, + { label: 'Legacy', id: 'legacy' }, + ], + value: () => 'dynamic', + condition: { field: 'operation', value: 'create_template' }, + }, + { + id: 'templateGenerations', + title: 'Filter by Generation', + type: 'short-input', + placeholder: 'legacy, dynamic, or both', + condition: { field: 'operation', value: 'list_templates' }, + }, + { + id: 'templatePageSize', + title: 'Page Size', + type: 'short-input', + placeholder: '20', + condition: { field: 'operation', value: 'list_templates' }, + }, + { + id: 'versionName', + title: 'Version Name', + type: 'short-input', + placeholder: 'Version name', + condition: { field: 'operation', value: 'create_template_version' }, + required: true, + }, + { + id: 'templateSubject', + title: 'Template Subject', + type: 'short-input', + placeholder: 'Email subject', + condition: { field: 'operation', value: 'create_template_version' }, + required: true, + }, + { + id: 'htmlContent', + title: 'HTML Content', + type: 'code', + placeholder: '{{name}}', + condition: { field: 'operation', value: 'create_template_version' }, + }, + { + id: 'plainContent', + title: 'Plain Text Content', + type: 'long-input', + placeholder: 'Plain text content', + condition: { field: 'operation', value: 'create_template_version' }, + }, + { + id: 'active', + title: 'Active', + type: 'dropdown', + options: [ + { label: 'Yes', id: 'true' }, + { label: 'No', id: 'false' }, + ], + value: () => 'true', + condition: { field: 'operation', value: 'create_template_version' }, + }, + ], + + tools: { + access: [ + 'sendgrid_send_mail', + 'sendgrid_add_contact', + 'sendgrid_get_contact', + 'sendgrid_search_contacts', + 'sendgrid_delete_contacts', + 'sendgrid_create_list', + 'sendgrid_get_list', + 'sendgrid_list_all_lists', + 'sendgrid_delete_list', + 'sendgrid_add_contacts_to_list', + 'sendgrid_remove_contacts_from_list', + 'sendgrid_create_template', + 'sendgrid_get_template', + 'sendgrid_list_templates', + 'sendgrid_delete_template', + 'sendgrid_create_template_version', + ], + config: { + tool: (params) => `sendgrid_${params.operation}`, + params: (params) => { + const { + operation, + mailSubject, + mailTemplateId, + listName, + templateName, + versionName, + templateSubject, + contactListIds, + templateGenerations, + listPageSize, + templatePageSize, + ...rest + } = params + + // Map renamed fields back to tool parameter names + return { + ...rest, + ...(mailSubject && { subject: mailSubject }), + ...(mailTemplateId && { templateId: mailTemplateId }), + ...(listName && { name: listName }), + ...(templateName && { name: templateName }), + ...(versionName && { name: versionName }), + ...(templateSubject && { subject: templateSubject }), + ...(contactListIds && { listIds: contactListIds }), + ...(templateGenerations && { generations: templateGenerations }), + ...(listPageSize && { pageSize: listPageSize }), + ...(templatePageSize && { pageSize: templatePageSize }), + } + }, + }, + }, + + inputs: { + operation: { type: 'string', description: 'Operation to perform' }, + apiKey: { type: 'string', description: 'SendGrid API key' }, + // Mail inputs + from: { type: 'string', description: 'Sender email address' }, + fromName: { type: 'string', description: 'Sender name' }, + to: { type: 'string', description: 'Recipient email address' }, + toName: { type: 'string', description: 'Recipient name' }, + mailSubject: { type: 'string', description: 'Email subject' }, + content: { type: 'string', description: 'Email content' }, + contentType: { type: 'string', description: 'Content type' }, + cc: { type: 'string', description: 'CC email address' }, + bcc: { type: 'string', description: 'BCC email address' }, + replyTo: { type: 'string', description: 'Reply-to email address' }, + replyToName: { type: 'string', description: 'Reply-to name' }, + mailTemplateId: { type: 'string', description: 'Template ID for sending mail' }, + dynamicTemplateData: { type: 'json', description: 'Dynamic template data' }, + attachmentFiles: { type: 'json', description: 'Files to attach (UI upload)' }, + attachments: { type: 'array', description: 'Files to attach (UserFile array)' }, + // Contact inputs + email: { type: 'string', description: 'Contact email' }, + firstName: { type: 'string', description: 'Contact first name' }, + lastName: { type: 'string', description: 'Contact last name' }, + customFields: { type: 'json', description: 'Custom fields' }, + contactId: { type: 'string', description: 'Contact ID' }, + contactIds: { type: 'string', description: 'Comma-separated contact IDs' }, + contacts: { type: 'json', description: 'Array of contact objects' }, + query: { type: 'string', description: 'Search query' }, + contactListIds: { type: 'string', description: 'Comma-separated list IDs for contact' }, + // List inputs + listName: { type: 'string', description: 'List name' }, + listId: { type: 'string', description: 'List ID' }, + listPageSize: { type: 'number', description: 'Page size for listing lists' }, + // Template inputs + templateName: { type: 'string', description: 'Template name' }, + templateId: { type: 'string', description: 'Template ID' }, + generation: { type: 'string', description: 'Template generation' }, + templateGenerations: { type: 'string', description: 'Filter templates by generation' }, + templatePageSize: { type: 'number', description: 'Page size for listing templates' }, + versionName: { type: 'string', description: 'Template version name' }, + templateSubject: { type: 'string', description: 'Template subject' }, + htmlContent: { type: 'string', description: 'HTML content' }, + plainContent: { type: 'string', description: 'Plain text content' }, + active: { type: 'boolean', description: 'Whether template version is active' }, + }, + + outputs: { + success: { type: 'boolean', description: 'Operation success status' }, + messageId: { type: 'string', description: 'Email message ID (send_mail)' }, + id: { type: 'string', description: 'Resource ID' }, + jobId: { type: 'string', description: 'Job ID for async operations' }, + email: { type: 'string', description: 'Email address' }, + firstName: { type: 'string', description: 'First name' }, + lastName: { type: 'string', description: 'Last name' }, + contacts: { type: 'json', description: 'Array of contacts' }, + contactCount: { type: 'number', description: 'Number of contacts' }, + lists: { type: 'json', description: 'Array of lists' }, + templates: { type: 'json', description: 'Array of templates' }, + message: { type: 'string', description: 'Status or success message' }, + name: { type: 'string', description: 'Resource name' }, + generation: { type: 'string', description: 'Template generation' }, + }, +} diff --git a/apps/sim/blocks/blocks/smtp.ts b/apps/sim/blocks/blocks/smtp.ts new file mode 100644 index 0000000000..d6ed236059 --- /dev/null +++ b/apps/sim/blocks/blocks/smtp.ts @@ -0,0 +1,209 @@ +import { SmtpIcon } from '@/components/icons' +import type { BlockConfig } from '@/blocks/types' +import { AuthMode } from '@/blocks/types' +import type { SmtpSendMailResult } from '@/tools/smtp/types' + +export const SmtpBlock: BlockConfig = { + type: 'smtp', + name: 'SMTP', + description: 'Send emails via any SMTP mail server', + longDescription: + 'Send emails using any SMTP server (Gmail, Outlook, custom servers, etc.). Configure SMTP connection settings and send emails with full control over content, recipients, and attachments.', + docsLink: 'https://docs.sim.ai/tools/smtp', + category: 'tools', + bgColor: '#4A5568', + icon: SmtpIcon, + authMode: AuthMode.ApiKey, + + subBlocks: [ + { + id: 'smtpHost', + title: 'SMTP Host', + type: 'short-input', + placeholder: 'smtp.gmail.com, smtp.example.com', + required: true, + }, + { + id: 'smtpPort', + title: 'SMTP Port', + type: 'short-input', + placeholder: '587', + required: true, + value: () => '587', + }, + { + id: 'smtpUsername', + title: 'SMTP Username', + type: 'short-input', + placeholder: 'your-email@example.com', + required: true, + }, + { + id: 'smtpPassword', + title: 'SMTP Password', + type: 'short-input', + placeholder: 'Your SMTP password', + required: true, + password: true, + }, + { + id: 'smtpSecure', + title: 'Security Mode', + type: 'dropdown', + options: [ + { label: 'TLS (Port 587)', id: 'TLS' }, + { label: 'SSL (Port 465)', id: 'SSL' }, + { label: 'None (Port 25)', id: 'None' }, + ], + value: () => 'TLS', + required: true, + }, + + { + id: 'from', + title: 'From', + type: 'short-input', + placeholder: 'sender@example.com', + required: true, + }, + { + id: 'to', + title: 'To', + type: 'short-input', + placeholder: 'recipient@example.com', + required: true, + }, + { + id: 'subject', + title: 'Subject', + type: 'short-input', + placeholder: 'Email subject', + required: true, + }, + { + id: 'body', + title: 'Body', + type: 'long-input', + placeholder: 'Email content', + required: true, + }, + { + id: 'contentType', + title: 'Content Type', + type: 'dropdown', + options: [ + { label: 'Plain Text', id: 'text' }, + { label: 'HTML', id: 'html' }, + ], + value: () => 'text', + required: false, + }, + + // Attachments Section + // File upload (basic mode) + { + id: 'attachmentFiles', + title: 'Attachments', + type: 'file-upload', + canonicalParamId: 'attachments', + placeholder: 'Upload files to attach', + mode: 'basic', + multiple: true, + required: false, + }, + // Variable reference (advanced mode) + { + id: 'attachments', + title: 'Attachments', + type: 'short-input', + canonicalParamId: 'attachments', + placeholder: 'Reference files from previous blocks', + mode: 'advanced', + required: false, + }, + + // Advanced Options Section + { + id: 'fromName', + title: 'From Name', + type: 'short-input', + placeholder: 'Display name for sender', + mode: 'advanced', + required: false, + }, + { + id: 'cc', + title: 'CC', + type: 'short-input', + placeholder: 'cc1@example.com, cc2@example.com', + mode: 'advanced', + required: false, + }, + { + id: 'bcc', + title: 'BCC', + type: 'short-input', + placeholder: 'bcc1@example.com, bcc2@example.com', + mode: 'advanced', + required: false, + }, + { + id: 'replyTo', + title: 'Reply To', + type: 'short-input', + placeholder: 'reply@example.com', + mode: 'advanced', + required: false, + }, + ], + + tools: { + access: ['smtp_send_mail'], + config: { + tool: () => 'smtp_send_mail', + params: (params) => ({ + smtpHost: params.smtpHost, + smtpPort: Number(params.smtpPort), + smtpUsername: params.smtpUsername, + smtpPassword: params.smtpPassword, + smtpSecure: params.smtpSecure, + from: params.from, + to: params.to, + subject: params.subject, + body: params.body, + contentType: params.contentType, + fromName: params.fromName, + cc: params.cc, + bcc: params.bcc, + replyTo: params.replyTo, + attachments: params.attachments, + }), + }, + }, + + inputs: { + smtpHost: { type: 'string', description: 'SMTP server hostname' }, + smtpPort: { type: 'number', description: 'SMTP server port' }, + smtpUsername: { type: 'string', description: 'SMTP authentication username' }, + smtpPassword: { type: 'string', description: 'SMTP authentication password' }, + smtpSecure: { type: 'string', description: 'Security protocol (TLS, SSL, or None)' }, + from: { type: 'string', description: 'Sender email address' }, + to: { type: 'string', description: 'Recipient email address' }, + subject: { type: 'string', description: 'Email subject' }, + body: { type: 'string', description: 'Email body content' }, + contentType: { type: 'string', description: 'Content type (text or html)' }, + fromName: { type: 'string', description: 'Display name for sender' }, + cc: { type: 'string', description: 'CC recipients (comma-separated)' }, + bcc: { type: 'string', description: 'BCC recipients (comma-separated)' }, + replyTo: { type: 'string', description: 'Reply-to email address' }, + attachments: { type: 'array', description: 'Files to attach (UserFile array)' }, + }, + + outputs: { + success: { type: 'boolean', description: 'Whether the email was sent successfully' }, + messageId: { type: 'string', description: 'Message ID from SMTP server' }, + to: { type: 'string', description: 'Recipient email address' }, + subject: { type: 'string', description: 'Email subject' }, + error: { type: 'string', description: 'Error message if sending failed' }, + }, +} diff --git a/apps/sim/blocks/registry.ts b/apps/sim/blocks/registry.ts index db663ba3ec..e7da0a7e57 100644 --- a/apps/sim/blocks/registry.ts +++ b/apps/sim/blocks/registry.ts @@ -41,8 +41,10 @@ import { JinaBlock } from '@/blocks/blocks/jina' import { JiraBlock } from '@/blocks/blocks/jira' import { KnowledgeBlock } from '@/blocks/blocks/knowledge' import { LinearBlock } from '@/blocks/blocks/linear' +import { LinkedInBlock } from '@/blocks/blocks/linkedin' import { LinkupBlock } from '@/blocks/blocks/linkup' import { MailchimpBlock } from '@/blocks/blocks/mailchimp' +import { MailgunBlock } from '@/blocks/blocks/mailgun' import { ManualTriggerBlock } from '@/blocks/blocks/manual_trigger' import { McpBlock } from '@/blocks/blocks/mcp' import { Mem0Block } from '@/blocks/blocks/mem0' @@ -74,10 +76,12 @@ import { RouterBlock } from '@/blocks/blocks/router' import { S3Block } from '@/blocks/blocks/s3' import { SalesforceBlock } from '@/blocks/blocks/salesforce' import { ScheduleBlock } from '@/blocks/blocks/schedule' +import { SendGridBlock } from '@/blocks/blocks/sendgrid' import { SentryBlock } from '@/blocks/blocks/sentry' import { SerperBlock } from '@/blocks/blocks/serper' import { SharepointBlock } from '@/blocks/blocks/sharepoint' import { SlackBlock } from '@/blocks/blocks/slack' +import { SmtpBlock } from '@/blocks/blocks/smtp' import { StagehandBlock } from '@/blocks/blocks/stagehand' import { StagehandAgentBlock } from '@/blocks/blocks/stagehand_agent' import { StartTriggerBlock } from '@/blocks/blocks/start_trigger' @@ -152,6 +156,7 @@ export const registry: Record = { jira: JiraBlock, knowledge: KnowledgeBlock, linear: LinearBlock, + linkedin: LinkedInBlock, linkup: LinkupBlock, mailchimp: MailchimpBlock, mcp: McpBlock, @@ -178,6 +183,9 @@ export const registry: Record = { pylon: PylonBlock, qdrant: QdrantBlock, resend: ResendBlock, + sendgrid: SendGridBlock, + mailgun: MailgunBlock, + smtp: SmtpBlock, memory: MemoryBlock, reddit: RedditBlock, response: ResponseBlock, diff --git a/apps/sim/components/icons.tsx b/apps/sim/components/icons.tsx index 3c70935669..c848e36eb6 100644 --- a/apps/sim/components/icons.tsx +++ b/apps/sim/components/icons.tsx @@ -1464,11 +1464,17 @@ export function DiscordIcon(props: SVGProps) { export function LinkedInIcon(props: SVGProps) { return ( - - + + + + + ) } @@ -4344,3 +4350,81 @@ export function PylonIcon(props: SVGProps) { ) } + +export function SendgridIcon(props: SVGProps) { + return ( + + + + + + + + + + + ) +} + +export function MailgunIcon(props: SVGProps) { + return ( + + + + ) +} + +export function SmtpIcon(props: SVGProps) { + return ( + + + + + ) +} diff --git a/apps/sim/lib/auth.ts b/apps/sim/lib/auth.ts index 48982d432a..a22affc129 100644 --- a/apps/sim/lib/auth.ts +++ b/apps/sim/lib/auth.ts @@ -157,6 +157,7 @@ export const auth = betterAuth({ 'asana', 'pipedrive', 'hubspot', + 'linkedin', // Common SSO provider patterns ...SSO_TRUSTED_PROVIDERS, @@ -1585,6 +1586,54 @@ export const auth = betterAuth({ } }, }, + // LinkedIn provider + { + providerId: 'linkedin', + clientId: env.LINKEDIN_CLIENT_ID as string, + clientSecret: env.LINKEDIN_CLIENT_SECRET as string, + authorizationUrl: 'https://www.linkedin.com/oauth/v2/authorization', + tokenUrl: 'https://www.linkedin.com/oauth/v2/accessToken', + userInfoUrl: 'https://api.linkedin.com/v2/userinfo', + scopes: ['profile', 'openid', 'email', 'w_member_social'], + responseType: 'code', + accessType: 'offline', + prompt: 'consent', + redirectURI: `${getBaseUrl()}/api/auth/oauth2/callback/linkedin`, + getUserInfo: async (tokens) => { + try { + logger.info('Fetching LinkedIn user profile') + + const response = await fetch('https://api.linkedin.com/v2/userinfo', { + headers: { + Authorization: `Bearer ${tokens.accessToken}`, + }, + }) + + if (!response.ok) { + logger.error('Failed to fetch LinkedIn user info', { + status: response.status, + statusText: response.statusText, + }) + throw new Error('Failed to fetch user info') + } + + const profile = await response.json() + + return { + id: profile.sub, + name: profile.name || 'LinkedIn User', + email: profile.email || `${profile.sub}@linkedin.user`, + emailVerified: profile.email_verified || true, + image: profile.picture || undefined, + createdAt: new Date(), + updatedAt: new Date(), + } + } catch (error) { + logger.error('Error in LinkedIn getUserInfo:', { error }) + return null + } + }, + }, ], }), // Include SSO plugin when enabled diff --git a/apps/sim/lib/env.ts b/apps/sim/lib/env.ts index 660c5051ed..66cdb0ad47 100644 --- a/apps/sim/lib/env.ts +++ b/apps/sim/lib/env.ts @@ -217,6 +217,8 @@ export const env = createEnv({ WEBFLOW_CLIENT_ID: z.string().optional(), // Webflow OAuth client ID WEBFLOW_CLIENT_SECRET: z.string().optional(), // Webflow OAuth client secret TRELLO_API_KEY: z.string().optional(), // Trello API Key + LINKEDIN_CLIENT_ID: z.string().optional(), // LinkedIn OAuth client ID + LINKEDIN_CLIENT_SECRET: z.string().optional(), // LinkedIn OAuth client secret // E2B Remote Code Execution E2B_ENABLED: z.string().optional(), // Enable E2B remote code execution diff --git a/apps/sim/lib/oauth/oauth.ts b/apps/sim/lib/oauth/oauth.ts index 41145c3bf8..ed51f34433 100644 --- a/apps/sim/lib/oauth/oauth.ts +++ b/apps/sim/lib/oauth/oauth.ts @@ -15,6 +15,7 @@ import { HubspotIcon, JiraIcon, LinearIcon, + LinkedInIcon, MicrosoftExcelIcon, MicrosoftIcon, MicrosoftOneDriveIcon, @@ -59,6 +60,7 @@ export type OAuthProvider = | 'pipedrive' | 'hubspot' | 'salesforce' + | 'linkedin' | string export type OAuthService = @@ -94,6 +96,7 @@ export type OAuthService = | 'pipedrive' | 'hubspot' | 'salesforce' + | 'linkedin' export interface OAuthProviderConfig { id: OAuthProvider name: string @@ -732,6 +735,23 @@ export const OAUTH_PROVIDERS: Record = { }, defaultService: 'hubspot', }, + linkedin: { + id: 'linkedin', + name: 'LinkedIn', + icon: (props) => LinkedInIcon(props), + services: { + linkedin: { + id: 'linkedin', + name: 'LinkedIn', + description: 'Share posts and access profile data on LinkedIn.', + providerId: 'linkedin', + icon: (props) => LinkedInIcon(props), + baseProviderIcon: (props) => LinkedInIcon(props), + scopes: ['profile', 'openid', 'email', 'w_member_social'], + }, + }, + defaultService: 'linkedin', + }, salesforce: { id: 'salesforce', name: 'Salesforce', @@ -1219,6 +1239,19 @@ function getProviderAuthConfig(provider: string): ProviderAuthConfig { supportsRefreshTokenRotation: true, } } + case 'linkedin': { + const { clientId, clientSecret } = getCredentials( + env.LINKEDIN_CLIENT_ID, + env.LINKEDIN_CLIENT_SECRET + ) + return { + tokenEndpoint: 'https://www.linkedin.com/oauth/v2/accessToken', + clientId, + clientSecret, + useBasicAuth: false, + supportsRefreshTokenRotation: false, + } + } case 'salesforce': { const { clientId, clientSecret } = getCredentials( env.SALESFORCE_CLIENT_ID, diff --git a/apps/sim/tools/linkedin/get_profile.ts b/apps/sim/tools/linkedin/get_profile.ts new file mode 100644 index 0000000000..0c766df85e --- /dev/null +++ b/apps/sim/tools/linkedin/get_profile.ts @@ -0,0 +1,56 @@ +import type { GetProfileParams, GetProfileResponse } from '@/tools/linkedin/types' +import type { ToolConfig } from '@/tools/types' + +export const linkedInGetProfileTool: ToolConfig = { + id: 'linkedin_get_profile', + name: 'Get LinkedIn Profile', + description: 'Retrieve your LinkedIn profile information', + version: '1.0.0', + + oauth: { + required: true, + provider: 'linkedin', + }, + + params: { + accessToken: { + type: 'string', + required: true, + visibility: 'hidden', + description: 'Access token for LinkedIn API', + }, + }, + + request: { + url: () => 'https://api.linkedin.com/v2/userinfo', + method: 'GET', + headers: (params: GetProfileParams): Record => ({ + Authorization: `Bearer ${params.accessToken}`, + 'X-Restli-Protocol-Version': '2.0.0', + }), + }, + + transformResponse: async (response: Response): Promise => { + if (!response.ok) { + return { + success: false, + output: {}, + error: `Failed to get profile: ${response.statusText}`, + } + } + + const profile = await response.json() + + return { + success: true, + output: { + profile: { + id: profile.sub, + name: profile.name, + email: profile.email, + picture: profile.picture, + }, + }, + } + }, +} diff --git a/apps/sim/tools/linkedin/index.ts b/apps/sim/tools/linkedin/index.ts new file mode 100644 index 0000000000..7b457c6cab --- /dev/null +++ b/apps/sim/tools/linkedin/index.ts @@ -0,0 +1,2 @@ +export { linkedInGetProfileTool } from './get_profile' +export { linkedInSharePostTool } from './share_post' diff --git a/apps/sim/tools/linkedin/share_post.ts b/apps/sim/tools/linkedin/share_post.ts new file mode 100644 index 0000000000..ed3bd8d198 --- /dev/null +++ b/apps/sim/tools/linkedin/share_post.ts @@ -0,0 +1,157 @@ +import type { + LinkedInProfileOutput, + ProfileIdExtractor, + SharePostParams, + SharePostResponse, +} from '@/tools/linkedin/types' +import type { ToolConfig } from '@/tools/types' + +// Helper function to extract profile ID from various response formats +const extractProfileId: ProfileIdExtractor = (output: unknown): string | null => { + if (typeof output === 'object' && output !== null) { + const profileOutput = output as LinkedInProfileOutput + return profileOutput.profile?.id || profileOutput.sub || profileOutput.id || null + } + return null +} + +export const linkedInSharePostTool: ToolConfig = { + id: 'linkedin_share_post', + name: 'Share Post on LinkedIn', + description: 'Share a post to your personal LinkedIn feed', + version: '1.0.0', + + oauth: { + required: true, + provider: 'linkedin', + }, + + params: { + accessToken: { + type: 'string', + required: true, + visibility: 'hidden', + description: 'Access token for LinkedIn API', + }, + text: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'The text content of your LinkedIn post', + }, + visibility: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Who can see this post: "PUBLIC" or "CONNECTIONS" (default: "PUBLIC")', + }, + }, + + // First request: Get user profile to obtain the person URN + request: { + url: () => 'https://api.linkedin.com/v2/userinfo', + method: 'GET', + headers: (params: SharePostParams) => ({ + Authorization: `Bearer ${params.accessToken}`, + 'X-Restli-Protocol-Version': '2.0.0', + }), + }, + + // Use postProcess to make the actual post creation request + postProcess: async (profileResult, params, executeTool) => { + try { + // Extract profile from the first request + if (!profileResult.success || !profileResult.output) { + return { + success: false, + output: {}, + error: 'Failed to fetch user profile', + } + } + + // Get profile data from output + const profileOutput = profileResult.output as LinkedInProfileOutput + const authorId = extractProfileId(profileOutput) + + if (!authorId) { + return { + success: false, + output: {}, + error: 'Could not extract LinkedIn profile ID from response', + } + } + + const authorUrn = `urn:li:person:${authorId}` + + // Create the post + const postData = { + author: authorUrn, + lifecycleState: 'PUBLISHED', + specificContent: { + 'com.linkedin.ugc.ShareContent': { + shareCommentary: { + text: params.text, + }, + shareMediaCategory: 'NONE', + }, + }, + visibility: { + 'com.linkedin.ugc.MemberNetworkVisibility': params.visibility || 'PUBLIC', + }, + } + + const response = await fetch('https://api.linkedin.com/v2/ugcPosts', { + method: 'POST', + headers: { + Authorization: `Bearer ${params.accessToken}`, + 'Content-Type': 'application/json', + 'X-Restli-Protocol-Version': '2.0.0', + }, + body: JSON.stringify(postData), + }) + + if (!response.ok) { + const error = await response.text() + return { + success: false, + output: {}, + error: `LinkedIn API error: ${error}`, + } + } + + const result = await response.json() + + return { + success: true, + output: { + postId: result.id, + }, + } + } catch (error) { + return { + success: false, + output: {}, + error: error instanceof Error ? error.message : 'Unknown error', + } + } + }, + + transformResponse: async (response: Response): Promise => { + // This handles the initial profile fetch response + if (!response.ok) { + return { + success: false, + output: {}, + error: `Failed to fetch profile: ${response.statusText}`, + } + } + + const profile = await response.json() + + // Return profile data for postProcess to use + return { + success: true, + output: profile, + } + }, +} diff --git a/apps/sim/tools/linkedin/types.ts b/apps/sim/tools/linkedin/types.ts new file mode 100644 index 0000000000..4ce9cfcc92 --- /dev/null +++ b/apps/sim/tools/linkedin/types.ts @@ -0,0 +1,89 @@ +import type { ToolResponse } from '@/tools/types' + +export interface LinkedInProfile { + sub: string + name: string + given_name: string + family_name: string + email?: string + picture?: string + email_verified?: boolean +} + +export interface LinkedInPost { + author: string // URN format: urn:li:person:abc123 + lifecycleState: 'PUBLISHED' + specificContent: { + 'com.linkedin.ugc.ShareContent': { + shareCommentary: { + text: string + } + shareMediaCategory: 'NONE' | 'ARTICLE' | 'IMAGE' + media?: Array<{ + status: 'READY' + description: { + text: string + } + media: string // URN format + title: { + text: string + } + }> + } + } + visibility: { + 'com.linkedin.ugc.MemberNetworkVisibility': 'PUBLIC' | 'CONNECTIONS' + } +} + +export type LinkedInResponse = { + success: boolean + output: { + postId?: string + profile?: { + id: string + name: string + email?: string + picture?: string + } + } + error?: string +} + +// Tool-specific type definitions +export interface LinkedInProfileOutput { + profile?: { + id: string + name?: string + email?: string + picture?: string + } + sub?: string + id?: string + [key: string]: unknown +} + +export interface SharePostParams { + accessToken: string + text: string + visibility?: 'PUBLIC' | 'CONNECTIONS' | 'LOGGED_IN' + mediaUrls?: string +} + +export interface SharePostResponse extends ToolResponse { + output: { + postId?: string + postUrl?: string + visibility?: string + } +} + +export interface GetProfileParams { + accessToken: string +} + +export interface GetProfileResponse extends ToolResponse { + output: LinkedInProfileOutput +} + +export type ProfileIdExtractor = (output: unknown) => string | null diff --git a/apps/sim/tools/mailchimp/add_member.ts b/apps/sim/tools/mailchimp/add_member.ts index 226ab6dceb..7a917f00ca 100644 --- a/apps/sim/tools/mailchimp/add_member.ts +++ b/apps/sim/tools/mailchimp/add_member.ts @@ -1,6 +1,6 @@ import { createLogger } from '@/lib/logs/console/logger' import type { ToolConfig } from '@/tools/types' -import { buildMailchimpUrl, handleMailchimpError } from './types' +import { buildMailchimpUrl, handleMailchimpError, type MailchimpMember } from './types' const logger = createLogger('MailchimpAddMember') @@ -16,7 +16,7 @@ export interface MailchimpAddMemberParams { export interface MailchimpAddMemberResponse { success: boolean output: { - member: any + member: MailchimpMember metadata: { operation: 'add_member' subscriberHash: string @@ -81,7 +81,7 @@ export const mailchimpAddMemberTool: ToolConfig< 'Content-Type': 'application/json', }), body: (params) => { - const body: any = { + const body: Record = { email_address: params.emailAddress, status: params.status, } diff --git a/apps/sim/tools/mailchimp/add_or_update_member.ts b/apps/sim/tools/mailchimp/add_or_update_member.ts index ae5a786544..a4b3daf7ac 100644 --- a/apps/sim/tools/mailchimp/add_or_update_member.ts +++ b/apps/sim/tools/mailchimp/add_or_update_member.ts @@ -1,6 +1,6 @@ import { createLogger } from '@/lib/logs/console/logger' import type { ToolConfig } from '@/tools/types' -import { buildMailchimpUrl, handleMailchimpError } from './types' +import { buildMailchimpUrl, handleMailchimpError, type MailchimpMember } from './types' const logger = createLogger('MailchimpAddOrUpdateMember') @@ -17,7 +17,7 @@ export interface MailchimpAddOrUpdateMemberParams { export interface MailchimpAddOrUpdateMemberResponse { success: boolean output: { - member: any + member: MailchimpMember metadata: { operation: 'add_or_update_member' subscriberHash: string @@ -89,7 +89,7 @@ export const mailchimpAddOrUpdateMemberTool: ToolConfig< 'Content-Type': 'application/json', }), body: (params) => { - const body: any = { + const body: Record = { email_address: params.emailAddress, status_if_new: params.statusIfNew, } diff --git a/apps/sim/tools/mailchimp/add_segment_member.ts b/apps/sim/tools/mailchimp/add_segment_member.ts index c5ea3d686a..0ab705a297 100644 --- a/apps/sim/tools/mailchimp/add_segment_member.ts +++ b/apps/sim/tools/mailchimp/add_segment_member.ts @@ -1,6 +1,6 @@ import { createLogger } from '@/lib/logs/console/logger' import type { ToolConfig } from '@/tools/types' -import { buildMailchimpUrl, handleMailchimpError } from './types' +import { buildMailchimpUrl, handleMailchimpError, type MailchimpMember } from './types' const logger = createLogger('MailchimpAddSegmentMember') @@ -14,7 +14,7 @@ export interface MailchimpAddSegmentMemberParams { export interface MailchimpAddSegmentMemberResponse { success: boolean output: { - member: any + member: MailchimpMember metadata: { operation: 'add_segment_member' segmentId: string diff --git a/apps/sim/tools/mailchimp/add_subscriber_to_automation.ts b/apps/sim/tools/mailchimp/add_subscriber_to_automation.ts index 81152a8985..8d84ec807a 100644 --- a/apps/sim/tools/mailchimp/add_subscriber_to_automation.ts +++ b/apps/sim/tools/mailchimp/add_subscriber_to_automation.ts @@ -1,5 +1,6 @@ import { createLogger } from '@/lib/logs/console/logger' import type { ToolConfig } from '@/tools/types' +import type { MailchimpMember } from './types' import { buildMailchimpUrl, handleMailchimpError } from './types' const logger = createLogger('MailchimpAddSubscriberToAutomation') @@ -14,7 +15,7 @@ export interface MailchimpAddSubscriberToAutomationParams { export interface MailchimpAddSubscriberToAutomationResponse { success: boolean output: { - subscriber: any + subscriber: MailchimpMember metadata: { operation: 'add_subscriber_to_automation' workflowId: string diff --git a/apps/sim/tools/mailchimp/create_audience.ts b/apps/sim/tools/mailchimp/create_audience.ts index 17310ec932..bb3d827f75 100644 --- a/apps/sim/tools/mailchimp/create_audience.ts +++ b/apps/sim/tools/mailchimp/create_audience.ts @@ -1,5 +1,6 @@ import { createLogger } from '@/lib/logs/console/logger' import type { ToolConfig } from '@/tools/types' +import type { MailchimpAudience } from './types' import { buildMailchimpUrl, handleMailchimpError } from './types' const logger = createLogger('MailchimpCreateAudience') @@ -16,7 +17,7 @@ export interface MailchimpCreateAudienceParams { export interface MailchimpCreateAudienceResponse { success: boolean output: { - list: any + list: MailchimpAudience metadata: { operation: 'create_audience' listId: string @@ -81,7 +82,7 @@ export const mailchimpCreateAudienceTool: ToolConfig< 'Content-Type': 'application/json', }), body: (params) => { - const body: any = { + const body: Record = { name: params.audienceName, permission_reminder: params.permissionReminder, email_type_option: params.emailTypeOption === 'true', diff --git a/apps/sim/tools/mailchimp/create_batch_operation.ts b/apps/sim/tools/mailchimp/create_batch_operation.ts index 5e49f871b1..1da6c56ff4 100644 --- a/apps/sim/tools/mailchimp/create_batch_operation.ts +++ b/apps/sim/tools/mailchimp/create_batch_operation.ts @@ -1,5 +1,6 @@ import { createLogger } from '@/lib/logs/console/logger' import type { ToolConfig } from '@/tools/types' +import type { MailchimpBatchOperation } from './types' import { buildMailchimpUrl, handleMailchimpError } from './types' const logger = createLogger('MailchimpCreateBatchOperation') @@ -12,7 +13,7 @@ export interface MailchimpCreateBatchOperationParams { export interface MailchimpCreateBatchOperationResponse { success: boolean output: { - batch: any + batch: MailchimpBatchOperation metadata: { operation: 'create_batch_operation' batchId: string diff --git a/apps/sim/tools/mailchimp/create_campaign.ts b/apps/sim/tools/mailchimp/create_campaign.ts index add7e5dce8..fce2b86fee 100644 --- a/apps/sim/tools/mailchimp/create_campaign.ts +++ b/apps/sim/tools/mailchimp/create_campaign.ts @@ -1,6 +1,6 @@ import { createLogger } from '@/lib/logs/console/logger' import type { ToolConfig } from '@/tools/types' -import { buildMailchimpUrl, handleMailchimpError } from './types' +import { buildMailchimpUrl, handleMailchimpError, type MailchimpCampaign } from './types' const logger = createLogger('MailchimpCreateCampaign') @@ -14,7 +14,7 @@ export interface MailchimpCreateCampaignParams { export interface MailchimpCreateCampaignResponse { success: boolean output: { - campaign: any + campaign: MailchimpCampaign metadata: { operation: 'create_campaign' campaignId: string @@ -67,7 +67,7 @@ export const mailchimpCreateCampaignTool: ToolConfig< 'Content-Type': 'application/json', }), body: (params) => { - const body: any = { + const body: Record = { type: params.campaignType, } diff --git a/apps/sim/tools/mailchimp/create_interest.ts b/apps/sim/tools/mailchimp/create_interest.ts index 2845a347c4..c29c562bee 100644 --- a/apps/sim/tools/mailchimp/create_interest.ts +++ b/apps/sim/tools/mailchimp/create_interest.ts @@ -1,5 +1,6 @@ import { createLogger } from '@/lib/logs/console/logger' import type { ToolConfig } from '@/tools/types' +import type { MailchimpInterest } from './types' import { buildMailchimpUrl, handleMailchimpError } from './types' const logger = createLogger('MailchimpCreateInterest') @@ -14,7 +15,7 @@ export interface MailchimpCreateInterestParams { export interface MailchimpCreateInterestResponse { success: boolean output: { - interest: any + interest: MailchimpInterest metadata: { operation: 'create_interest' interestId: string diff --git a/apps/sim/tools/mailchimp/create_interest_category.ts b/apps/sim/tools/mailchimp/create_interest_category.ts index 2fb3b147b4..f33a6e7342 100644 --- a/apps/sim/tools/mailchimp/create_interest_category.ts +++ b/apps/sim/tools/mailchimp/create_interest_category.ts @@ -1,5 +1,6 @@ import { createLogger } from '@/lib/logs/console/logger' import type { ToolConfig } from '@/tools/types' +import type { MailchimpInterestCategory } from './types' import { buildMailchimpUrl, handleMailchimpError } from './types' const logger = createLogger('MailchimpCreateInterestCategory') @@ -14,7 +15,7 @@ export interface MailchimpCreateInterestCategoryParams { export interface MailchimpCreateInterestCategoryResponse { success: boolean output: { - category: any + category: MailchimpInterestCategory metadata: { operation: 'create_interest_category' interestCategoryId: string diff --git a/apps/sim/tools/mailchimp/create_landing_page.ts b/apps/sim/tools/mailchimp/create_landing_page.ts index 5ed9ca3f21..c2895c8cc4 100644 --- a/apps/sim/tools/mailchimp/create_landing_page.ts +++ b/apps/sim/tools/mailchimp/create_landing_page.ts @@ -1,5 +1,6 @@ import { createLogger } from '@/lib/logs/console/logger' import type { ToolConfig } from '@/tools/types' +import type { MailchimpLandingPage } from './types' import { buildMailchimpUrl, handleMailchimpError } from './types' const logger = createLogger('MailchimpCreateLandingPage') @@ -13,7 +14,7 @@ export interface MailchimpCreateLandingPageParams { export interface MailchimpCreateLandingPageResponse { success: boolean output: { - landingPage: any + landingPage: MailchimpLandingPage metadata: { operation: 'create_landing_page' pageId: string @@ -60,7 +61,7 @@ export const mailchimpCreateLandingPageTool: ToolConfig< 'Content-Type': 'application/json', }), body: (params) => { - const body: any = { + const body: Record = { type: params.landingPageType, } diff --git a/apps/sim/tools/mailchimp/create_merge_field.ts b/apps/sim/tools/mailchimp/create_merge_field.ts index d069404ab2..d409c96ecb 100644 --- a/apps/sim/tools/mailchimp/create_merge_field.ts +++ b/apps/sim/tools/mailchimp/create_merge_field.ts @@ -1,5 +1,6 @@ import { createLogger } from '@/lib/logs/console/logger' import type { ToolConfig } from '@/tools/types' +import type { MailchimpMergeField } from './types' import { buildMailchimpUrl, handleMailchimpError } from './types' const logger = createLogger('MailchimpCreateMergeField') @@ -14,7 +15,7 @@ export interface MailchimpCreateMergeFieldParams { export interface MailchimpCreateMergeFieldResponse { success: boolean output: { - mergeField: any + mergeField: MailchimpMergeField metadata: { operation: 'create_merge_field' mergeId: string diff --git a/apps/sim/tools/mailchimp/create_segment.ts b/apps/sim/tools/mailchimp/create_segment.ts index 4c3afb767a..c278444806 100644 --- a/apps/sim/tools/mailchimp/create_segment.ts +++ b/apps/sim/tools/mailchimp/create_segment.ts @@ -1,5 +1,6 @@ import { createLogger } from '@/lib/logs/console/logger' import type { ToolConfig } from '@/tools/types' +import type { MailchimpSegment } from './types' import { buildMailchimpUrl, handleMailchimpError } from './types' const logger = createLogger('MailchimpCreateSegment') @@ -14,7 +15,7 @@ export interface MailchimpCreateSegmentParams { export interface MailchimpCreateSegmentResponse { success: boolean output: { - segment: any + segment: MailchimpSegment metadata: { operation: 'create_segment' segmentId: string @@ -67,7 +68,7 @@ export const mailchimpCreateSegmentTool: ToolConfig< 'Content-Type': 'application/json', }), body: (params) => { - const body: any = { + const body: Record = { name: params.segmentName, } diff --git a/apps/sim/tools/mailchimp/get_audience.ts b/apps/sim/tools/mailchimp/get_audience.ts index daf71dd4b2..c4f92bc6be 100644 --- a/apps/sim/tools/mailchimp/get_audience.ts +++ b/apps/sim/tools/mailchimp/get_audience.ts @@ -1,5 +1,6 @@ import { createLogger } from '@/lib/logs/console/logger' import type { ToolConfig } from '@/tools/types' +import type { MailchimpAudience } from './types' import { buildMailchimpUrl, handleMailchimpError } from './types' const logger = createLogger('MailchimpGetAudience') @@ -12,7 +13,7 @@ export interface MailchimpGetAudienceParams { export interface MailchimpGetAudienceResponse { success: boolean output: { - list: any + list: MailchimpAudience metadata: { operation: 'get_audience' listId: string diff --git a/apps/sim/tools/mailchimp/get_audiences.ts b/apps/sim/tools/mailchimp/get_audiences.ts index 971d7a528d..cf9383c96a 100644 --- a/apps/sim/tools/mailchimp/get_audiences.ts +++ b/apps/sim/tools/mailchimp/get_audiences.ts @@ -1,5 +1,6 @@ import { createLogger } from '@/lib/logs/console/logger' import type { ToolConfig } from '@/tools/types' +import type { MailchimpAudience } from './types' import { buildMailchimpUrl, handleMailchimpError } from './types' const logger = createLogger('MailchimpGetAudiences') @@ -13,7 +14,7 @@ export interface MailchimpGetAudiencesParams { export interface MailchimpGetAudiencesResponse { success: boolean output: { - lists: any[] + lists: MailchimpAudience[] totalItems: number metadata: { operation: 'get_audiences' diff --git a/apps/sim/tools/mailchimp/get_automation.ts b/apps/sim/tools/mailchimp/get_automation.ts index 9b05f9f5ea..dae107aa63 100644 --- a/apps/sim/tools/mailchimp/get_automation.ts +++ b/apps/sim/tools/mailchimp/get_automation.ts @@ -1,5 +1,6 @@ import { createLogger } from '@/lib/logs/console/logger' import type { ToolConfig } from '@/tools/types' +import type { MailchimpAutomation } from './types' import { buildMailchimpUrl, handleMailchimpError } from './types' const logger = createLogger('MailchimpGetAutomation') @@ -12,7 +13,7 @@ export interface MailchimpGetAutomationParams { export interface MailchimpGetAutomationResponse { success: boolean output: { - automation: any + automation: MailchimpAutomation metadata: { operation: 'get_automation' workflowId: string diff --git a/apps/sim/tools/mailchimp/get_automations.ts b/apps/sim/tools/mailchimp/get_automations.ts index ea47a87133..4ae25e30db 100644 --- a/apps/sim/tools/mailchimp/get_automations.ts +++ b/apps/sim/tools/mailchimp/get_automations.ts @@ -1,5 +1,6 @@ import { createLogger } from '@/lib/logs/console/logger' import type { ToolConfig } from '@/tools/types' +import type { MailchimpAutomation } from './types' import { buildMailchimpUrl, handleMailchimpError } from './types' const logger = createLogger('MailchimpGetAutomations') @@ -13,7 +14,7 @@ export interface MailchimpGetAutomationsParams { export interface MailchimpGetAutomationsResponse { success: boolean output: { - automations: any[] + automations: MailchimpAutomation[] totalItems: number metadata: { operation: 'get_automations' diff --git a/apps/sim/tools/mailchimp/get_batch_operation.ts b/apps/sim/tools/mailchimp/get_batch_operation.ts index 4e1ccdd089..a9c478d74d 100644 --- a/apps/sim/tools/mailchimp/get_batch_operation.ts +++ b/apps/sim/tools/mailchimp/get_batch_operation.ts @@ -1,5 +1,6 @@ import { createLogger } from '@/lib/logs/console/logger' import type { ToolConfig } from '@/tools/types' +import type { MailchimpBatchOperation } from './types' import { buildMailchimpUrl, handleMailchimpError } from './types' const logger = createLogger('MailchimpGetBatchOperation') @@ -12,7 +13,7 @@ export interface MailchimpGetBatchOperationParams { export interface MailchimpGetBatchOperationResponse { success: boolean output: { - batch: any + batch: MailchimpBatchOperation metadata: { operation: 'get_batch_operation' batchId: string diff --git a/apps/sim/tools/mailchimp/get_batch_operations.ts b/apps/sim/tools/mailchimp/get_batch_operations.ts index 0e98715d86..c4ef501ef8 100644 --- a/apps/sim/tools/mailchimp/get_batch_operations.ts +++ b/apps/sim/tools/mailchimp/get_batch_operations.ts @@ -1,5 +1,6 @@ import { createLogger } from '@/lib/logs/console/logger' import type { ToolConfig } from '@/tools/types' +import type { MailchimpBatchOperation } from './types' import { buildMailchimpUrl, handleMailchimpError } from './types' const logger = createLogger('MailchimpGetBatchOperations') @@ -13,7 +14,7 @@ export interface MailchimpGetBatchOperationsParams { export interface MailchimpGetBatchOperationsResponse { success: boolean output: { - batches: any[] + batches: MailchimpBatchOperation[] totalItems: number metadata: { operation: 'get_batch_operations' diff --git a/apps/sim/tools/mailchimp/get_campaign.ts b/apps/sim/tools/mailchimp/get_campaign.ts index ec40e0272f..4c4ac68542 100644 --- a/apps/sim/tools/mailchimp/get_campaign.ts +++ b/apps/sim/tools/mailchimp/get_campaign.ts @@ -1,6 +1,6 @@ import { createLogger } from '@/lib/logs/console/logger' import type { ToolConfig } from '@/tools/types' -import { buildMailchimpUrl, handleMailchimpError } from './types' +import { buildMailchimpUrl, handleMailchimpError, type MailchimpCampaign } from './types' const logger = createLogger('MailchimpGetCampaign') @@ -12,7 +12,7 @@ export interface MailchimpGetCampaignParams { export interface MailchimpGetCampaignResponse { success: boolean output: { - campaign: any + campaign: MailchimpCampaign metadata: { operation: 'get_campaign' campaignId: string diff --git a/apps/sim/tools/mailchimp/get_campaign_content.ts b/apps/sim/tools/mailchimp/get_campaign_content.ts index 706b8b5ae7..3e0a33bf5e 100644 --- a/apps/sim/tools/mailchimp/get_campaign_content.ts +++ b/apps/sim/tools/mailchimp/get_campaign_content.ts @@ -1,6 +1,6 @@ import { createLogger } from '@/lib/logs/console/logger' import type { ToolConfig } from '@/tools/types' -import { buildMailchimpUrl, handleMailchimpError } from './types' +import { buildMailchimpUrl, handleMailchimpError, type MailchimpCampaignContent } from './types' const logger = createLogger('MailchimpGetCampaignContent') @@ -12,7 +12,7 @@ export interface MailchimpGetCampaignContentParams { export interface MailchimpGetCampaignContentResponse { success: boolean output: { - content: any + content: MailchimpCampaignContent metadata: { operation: 'get_campaign_content' campaignId: string diff --git a/apps/sim/tools/mailchimp/get_campaign_report.ts b/apps/sim/tools/mailchimp/get_campaign_report.ts index 852a9c912f..306baef7cc 100644 --- a/apps/sim/tools/mailchimp/get_campaign_report.ts +++ b/apps/sim/tools/mailchimp/get_campaign_report.ts @@ -1,6 +1,6 @@ import { createLogger } from '@/lib/logs/console/logger' import type { ToolConfig } from '@/tools/types' -import { buildMailchimpUrl, handleMailchimpError } from './types' +import { buildMailchimpUrl, handleMailchimpError, type MailchimpCampaignReport } from './types' const logger = createLogger('MailchimpGetCampaignReport') @@ -12,7 +12,7 @@ export interface MailchimpGetCampaignReportParams { export interface MailchimpGetCampaignReportResponse { success: boolean output: { - report: any + report: MailchimpCampaignReport metadata: { operation: 'get_campaign_report' campaignId: string diff --git a/apps/sim/tools/mailchimp/get_campaign_reports.ts b/apps/sim/tools/mailchimp/get_campaign_reports.ts index d83a2acd2c..d5a1bd152a 100644 --- a/apps/sim/tools/mailchimp/get_campaign_reports.ts +++ b/apps/sim/tools/mailchimp/get_campaign_reports.ts @@ -1,6 +1,6 @@ import { createLogger } from '@/lib/logs/console/logger' import type { ToolConfig } from '@/tools/types' -import { buildMailchimpUrl, handleMailchimpError } from './types' +import { buildMailchimpUrl, handleMailchimpError, type MailchimpCampaignReport } from './types' const logger = createLogger('MailchimpGetCampaignReports') @@ -13,7 +13,7 @@ export interface MailchimpGetCampaignReportsParams { export interface MailchimpGetCampaignReportsResponse { success: boolean output: { - reports: any[] + reports: MailchimpCampaignReport[] totalItems: number metadata: { operation: 'get_campaign_reports' diff --git a/apps/sim/tools/mailchimp/get_campaigns.ts b/apps/sim/tools/mailchimp/get_campaigns.ts index bc725ab7bc..65b5404240 100644 --- a/apps/sim/tools/mailchimp/get_campaigns.ts +++ b/apps/sim/tools/mailchimp/get_campaigns.ts @@ -1,6 +1,6 @@ import { createLogger } from '@/lib/logs/console/logger' import type { ToolConfig } from '@/tools/types' -import { buildMailchimpUrl, handleMailchimpError } from './types' +import { buildMailchimpUrl, handleMailchimpError, type MailchimpCampaign } from './types' const logger = createLogger('MailchimpGetCampaigns') @@ -15,7 +15,7 @@ export interface MailchimpGetCampaignsParams { export interface MailchimpGetCampaignsResponse { success: boolean output: { - campaigns: any[] + campaigns: MailchimpCampaign[] totalItems: number metadata: { operation: 'get_campaigns' diff --git a/apps/sim/tools/mailchimp/get_interest.ts b/apps/sim/tools/mailchimp/get_interest.ts index bdde022c76..8e1b1bea1d 100644 --- a/apps/sim/tools/mailchimp/get_interest.ts +++ b/apps/sim/tools/mailchimp/get_interest.ts @@ -1,5 +1,6 @@ import { createLogger } from '@/lib/logs/console/logger' import type { ToolConfig } from '@/tools/types' +import type { MailchimpInterest } from './types' import { buildMailchimpUrl, handleMailchimpError } from './types' const logger = createLogger('MailchimpGetInterest') @@ -14,7 +15,7 @@ export interface MailchimpGetInterestParams { export interface MailchimpGetInterestResponse { success: boolean output: { - interest: any + interest: MailchimpInterest metadata: { operation: 'get_interest' interestId: string diff --git a/apps/sim/tools/mailchimp/get_interest_category.ts b/apps/sim/tools/mailchimp/get_interest_category.ts index 6d51d0457f..e550a3e3b6 100644 --- a/apps/sim/tools/mailchimp/get_interest_category.ts +++ b/apps/sim/tools/mailchimp/get_interest_category.ts @@ -1,5 +1,6 @@ import { createLogger } from '@/lib/logs/console/logger' import type { ToolConfig } from '@/tools/types' +import type { MailchimpInterestCategory } from './types' import { buildMailchimpUrl, handleMailchimpError } from './types' const logger = createLogger('MailchimpGetInterestCategory') @@ -13,7 +14,7 @@ export interface MailchimpGetInterestCategoryParams { export interface MailchimpGetInterestCategoryResponse { success: boolean output: { - category: any + category: MailchimpInterestCategory metadata: { operation: 'get_interest_category' interestCategoryId: string diff --git a/apps/sim/tools/mailchimp/get_landing_page.ts b/apps/sim/tools/mailchimp/get_landing_page.ts index f3ec0cf37b..c8abd6265e 100644 --- a/apps/sim/tools/mailchimp/get_landing_page.ts +++ b/apps/sim/tools/mailchimp/get_landing_page.ts @@ -1,5 +1,6 @@ import { createLogger } from '@/lib/logs/console/logger' import type { ToolConfig } from '@/tools/types' +import type { MailchimpLandingPage } from './types' import { buildMailchimpUrl, handleMailchimpError } from './types' const logger = createLogger('MailchimpGetLandingPage') @@ -12,7 +13,7 @@ export interface MailchimpGetLandingPageParams { export interface MailchimpGetLandingPageResponse { success: boolean output: { - landingPage: any + landingPage: MailchimpLandingPage metadata: { operation: 'get_landing_page' pageId: string diff --git a/apps/sim/tools/mailchimp/get_landing_pages.ts b/apps/sim/tools/mailchimp/get_landing_pages.ts index b8095cdd9c..7147e5d005 100644 --- a/apps/sim/tools/mailchimp/get_landing_pages.ts +++ b/apps/sim/tools/mailchimp/get_landing_pages.ts @@ -1,5 +1,6 @@ import { createLogger } from '@/lib/logs/console/logger' import type { ToolConfig } from '@/tools/types' +import type { MailchimpLandingPage } from './types' import { buildMailchimpUrl, handleMailchimpError } from './types' const logger = createLogger('MailchimpGetLandingPages') @@ -13,7 +14,7 @@ export interface MailchimpGetLandingPagesParams { export interface MailchimpGetLandingPagesResponse { success: boolean output: { - landingPages: any[] + landingPages: MailchimpLandingPage[] totalItems: number metadata: { operation: 'get_landing_pages' diff --git a/apps/sim/tools/mailchimp/get_member.ts b/apps/sim/tools/mailchimp/get_member.ts index 42a24a1eaa..8be49b13c2 100644 --- a/apps/sim/tools/mailchimp/get_member.ts +++ b/apps/sim/tools/mailchimp/get_member.ts @@ -1,6 +1,6 @@ import { createLogger } from '@/lib/logs/console/logger' import type { ToolConfig } from '@/tools/types' -import { buildMailchimpUrl, handleMailchimpError } from './types' +import { buildMailchimpUrl, handleMailchimpError, type MailchimpMember } from './types' const logger = createLogger('MailchimpGetMember') @@ -13,7 +13,7 @@ export interface MailchimpGetMemberParams { export interface MailchimpGetMemberResponse { success: boolean output: { - member: any + member: MailchimpMember metadata: { operation: 'get_member' subscriberHash: string diff --git a/apps/sim/tools/mailchimp/get_member_tags.ts b/apps/sim/tools/mailchimp/get_member_tags.ts index 850f7e23b9..f4816fe778 100644 --- a/apps/sim/tools/mailchimp/get_member_tags.ts +++ b/apps/sim/tools/mailchimp/get_member_tags.ts @@ -1,6 +1,6 @@ import { createLogger } from '@/lib/logs/console/logger' import type { ToolConfig } from '@/tools/types' -import { buildMailchimpUrl, handleMailchimpError } from './types' +import { buildMailchimpUrl, handleMailchimpError, type MailchimpTag } from './types' const logger = createLogger('MailchimpGetMemberTags') @@ -13,7 +13,7 @@ export interface MailchimpGetMemberTagsParams { export interface MailchimpGetMemberTagsResponse { success: boolean output: { - tags: any[] + tags: MailchimpTag[] totalItems: number metadata: { operation: 'get_member_tags' diff --git a/apps/sim/tools/mailchimp/get_members.ts b/apps/sim/tools/mailchimp/get_members.ts index 64fbaa7b3a..a7e31dcc3f 100644 --- a/apps/sim/tools/mailchimp/get_members.ts +++ b/apps/sim/tools/mailchimp/get_members.ts @@ -1,6 +1,6 @@ import { createLogger } from '@/lib/logs/console/logger' import type { ToolConfig } from '@/tools/types' -import { buildMailchimpUrl, handleMailchimpError } from './types' +import { buildMailchimpUrl, handleMailchimpError, type MailchimpMember } from './types' const logger = createLogger('MailchimpGetMembers') @@ -15,7 +15,7 @@ export interface MailchimpGetMembersParams { export interface MailchimpGetMembersResponse { success: boolean output: { - members: any[] + members: MailchimpMember[] totalItems: number metadata: { operation: 'get_members' diff --git a/apps/sim/tools/mailchimp/get_merge_fields.ts b/apps/sim/tools/mailchimp/get_merge_fields.ts index 8e1dbca19a..796429f03d 100644 --- a/apps/sim/tools/mailchimp/get_merge_fields.ts +++ b/apps/sim/tools/mailchimp/get_merge_fields.ts @@ -1,5 +1,6 @@ import { createLogger } from '@/lib/logs/console/logger' import type { ToolConfig } from '@/tools/types' +import type { MailchimpMergeField } from './types' import { buildMailchimpUrl, handleMailchimpError } from './types' const logger = createLogger('MailchimpGetMergeFields') @@ -14,7 +15,7 @@ export interface MailchimpGetMergeFieldsParams { export interface MailchimpGetMergeFieldsResponse { success: boolean output: { - mergeFields: any[] + mergeFields: MailchimpMergeField[] totalItems: number metadata: { operation: 'get_merge_fields' diff --git a/apps/sim/tools/mailchimp/get_segment.ts b/apps/sim/tools/mailchimp/get_segment.ts index ed2ba417ad..171e04bb8a 100644 --- a/apps/sim/tools/mailchimp/get_segment.ts +++ b/apps/sim/tools/mailchimp/get_segment.ts @@ -1,5 +1,6 @@ import { createLogger } from '@/lib/logs/console/logger' import type { ToolConfig } from '@/tools/types' +import type { MailchimpSegment } from './types' import { buildMailchimpUrl, handleMailchimpError } from './types' const logger = createLogger('MailchimpGetSegment') @@ -13,7 +14,7 @@ export interface MailchimpGetSegmentParams { export interface MailchimpGetSegmentResponse { success: boolean output: { - segment: any + segment: MailchimpSegment metadata: { operation: 'get_segment' segmentId: string diff --git a/apps/sim/tools/mailchimp/get_segment_members.ts b/apps/sim/tools/mailchimp/get_segment_members.ts index 8a594c8fb2..4c51959730 100644 --- a/apps/sim/tools/mailchimp/get_segment_members.ts +++ b/apps/sim/tools/mailchimp/get_segment_members.ts @@ -1,5 +1,6 @@ import { createLogger } from '@/lib/logs/console/logger' import type { ToolConfig } from '@/tools/types' +import type { MailchimpMember } from './types' import { buildMailchimpUrl, handleMailchimpError } from './types' const logger = createLogger('MailchimpGetSegmentMembers') @@ -15,7 +16,7 @@ export interface MailchimpGetSegmentMembersParams { export interface MailchimpGetSegmentMembersResponse { success: boolean output: { - members: any[] + members: MailchimpMember[] totalItems: number metadata: { operation: 'get_segment_members' diff --git a/apps/sim/tools/mailchimp/get_template.ts b/apps/sim/tools/mailchimp/get_template.ts index 31a4f79389..9e079a23e4 100644 --- a/apps/sim/tools/mailchimp/get_template.ts +++ b/apps/sim/tools/mailchimp/get_template.ts @@ -1,5 +1,6 @@ import { createLogger } from '@/lib/logs/console/logger' import type { ToolConfig } from '@/tools/types' +import type { MailchimpTemplate } from './types' import { buildMailchimpUrl, handleMailchimpError } from './types' const logger = createLogger('MailchimpGetTemplate') @@ -12,7 +13,7 @@ export interface MailchimpGetTemplateParams { export interface MailchimpGetTemplateResponse { success: boolean output: { - template: any + template: MailchimpTemplate metadata: { operation: 'get_template' templateId: string diff --git a/apps/sim/tools/mailchimp/get_templates.ts b/apps/sim/tools/mailchimp/get_templates.ts index db181474c6..8be121bf43 100644 --- a/apps/sim/tools/mailchimp/get_templates.ts +++ b/apps/sim/tools/mailchimp/get_templates.ts @@ -1,5 +1,6 @@ import { createLogger } from '@/lib/logs/console/logger' import type { ToolConfig } from '@/tools/types' +import type { MailchimpTemplate } from './types' import { buildMailchimpUrl, handleMailchimpError } from './types' const logger = createLogger('MailchimpGetTemplates') @@ -13,7 +14,7 @@ export interface MailchimpGetTemplatesParams { export interface MailchimpGetTemplatesResponse { success: boolean output: { - templates: any[] + templates: MailchimpTemplate[] totalItems: number metadata: { operation: 'get_templates' diff --git a/apps/sim/tools/mailchimp/set_campaign_content.ts b/apps/sim/tools/mailchimp/set_campaign_content.ts index 737756c548..9dcf0a9d82 100644 --- a/apps/sim/tools/mailchimp/set_campaign_content.ts +++ b/apps/sim/tools/mailchimp/set_campaign_content.ts @@ -1,6 +1,6 @@ import { createLogger } from '@/lib/logs/console/logger' import type { ToolConfig } from '@/tools/types' -import { buildMailchimpUrl, handleMailchimpError } from './types' +import { buildMailchimpUrl, handleMailchimpError, type MailchimpCampaignContent } from './types' const logger = createLogger('MailchimpSetCampaignContent') @@ -15,7 +15,7 @@ export interface MailchimpSetCampaignContentParams { export interface MailchimpSetCampaignContentResponse { success: boolean output: { - content: any + content: MailchimpCampaignContent metadata: { operation: 'set_campaign_content' campaignId: string @@ -74,7 +74,7 @@ export const mailchimpSetCampaignContentTool: ToolConfig< 'Content-Type': 'application/json', }), body: (params) => { - const body: any = {} + const body: Record = {} if (params.html) body.html = params.html if (params.plainText) body.plain_text = params.plainText diff --git a/apps/sim/tools/mailchimp/types.ts b/apps/sim/tools/mailchimp/types.ts index 2348e68639..7fcdb9d5d8 100644 --- a/apps/sim/tools/mailchimp/types.ts +++ b/apps/sim/tools/mailchimp/types.ts @@ -23,12 +23,377 @@ export interface MailchimpResponse { paging?: MailchimpPagingInfo metadata: { operation: string - [key: string]: any + [key: string]: unknown } success: boolean } } +// Member/Subscriber +export interface MailchimpMember { + id: string + email_address: string + unique_email_id?: string + status: 'subscribed' | 'unsubscribed' | 'cleaned' | 'pending' + merge_fields?: Record + interests?: Record + stats?: { + avg_open_rate?: number + avg_click_rate?: number + } + ip_signup?: string + timestamp_signup?: string + ip_opt?: string + timestamp_opt?: string + member_rating?: number + last_changed?: string + language?: string + vip?: boolean + email_client?: string + location?: { + latitude?: number + longitude?: number + gmtoff?: number + dstoff?: number + country_code?: string + timezone?: string + } + tags?: Array<{ id: number; name: string }> + [key: string]: unknown +} + +// Audience/List +export interface MailchimpAudience { + id: string + name: string + contact: { + company: string + address1: string + address2?: string + city: string + state: string + zip: string + country: string + phone?: string + } + permission_reminder: string + campaign_defaults: { + from_name: string + from_email: string + subject: string + language: string + } + email_type_option: boolean + stats?: { + member_count?: number + unsubscribe_count?: number + cleaned_count?: number + member_count_since_send?: number + unsubscribe_count_since_send?: number + cleaned_count_since_send?: number + campaign_count?: number + campaign_last_sent?: string + merge_field_count?: number + avg_sub_rate?: number + avg_unsub_rate?: number + target_sub_rate?: number + open_rate?: number + click_rate?: number + last_sub_date?: string + last_unsub_date?: string + } + date_created?: string + list_rating?: number + subscribe_url_short?: string + subscribe_url_long?: string + visibility?: string + [key: string]: unknown +} + +// Campaign +export interface MailchimpCampaign { + id: string + type: 'regular' | 'plaintext' | 'absplit' | 'rss' | 'variate' + create_time?: string + archive_url?: string + long_archive_url?: string + status: 'save' | 'paused' | 'schedule' | 'sending' | 'sent' + emails_sent?: number + send_time?: string + content_type?: string + recipients?: { + list_id: string + list_name?: string + segment_text?: string + recipient_count?: number + } + settings?: { + subject_line?: string + preview_text?: string + title?: string + from_name?: string + reply_to?: string + use_conversation?: boolean + to_name?: string + folder_id?: string + authenticate?: boolean + auto_footer?: boolean + inline_css?: boolean + auto_tweet?: boolean + fb_comments?: boolean + timewarp?: boolean + template_id?: number + drag_and_drop?: boolean + } + tracking?: { + opens?: boolean + html_clicks?: boolean + text_clicks?: boolean + goal_tracking?: boolean + ecomm360?: boolean + google_analytics?: string + clicktale?: string + } + [key: string]: unknown +} + +// Campaign Content +export interface MailchimpCampaignContent { + html?: string + plain_text?: string + archive_html?: string + [key: string]: unknown +} + +// Campaign Report +export interface MailchimpCampaignReport { + id: string + campaign_title?: string + type?: string + emails_sent?: number + abuse_reports?: number + unsubscribed?: number + send_time?: string + bounces?: { + hard_bounces?: number + soft_bounces?: number + syntax_errors?: number + } + forwards?: { + forwards_count?: number + forwards_opens?: number + } + opens?: { + opens_total?: number + unique_opens?: number + open_rate?: number + last_open?: string + } + clicks?: { + clicks_total?: number + unique_clicks?: number + unique_subscriber_clicks?: number + click_rate?: number + last_click?: string + } + list_stats?: { + sub_rate?: number + unsub_rate?: number + open_rate?: number + click_rate?: number + } + [key: string]: unknown +} + +// Automation +export interface MailchimpAutomation { + id: string + create_time?: string + start_time?: string + status: 'save' | 'paused' | 'sending' + emails_sent?: number + recipients?: { + list_id: string + list_name?: string + segment_opts?: unknown + } + settings?: { + title?: string + from_name?: string + reply_to?: string + use_conversation?: boolean + to_name?: string + authenticate?: boolean + auto_footer?: boolean + inline_css?: boolean + } + tracking?: { + opens?: boolean + html_clicks?: boolean + text_clicks?: boolean + goal_tracking?: boolean + ecomm360?: boolean + google_analytics?: string + clicktale?: string + } + [key: string]: unknown +} + +// Segment +export interface MailchimpSegment { + id: number + name: string + member_count?: number + type: 'saved' | 'static' | 'fuzzy' + created_at?: string + updated_at?: string + options?: { + match?: 'any' | 'all' + conditions?: Array<{ + condition_type?: string + field?: string + op?: string + value?: unknown + }> + } + list_id?: string + [key: string]: unknown +} + +// Template +export interface MailchimpTemplate { + id: number + type: string + name: string + drag_and_drop?: boolean + responsive?: boolean + category?: string + date_created?: string + date_edited?: string + created_by?: string + edited_by?: string + active?: boolean + folder_id?: string + thumbnail?: string + share_url?: string + [key: string]: unknown +} + +// Landing Page +export interface MailchimpLandingPage { + id: string + name: string + title?: string + description?: string + template_id?: number + status: 'draft' | 'published' | 'unpublished' + list_id?: string + store_id?: string + web_id?: number + created_at?: string + published_at?: string + unpublished_at?: string + updated_at?: string + url?: string + tracking?: { + opens?: boolean + html_clicks?: boolean + text_clicks?: boolean + goal_tracking?: boolean + ecomm360?: boolean + google_analytics?: string + clicktale?: string + } + [key: string]: unknown +} + +// Interest Category +export interface MailchimpInterestCategory { + list_id?: string + id: string + title: string + display_order?: number + type: 'checkboxes' | 'dropdown' | 'radio' | 'hidden' + [key: string]: unknown +} + +// Interest +export interface MailchimpInterest { + category_id?: string + list_id?: string + id: string + name: string + subscriber_count?: string + display_order?: number + [key: string]: unknown +} + +// Merge Field +export interface MailchimpMergeField { + merge_id?: number + tag: string + name: string + type: + | 'text' + | 'number' + | 'address' + | 'phone' + | 'date' + | 'url' + | 'imageurl' + | 'radio' + | 'dropdown' + | 'birthday' + | 'zip' + required?: boolean + default_value?: string + public?: boolean + display_order?: number + options?: { + default_country?: number + phone_format?: string + date_format?: string + choices?: string[] + size?: number + } + help_text?: string + list_id?: string + [key: string]: unknown +} + +// Batch Operation +export interface MailchimpBatchOperation { + id: string + status: 'pending' | 'preprocessing' | 'started' | 'finalizing' | 'finished' + total_operations?: number + finished_operations?: number + errored_operations?: number + submitted_at?: string + completed_at?: string + response_body_url?: string + [key: string]: unknown +} + +// Tag +export interface MailchimpTag { + id: number + name: string + [key: string]: unknown +} + +// Error Response +export interface MailchimpErrorResponse { + type?: string + title?: string + status?: number + detail?: string + instance?: string + errors?: Array<{ + field?: string + message?: string + }> +} + // Helper function to extract server prefix from API key export function extractServerPrefix(apiKey: string): string { const parts = apiKey.split('-') @@ -45,9 +410,11 @@ export function buildMailchimpUrl(apiKey: string, path: string): string { } // Helper function for consistent error handling -export function handleMailchimpError(data: any, status: number, operation: string): never { +export function handleMailchimpError(data: unknown, status: number, operation: string): never { logger.error(`Mailchimp API request failed for ${operation}`, { data, status }) - const errorMessage = data.detail || data.title || data.error || data.message || 'Unknown error' + const errorData = data as Record + const errorMessage = + errorData.detail || errorData.title || errorData.error || errorData.message || 'Unknown error' throw new Error(`Mailchimp ${operation} failed: ${errorMessage}`) } diff --git a/apps/sim/tools/mailchimp/unarchive_member.ts b/apps/sim/tools/mailchimp/unarchive_member.ts index da92094208..7f25767192 100644 --- a/apps/sim/tools/mailchimp/unarchive_member.ts +++ b/apps/sim/tools/mailchimp/unarchive_member.ts @@ -1,6 +1,6 @@ import { createLogger } from '@/lib/logs/console/logger' import type { ToolConfig } from '@/tools/types' -import { buildMailchimpUrl, handleMailchimpError } from './types' +import { buildMailchimpUrl, handleMailchimpError, type MailchimpMember } from './types' const logger = createLogger('MailchimpUnarchiveMember') @@ -15,7 +15,7 @@ export interface MailchimpUnarchiveMemberParams { export interface MailchimpUnarchiveMemberResponse { success: boolean output: { - member: any + member: MailchimpMember metadata: { operation: 'unarchive_member' subscriberHash: string diff --git a/apps/sim/tools/mailchimp/update_audience.ts b/apps/sim/tools/mailchimp/update_audience.ts index fe7b7a3828..1352443c19 100644 --- a/apps/sim/tools/mailchimp/update_audience.ts +++ b/apps/sim/tools/mailchimp/update_audience.ts @@ -1,5 +1,6 @@ import { createLogger } from '@/lib/logs/console/logger' import type { ToolConfig } from '@/tools/types' +import type { MailchimpAudience } from './types' import { buildMailchimpUrl, handleMailchimpError } from './types' const logger = createLogger('MailchimpUpdateAudience') @@ -16,7 +17,7 @@ export interface MailchimpUpdateAudienceParams { export interface MailchimpUpdateAudienceResponse { success: boolean output: { - list: any + list: MailchimpAudience metadata: { operation: 'update_audience' listId: string @@ -81,7 +82,7 @@ export const mailchimpUpdateAudienceTool: ToolConfig< 'Content-Type': 'application/json', }), body: (params) => { - const body: any = {} + const body: Record = {} if (params.audienceName) body.name = params.audienceName if (params.permissionReminder) body.permission_reminder = params.permissionReminder diff --git a/apps/sim/tools/mailchimp/update_campaign.ts b/apps/sim/tools/mailchimp/update_campaign.ts index 246c9d91fe..2040418c3b 100644 --- a/apps/sim/tools/mailchimp/update_campaign.ts +++ b/apps/sim/tools/mailchimp/update_campaign.ts @@ -1,6 +1,6 @@ import { createLogger } from '@/lib/logs/console/logger' import type { ToolConfig } from '@/tools/types' -import { buildMailchimpUrl, handleMailchimpError } from './types' +import { buildMailchimpUrl, handleMailchimpError, type MailchimpCampaign } from './types' const logger = createLogger('MailchimpUpdateCampaign') @@ -14,7 +14,7 @@ export interface MailchimpUpdateCampaignParams { export interface MailchimpUpdateCampaignResponse { success: boolean output: { - campaign: any + campaign: MailchimpCampaign metadata: { operation: 'update_campaign' campaignId: string @@ -67,7 +67,7 @@ export const mailchimpUpdateCampaignTool: ToolConfig< 'Content-Type': 'application/json', }), body: (params) => { - const body: any = {} + const body: Record = {} if (params.campaignSettings) { try { diff --git a/apps/sim/tools/mailchimp/update_interest.ts b/apps/sim/tools/mailchimp/update_interest.ts index ba9d03016c..5da1aaf49a 100644 --- a/apps/sim/tools/mailchimp/update_interest.ts +++ b/apps/sim/tools/mailchimp/update_interest.ts @@ -1,5 +1,6 @@ import { createLogger } from '@/lib/logs/console/logger' import type { ToolConfig } from '@/tools/types' +import type { MailchimpInterest } from './types' import { buildMailchimpUrl, handleMailchimpError } from './types' const logger = createLogger('MailchimpUpdateInterest') @@ -15,7 +16,7 @@ export interface MailchimpUpdateInterestParams { export interface MailchimpUpdateInterestResponse { success: boolean output: { - interest: any + interest: MailchimpInterest metadata: { operation: 'update_interest' interestId: string @@ -78,7 +79,7 @@ export const mailchimpUpdateInterestTool: ToolConfig< 'Content-Type': 'application/json', }), body: (params) => { - const body: any = {} + const body: Record = {} if (params.interestName) body.name = params.interestName diff --git a/apps/sim/tools/mailchimp/update_interest_category.ts b/apps/sim/tools/mailchimp/update_interest_category.ts index b21fa61226..898d36dc38 100644 --- a/apps/sim/tools/mailchimp/update_interest_category.ts +++ b/apps/sim/tools/mailchimp/update_interest_category.ts @@ -1,5 +1,6 @@ import { createLogger } from '@/lib/logs/console/logger' import type { ToolConfig } from '@/tools/types' +import type { MailchimpInterestCategory } from './types' import { buildMailchimpUrl, handleMailchimpError } from './types' const logger = createLogger('MailchimpUpdateInterestCategory') @@ -14,7 +15,7 @@ export interface MailchimpUpdateInterestCategoryParams { export interface MailchimpUpdateInterestCategoryResponse { success: boolean output: { - category: any + category: MailchimpInterestCategory metadata: { operation: 'update_interest_category' interestCategoryId: string @@ -71,7 +72,7 @@ export const mailchimpUpdateInterestCategoryTool: ToolConfig< 'Content-Type': 'application/json', }), body: (params) => { - const body: any = {} + const body: Record = {} if (params.interestCategoryTitle) body.title = params.interestCategoryTitle diff --git a/apps/sim/tools/mailchimp/update_landing_page.ts b/apps/sim/tools/mailchimp/update_landing_page.ts index 8d002653e7..a84fbd8112 100644 --- a/apps/sim/tools/mailchimp/update_landing_page.ts +++ b/apps/sim/tools/mailchimp/update_landing_page.ts @@ -1,5 +1,6 @@ import { createLogger } from '@/lib/logs/console/logger' import type { ToolConfig } from '@/tools/types' +import type { MailchimpLandingPage } from './types' import { buildMailchimpUrl, handleMailchimpError } from './types' const logger = createLogger('MailchimpUpdateLandingPage') @@ -13,7 +14,7 @@ export interface MailchimpUpdateLandingPageParams { export interface MailchimpUpdateLandingPageResponse { success: boolean output: { - landingPage: any + landingPage: MailchimpLandingPage metadata: { operation: 'update_landing_page' pageId: string @@ -60,7 +61,7 @@ export const mailchimpUpdateLandingPageTool: ToolConfig< 'Content-Type': 'application/json', }), body: (params) => { - const body: any = {} + const body: Record = {} if (params.landingPageTitle) body.title = params.landingPageTitle diff --git a/apps/sim/tools/mailchimp/update_member.ts b/apps/sim/tools/mailchimp/update_member.ts index 0483f8bf92..fe730b23bf 100644 --- a/apps/sim/tools/mailchimp/update_member.ts +++ b/apps/sim/tools/mailchimp/update_member.ts @@ -1,6 +1,6 @@ import { createLogger } from '@/lib/logs/console/logger' import type { ToolConfig } from '@/tools/types' -import { buildMailchimpUrl, handleMailchimpError } from './types' +import { buildMailchimpUrl, handleMailchimpError, type MailchimpMember } from './types' const logger = createLogger('MailchimpUpdateMember') @@ -17,7 +17,7 @@ export interface MailchimpUpdateMemberParams { export interface MailchimpUpdateMemberResponse { success: boolean output: { - member: any + member: MailchimpMember metadata: { operation: 'update_member' subscriberHash: string @@ -89,7 +89,7 @@ export const mailchimpUpdateMemberTool: ToolConfig< 'Content-Type': 'application/json', }), body: (params) => { - const body: any = {} + const body: Record = {} if (params.emailAddress) body.email_address = params.emailAddress if (params.status) body.status = params.status diff --git a/apps/sim/tools/mailchimp/update_merge_field.ts b/apps/sim/tools/mailchimp/update_merge_field.ts index 1b25460769..c1c266256b 100644 --- a/apps/sim/tools/mailchimp/update_merge_field.ts +++ b/apps/sim/tools/mailchimp/update_merge_field.ts @@ -1,5 +1,6 @@ import { createLogger } from '@/lib/logs/console/logger' import type { ToolConfig } from '@/tools/types' +import type { MailchimpMergeField } from './types' import { buildMailchimpUrl, handleMailchimpError } from './types' const logger = createLogger('MailchimpUpdateMergeField') @@ -14,7 +15,7 @@ export interface MailchimpUpdateMergeFieldParams { export interface MailchimpUpdateMergeFieldResponse { success: boolean output: { - mergeField: any + mergeField: MailchimpMergeField metadata: { operation: 'update_merge_field' mergeId: string @@ -68,7 +69,7 @@ export const mailchimpUpdateMergeFieldTool: ToolConfig< 'Content-Type': 'application/json', }), body: (params) => { - const body: any = {} + const body: Record = {} if (params.mergeName) body.name = params.mergeName diff --git a/apps/sim/tools/mailchimp/update_segment.ts b/apps/sim/tools/mailchimp/update_segment.ts index 90d237514c..ebac0e4b9e 100644 --- a/apps/sim/tools/mailchimp/update_segment.ts +++ b/apps/sim/tools/mailchimp/update_segment.ts @@ -1,5 +1,6 @@ import { createLogger } from '@/lib/logs/console/logger' import type { ToolConfig } from '@/tools/types' +import type { MailchimpSegment } from './types' import { buildMailchimpUrl, handleMailchimpError } from './types' const logger = createLogger('MailchimpUpdateSegment') @@ -15,7 +16,7 @@ export interface MailchimpUpdateSegmentParams { export interface MailchimpUpdateSegmentResponse { success: boolean output: { - segment: any + segment: MailchimpSegment metadata: { operation: 'update_segment' segmentId: string @@ -75,7 +76,7 @@ export const mailchimpUpdateSegmentTool: ToolConfig< 'Content-Type': 'application/json', }), body: (params) => { - const body: any = {} + const body: Record = {} if (params.segmentName) body.name = params.segmentName diff --git a/apps/sim/tools/mailchimp/update_template.ts b/apps/sim/tools/mailchimp/update_template.ts index 3e7ea3fbba..115fd24c2b 100644 --- a/apps/sim/tools/mailchimp/update_template.ts +++ b/apps/sim/tools/mailchimp/update_template.ts @@ -1,5 +1,6 @@ import { createLogger } from '@/lib/logs/console/logger' import type { ToolConfig } from '@/tools/types' +import type { MailchimpTemplate } from './types' import { buildMailchimpUrl, handleMailchimpError } from './types' const logger = createLogger('MailchimpUpdateTemplate') @@ -14,7 +15,7 @@ export interface MailchimpUpdateTemplateParams { export interface MailchimpUpdateTemplateResponse { success: boolean output: { - template: any + template: MailchimpTemplate metadata: { operation: 'update_template' templateId: string @@ -67,7 +68,7 @@ export const mailchimpUpdateTemplateTool: ToolConfig< 'Content-Type': 'application/json', }), body: (params) => { - const body: any = {} + const body: Record = {} if (params.templateName) body.name = params.templateName if (params.templateHtml) body.html = params.templateHtml diff --git a/apps/sim/tools/mailgun/add_list_member.ts b/apps/sim/tools/mailgun/add_list_member.ts new file mode 100644 index 0000000000..6e33e5a95b --- /dev/null +++ b/apps/sim/tools/mailgun/add_list_member.ts @@ -0,0 +1,101 @@ +import type { AddListMemberParams, AddListMemberResult } from '@/tools/mailgun/types' +import type { ToolConfig } from '@/tools/types' + +export const mailgunAddListMemberTool: ToolConfig = { + id: 'mailgun_add_list_member', + name: 'Mailgun Add List Member', + description: 'Add a member to a mailing list', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Mailgun API key', + }, + listAddress: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'Mailing list address', + }, + address: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'Member email address', + }, + name: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Member name', + }, + vars: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'JSON string of custom variables', + }, + subscribed: { + type: 'boolean', + required: false, + visibility: 'user-or-llm', + description: 'Whether the member is subscribed', + }, + }, + + request: { + url: (params) => `https://api.mailgun.net/v3/lists/${params.listAddress}/members`, + method: 'POST', + headers: (params) => ({ + Authorization: `Basic ${Buffer.from(`api:${params.apiKey}`).toString('base64')}`, + }), + body: (params) => { + const formData = new FormData() + formData.append('address', params.address) + + if (params.name) { + formData.append('name', params.name) + } + if (params.vars) { + formData.append('vars', params.vars) + } + if (params.subscribed !== undefined) { + formData.append('subscribed', params.subscribed ? 'yes' : 'no') + } + + return { body: formData } + }, + }, + + transformResponse: async (response, params): Promise => { + if (!response.ok) { + const error = await response.json() + throw new Error(error.message || 'Failed to add list member') + } + + const result = await response.json() + + return { + success: true, + output: { + success: true, + message: result.message, + member: { + address: result.member.address, + name: result.member.name, + subscribed: result.member.subscribed, + vars: result.member.vars, + }, + }, + } + }, + + outputs: { + success: { type: 'boolean', description: 'Whether the member was added successfully' }, + message: { type: 'string', description: 'Response message' }, + member: { type: 'json', description: 'Added member details' }, + }, +} diff --git a/apps/sim/tools/mailgun/create_mailing_list.ts b/apps/sim/tools/mailgun/create_mailing_list.ts new file mode 100644 index 0000000000..6d7f5d6629 --- /dev/null +++ b/apps/sim/tools/mailgun/create_mailing_list.ts @@ -0,0 +1,99 @@ +import type { CreateMailingListParams, CreateMailingListResult } from '@/tools/mailgun/types' +import type { ToolConfig } from '@/tools/types' + +export const mailgunCreateMailingListTool: ToolConfig< + CreateMailingListParams, + CreateMailingListResult +> = { + id: 'mailgun_create_mailing_list', + name: 'Mailgun Create Mailing List', + description: 'Create a new mailing list', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Mailgun API key', + }, + address: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'Mailing list address (e.g., list@example.com)', + }, + name: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Mailing list name', + }, + description: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Mailing list description', + }, + accessLevel: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Access level: readonly, members, or everyone', + }, + }, + + request: { + url: () => 'https://api.mailgun.net/v3/lists', + method: 'POST', + headers: (params) => ({ + Authorization: `Basic ${Buffer.from(`api:${params.apiKey}`).toString('base64')}`, + }), + body: (params) => { + const formData = new FormData() + formData.append('address', params.address) + + if (params.name) { + formData.append('name', params.name) + } + if (params.description) { + formData.append('description', params.description) + } + if (params.accessLevel) { + formData.append('access_level', params.accessLevel) + } + + return { body: formData } + }, + }, + + transformResponse: async (response, params): Promise => { + if (!response.ok) { + const error = await response.json() + throw new Error(error.message || 'Failed to create mailing list') + } + + const result = await response.json() + + return { + success: true, + output: { + success: true, + message: result.message, + list: { + address: result.list.address, + name: result.list.name, + description: result.list.description, + accessLevel: result.list.access_level, + createdAt: result.list.created_at, + }, + }, + } + }, + + outputs: { + success: { type: 'boolean', description: 'Whether the list was created successfully' }, + message: { type: 'string', description: 'Response message' }, + list: { type: 'json', description: 'Created mailing list details' }, + }, +} diff --git a/apps/sim/tools/mailgun/get_domain.ts b/apps/sim/tools/mailgun/get_domain.ts new file mode 100644 index 0000000000..7b8ce4104a --- /dev/null +++ b/apps/sim/tools/mailgun/get_domain.ts @@ -0,0 +1,62 @@ +import type { GetDomainParams, GetDomainResult } from '@/tools/mailgun/types' +import type { ToolConfig } from '@/tools/types' + +export const mailgunGetDomainTool: ToolConfig = { + id: 'mailgun_get_domain', + name: 'Mailgun Get Domain', + description: 'Get details of a specific domain', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Mailgun API key', + }, + domain: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'Domain name', + }, + }, + + request: { + url: (params) => `https://api.mailgun.net/v3/domains/${params.domain}`, + method: 'GET', + headers: (params) => ({ + Authorization: `Basic ${Buffer.from(`api:${params.apiKey}`).toString('base64')}`, + }), + }, + + transformResponse: async (response, params): Promise => { + if (!response.ok) { + const error = await response.json() + throw new Error(error.message || 'Failed to get domain') + } + + const result = await response.json() + + return { + success: true, + output: { + success: true, + domain: { + name: result.domain.name, + smtpLogin: result.domain.smtp_login, + smtpPassword: result.domain.smtp_password, + spamAction: result.domain.spam_action, + state: result.domain.state, + createdAt: result.domain.created_at, + type: result.domain.type, + }, + }, + } + }, + + outputs: { + success: { type: 'boolean', description: 'Whether the request was successful' }, + domain: { type: 'json', description: 'Domain details' }, + }, +} diff --git a/apps/sim/tools/mailgun/get_mailing_list.ts b/apps/sim/tools/mailgun/get_mailing_list.ts new file mode 100644 index 0000000000..509021d8a5 --- /dev/null +++ b/apps/sim/tools/mailgun/get_mailing_list.ts @@ -0,0 +1,61 @@ +import type { GetMailingListParams, GetMailingListResult } from '@/tools/mailgun/types' +import type { ToolConfig } from '@/tools/types' + +export const mailgunGetMailingListTool: ToolConfig = { + id: 'mailgun_get_mailing_list', + name: 'Mailgun Get Mailing List', + description: 'Get details of a mailing list', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Mailgun API key', + }, + address: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'Mailing list address', + }, + }, + + request: { + url: (params) => `https://api.mailgun.net/v3/lists/${params.address}`, + method: 'GET', + headers: (params) => ({ + Authorization: `Basic ${Buffer.from(`api:${params.apiKey}`).toString('base64')}`, + }), + }, + + transformResponse: async (response, params): Promise => { + if (!response.ok) { + const error = await response.json() + throw new Error(error.message || 'Failed to get mailing list') + } + + const result = await response.json() + + return { + success: true, + output: { + success: true, + list: { + address: result.list.address, + name: result.list.name, + description: result.list.description, + accessLevel: result.list.access_level, + membersCount: result.list.members_count, + createdAt: result.list.created_at, + }, + }, + } + }, + + outputs: { + success: { type: 'boolean', description: 'Whether the request was successful' }, + list: { type: 'json', description: 'Mailing list details' }, + }, +} diff --git a/apps/sim/tools/mailgun/get_message.ts b/apps/sim/tools/mailgun/get_message.ts new file mode 100644 index 0000000000..22066e5873 --- /dev/null +++ b/apps/sim/tools/mailgun/get_message.ts @@ -0,0 +1,83 @@ +import type { GetMessageParams, GetMessageResult } from '@/tools/mailgun/types' +import type { ToolConfig } from '@/tools/types' + +export const mailgunGetMessageTool: ToolConfig = { + id: 'mailgun_get_message', + name: 'Mailgun Get Message', + description: 'Retrieve a stored message by its key', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Mailgun API key', + }, + domain: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Mailgun domain', + }, + messageKey: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'Message storage key', + }, + }, + + request: { + url: (params) => + `https://api.mailgun.net/v3/domains/${params.domain}/messages/${params.messageKey}`, + method: 'GET', + headers: (params) => ({ + Authorization: `Basic ${Buffer.from(`api:${params.apiKey}`).toString('base64')}`, + }), + }, + + transformResponse: async (response, params): Promise => { + if (!response.ok) { + const error = await response.json() + throw new Error(error.message || 'Failed to get message') + } + + const result = await response.json() + + return { + success: true, + output: { + success: true, + recipients: result.recipients, + from: result.from, + subject: result.subject, + bodyPlain: result['body-plain'], + strippedText: result['stripped-text'], + strippedSignature: result['stripped-signature'], + bodyHtml: result['body-html'], + strippedHtml: result['stripped-html'], + attachmentCount: result['attachment-count'], + timestamp: result.timestamp, + messageHeaders: result['message-headers'], + contentIdMap: result['content-id-map'], + }, + } + }, + + outputs: { + success: { type: 'boolean', description: 'Whether the request was successful' }, + recipients: { type: 'string', description: 'Message recipients' }, + from: { type: 'string', description: 'Sender email' }, + subject: { type: 'string', description: 'Message subject' }, + bodyPlain: { type: 'string', description: 'Plain text body' }, + strippedText: { type: 'string', description: 'Stripped text' }, + strippedSignature: { type: 'string', description: 'Stripped signature' }, + bodyHtml: { type: 'string', description: 'HTML body' }, + strippedHtml: { type: 'string', description: 'Stripped HTML' }, + attachmentCount: { type: 'number', description: 'Number of attachments' }, + timestamp: { type: 'number', description: 'Message timestamp' }, + messageHeaders: { type: 'json', description: 'Message headers' }, + contentIdMap: { type: 'json', description: 'Content ID map' }, + }, +} diff --git a/apps/sim/tools/mailgun/index.ts b/apps/sim/tools/mailgun/index.ts new file mode 100644 index 0000000000..2e9bf29035 --- /dev/null +++ b/apps/sim/tools/mailgun/index.ts @@ -0,0 +1,11 @@ +// Message Operations + +export { mailgunAddListMemberTool } from './add_list_member' +export { mailgunCreateMailingListTool } from './create_mailing_list' +export { mailgunGetDomainTool } from './get_domain' +export { mailgunGetMailingListTool } from './get_mailing_list' +export { mailgunGetMessageTool } from './get_message' +export { mailgunListDomainsTool } from './list_domains' +export { mailgunListMessagesTool } from './list_messages' +export { mailgunSendMessageTool } from './send_message' +export type { SendMessageParams, SendMessageResult } from './types' diff --git a/apps/sim/tools/mailgun/list_domains.ts b/apps/sim/tools/mailgun/list_domains.ts new file mode 100644 index 0000000000..4735d30aa5 --- /dev/null +++ b/apps/sim/tools/mailgun/list_domains.ts @@ -0,0 +1,50 @@ +import type { ListDomainsParams, ListDomainsResult } from '@/tools/mailgun/types' +import type { ToolConfig } from '@/tools/types' + +export const mailgunListDomainsTool: ToolConfig = { + id: 'mailgun_list_domains', + name: 'Mailgun List Domains', + description: 'List all domains for your Mailgun account', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Mailgun API key', + }, + }, + + request: { + url: () => 'https://api.mailgun.net/v3/domains', + method: 'GET', + headers: (params) => ({ + Authorization: `Basic ${Buffer.from(`api:${params.apiKey}`).toString('base64')}`, + }), + }, + + transformResponse: async (response, params): Promise => { + if (!response.ok) { + const error = await response.json() + throw new Error(error.message || 'Failed to list domains') + } + + const result = await response.json() + + return { + success: true, + output: { + success: true, + totalCount: result.total_count, + items: result.items || [], + }, + } + }, + + outputs: { + success: { type: 'boolean', description: 'Whether the request was successful' }, + totalCount: { type: 'number', description: 'Total number of domains' }, + items: { type: 'json', description: 'Array of domain objects' }, + }, +} diff --git a/apps/sim/tools/mailgun/list_messages.ts b/apps/sim/tools/mailgun/list_messages.ts new file mode 100644 index 0000000000..59a269d39d --- /dev/null +++ b/apps/sim/tools/mailgun/list_messages.ts @@ -0,0 +1,81 @@ +import type { ListMessagesParams, ListMessagesResult } from '@/tools/mailgun/types' +import type { ToolConfig } from '@/tools/types' + +export const mailgunListMessagesTool: ToolConfig = { + id: 'mailgun_list_messages', + name: 'Mailgun List Messages', + description: 'List events (logs) for messages sent through Mailgun', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Mailgun API key', + }, + domain: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Mailgun domain', + }, + event: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Filter by event type (accepted, delivered, failed, opened, clicked, etc.)', + }, + limit: { + type: 'number', + required: false, + visibility: 'user-or-llm', + description: 'Maximum number of events to return (default: 100)', + }, + }, + + request: { + url: (params) => { + const baseUrl = `https://api.mailgun.net/v3/${params.domain}/events` + const queryParams = new URLSearchParams() + + if (params.event) { + queryParams.append('event', params.event) + } + if (params.limit) { + queryParams.append('limit', params.limit.toString()) + } + + const query = queryParams.toString() + return query ? `${baseUrl}?${query}` : baseUrl + }, + method: 'GET', + headers: (params) => ({ + Authorization: `Basic ${Buffer.from(`api:${params.apiKey}`).toString('base64')}`, + }), + }, + + transformResponse: async (response, params): Promise => { + if (!response.ok) { + const error = await response.json() + throw new Error(error.message || 'Failed to list messages') + } + + const result = await response.json() + + return { + success: true, + output: { + success: true, + items: result.items || [], + paging: result.paging || {}, + }, + } + }, + + outputs: { + success: { type: 'boolean', description: 'Whether the request was successful' }, + items: { type: 'json', description: 'Array of event items' }, + paging: { type: 'json', description: 'Paging information' }, + }, +} diff --git a/apps/sim/tools/mailgun/send_message.ts b/apps/sim/tools/mailgun/send_message.ts new file mode 100644 index 0000000000..c4e7a9735c --- /dev/null +++ b/apps/sim/tools/mailgun/send_message.ts @@ -0,0 +1,129 @@ +import type { SendMessageParams, SendMessageResult } from '@/tools/mailgun/types' +import type { ToolConfig } from '@/tools/types' + +export const mailgunSendMessageTool: ToolConfig = { + id: 'mailgun_send_message', + name: 'Mailgun Send Message', + description: 'Send an email using Mailgun API', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Mailgun API key', + }, + domain: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Mailgun domain (e.g., mg.example.com)', + }, + from: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'Sender email address', + }, + to: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'Recipient email address (comma-separated for multiple)', + }, + subject: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'Email subject', + }, + text: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Plain text body of the email', + }, + html: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'HTML body of the email', + }, + cc: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'CC email address (comma-separated for multiple)', + }, + bcc: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'BCC email address (comma-separated for multiple)', + }, + tags: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Tags for the email (comma-separated)', + }, + }, + + request: { + url: (params) => `https://api.mailgun.net/v3/${params.domain}/messages`, + method: 'POST', + headers: (params) => ({ + Authorization: `Basic ${Buffer.from(`api:${params.apiKey}`).toString('base64')}`, + }), + body: (params) => { + const formData = new FormData() + formData.append('from', params.from) + formData.append('to', params.to) + formData.append('subject', params.subject) + + if (params.text) { + formData.append('text', params.text) + } + if (params.html) { + formData.append('html', params.html) + } + if (params.cc) { + formData.append('cc', params.cc) + } + if (params.bcc) { + formData.append('bcc', params.bcc) + } + if (params.tags) { + const tagArray = params.tags.split(',').map((t) => t.trim()) + tagArray.forEach((tag) => formData.append('o:tag', tag)) + } + + return { body: formData } + }, + }, + + transformResponse: async (response, params): Promise => { + if (!response.ok) { + const error = await response.json() + throw new Error(error.message || 'Failed to send message') + } + + const result = await response.json() + + return { + success: true, + output: { + success: true, + id: result.id, + message: result.message || 'Queued. Thank you.', + }, + } + }, + + outputs: { + success: { type: 'boolean', description: 'Whether the message was sent successfully' }, + id: { type: 'string', description: 'Message ID' }, + message: { type: 'string', description: 'Response message from Mailgun' }, + }, +} diff --git a/apps/sim/tools/mailgun/types.ts b/apps/sim/tools/mailgun/types.ts new file mode 100644 index 0000000000..75cb4e0fbc --- /dev/null +++ b/apps/sim/tools/mailgun/types.ts @@ -0,0 +1,201 @@ +import type { ToolResponse } from '@/tools/types' + +export interface MailgunMessageHeaders { + [key: string]: string | string[] +} + +export interface MailgunMessageItem { + timestamp: number + event: string + recipient: string + sender?: string + subject?: string + deliveryStatus?: string + [key: string]: unknown +} + +export interface MailgunDomainItem { + name: string + state: string + type: string + created_at?: string + smtp_login?: string + [key: string]: unknown +} + +export interface MailgunPaging { + first?: string + next?: string + previous?: string + last?: string +} + +export interface MailgunMailingListMember { + address: string + name?: string + subscribed: boolean + vars?: Record +} + +// Send Message +export interface SendMessageParams { + apiKey: string + domain: string + from: string + to: string + subject: string + text?: string + html?: string + cc?: string + bcc?: string + tags?: string +} + +export interface SendMessageResult extends ToolResponse { + output: { + success: boolean + id: string + message: string + } +} + +// Get Message +export interface GetMessageParams { + apiKey: string + domain: string + messageKey: string +} + +export interface GetMessageResult extends ToolResponse { + output: { + success: boolean + recipients: string + from: string + subject: string + bodyPlain: string + strippedText: string + strippedSignature: string + bodyHtml: string + strippedHtml: string + attachmentCount: number + timestamp: number + messageHeaders: MailgunMessageHeaders + contentIdMap: Record + } +} + +// List Messages (Events) +export interface ListMessagesParams { + apiKey: string + domain: string + event?: string + limit?: number +} + +export interface ListMessagesResult extends ToolResponse { + output: { + success: boolean + items: MailgunMessageItem[] + paging: MailgunPaging + } +} + +// Create Mailing List +export interface CreateMailingListParams { + apiKey: string + address: string + name?: string + description?: string + accessLevel?: 'readonly' | 'members' | 'everyone' +} + +export interface CreateMailingListResult extends ToolResponse { + output: { + success: boolean + message: string + list: { + address: string + name: string + description: string + accessLevel: string + createdAt: string + } + } +} + +// Get Mailing List +export interface GetMailingListParams { + apiKey: string + address: string +} + +export interface GetMailingListResult extends ToolResponse { + output: { + success: boolean + list: { + address: string + name: string + description: string + accessLevel: string + membersCount: number + createdAt: string + } + } +} + +// Add List Member +export interface AddListMemberParams { + apiKey: string + listAddress: string + address: string + name?: string + vars?: string + subscribed?: boolean +} + +export interface AddListMemberResult extends ToolResponse { + output: { + success: boolean + message: string + member: { + address: string + name: string + subscribed: boolean + vars: Record + } + } +} + +// List Domains +export interface ListDomainsParams { + apiKey: string +} + +export interface ListDomainsResult extends ToolResponse { + output: { + success: boolean + totalCount: number + items: MailgunDomainItem[] + } +} + +// Get Domain +export interface GetDomainParams { + apiKey: string + domain: string +} + +export interface GetDomainResult extends ToolResponse { + output: { + success: boolean + domain: { + name: string + smtpLogin: string + smtpPassword: string + spamAction: string + state: string + createdAt: string + type: string + } + } +} diff --git a/apps/sim/tools/registry.ts b/apps/sim/tools/registry.ts index f22d04cd20..9d993891b6 100644 --- a/apps/sim/tools/registry.ts +++ b/apps/sim/tools/registry.ts @@ -419,6 +419,7 @@ import { linearUpdateProjectTool, linearUpdateWorkflowStateTool, } from '@/tools/linear' +import { linkedInGetProfileTool, linkedInSharePostTool } from '@/tools/linkedin' import { linkupSearchTool } from '@/tools/linkup' import { mailchimpAddMemberTagsTool, @@ -495,6 +496,16 @@ import { mailchimpUpdateSegmentTool, mailchimpUpdateTemplateTool, } from '@/tools/mailchimp' +import { + mailgunAddListMemberTool, + mailgunCreateMailingListTool, + mailgunGetDomainTool, + mailgunGetMailingListTool, + mailgunGetMessageTool, + mailgunListDomainsTool, + mailgunListMessagesTool, + mailgunSendMessageTool, +} from '@/tools/mailgun' import { mem0AddMemoriesTool, mem0GetMemoriesTool, mem0SearchMemoriesTool } from '@/tools/mem0' import { memoryAddTool, memoryDeleteTool, memoryGetAllTool, memoryGetTool } from '@/tools/memory' import { @@ -756,6 +767,24 @@ import { salesforceUpdateOpportunityTool, salesforceUpdateTaskTool, } from '@/tools/salesforce' +import { + sendGridAddContactsToListTool, + sendGridAddContactTool, + sendGridCreateListTool, + sendGridCreateTemplateTool, + sendGridCreateTemplateVersionTool, + sendGridDeleteContactsTool, + sendGridDeleteListTool, + sendGridDeleteTemplateTool, + sendGridGetContactTool, + sendGridGetListTool, + sendGridGetTemplateTool, + sendGridListAllListsTool, + sendGridListTemplatesTool, + sendGridRemoveContactsFromListTool, + sendGridSearchContactsTool, + sendGridSendMailTool, +} from '@/tools/sendgrid' import { createDeployTool, createProjectTool, @@ -791,6 +820,7 @@ import { slackUpdateMessageTool, } from '@/tools/slack' import { smsSendTool } from '@/tools/sms' +import { smtpSendMailTool } from '@/tools/smtp' import { stagehandAgentTool, stagehandExtractTool } from '@/tools/stagehand' import { stripeCancelPaymentIntentTool, @@ -1025,7 +1055,34 @@ export const tools: Record = { jina_read_url: readUrlTool, jina_search: jinaSearchTool, linkup_search: linkupSearchTool, + linkedin_share_post: linkedInSharePostTool, + linkedin_get_profile: linkedInGetProfileTool, resend_send: mailSendTool, + sendgrid_send_mail: sendGridSendMailTool, + sendgrid_add_contact: sendGridAddContactTool, + sendgrid_get_contact: sendGridGetContactTool, + sendgrid_search_contacts: sendGridSearchContactsTool, + sendgrid_delete_contacts: sendGridDeleteContactsTool, + sendgrid_create_list: sendGridCreateListTool, + sendgrid_get_list: sendGridGetListTool, + sendgrid_list_all_lists: sendGridListAllListsTool, + sendgrid_delete_list: sendGridDeleteListTool, + sendgrid_add_contacts_to_list: sendGridAddContactsToListTool, + sendgrid_remove_contacts_from_list: sendGridRemoveContactsFromListTool, + sendgrid_create_template: sendGridCreateTemplateTool, + sendgrid_get_template: sendGridGetTemplateTool, + sendgrid_list_templates: sendGridListTemplatesTool, + sendgrid_delete_template: sendGridDeleteTemplateTool, + sendgrid_create_template_version: sendGridCreateTemplateVersionTool, + smtp_send_mail: smtpSendMailTool, + mailgun_send_message: mailgunSendMessageTool, + mailgun_get_message: mailgunGetMessageTool, + mailgun_list_messages: mailgunListMessagesTool, + mailgun_create_mailing_list: mailgunCreateMailingListTool, + mailgun_get_mailing_list: mailgunGetMailingListTool, + mailgun_add_list_member: mailgunAddListMemberTool, + mailgun_list_domains: mailgunListDomainsTool, + mailgun_get_domain: mailgunGetDomainTool, sms_send: smsSendTool, jira_retrieve: jiraRetrieveTool, jira_update: jiraUpdateTool, diff --git a/apps/sim/tools/sendgrid/add_contact.ts b/apps/sim/tools/sendgrid/add_contact.ts new file mode 100644 index 0000000000..5c91e37f35 --- /dev/null +++ b/apps/sim/tools/sendgrid/add_contact.ts @@ -0,0 +1,118 @@ +import type { + AddContactParams, + ContactResult, + SendGridContactObject, + SendGridContactRequest, +} from '@/tools/sendgrid/types' +import type { ToolConfig } from '@/tools/types' + +export const sendGridAddContactTool: ToolConfig = { + id: 'sendgrid_add_contact', + name: 'SendGrid Add Contact', + description: 'Add a new contact to SendGrid', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'SendGrid API key', + }, + email: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'Contact email address', + }, + firstName: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Contact first name', + }, + lastName: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Contact last name', + }, + customFields: { + type: 'json', + required: false, + visibility: 'user-or-llm', + description: + 'JSON object of custom field key-value pairs (use field IDs like e1_T, e2_N, e3_D, not field names)', + }, + listIds: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Comma-separated list IDs to add the contact to', + }, + }, + + request: { + url: () => 'https://api.sendgrid.com/v3/marketing/contacts', + method: 'PUT', + headers: (params) => ({ + Authorization: `Bearer ${params.apiKey}`, + 'Content-Type': 'application/json', + }), + body: (params) => { + const contact: SendGridContactObject = { + email: params.email, + } + + if (params.firstName) contact.first_name = params.firstName + if (params.lastName) contact.last_name = params.lastName + + if (params.customFields) { + const customFields = + typeof params.customFields === 'string' + ? JSON.parse(params.customFields) + : params.customFields + Object.assign(contact, customFields) + } + + const body: SendGridContactRequest = { + contacts: [contact], + } + + if (params.listIds) { + body.list_ids = params.listIds.split(',').map((id) => id.trim()) + } + + return { body: JSON.stringify(body) } + }, + }, + + transformResponse: async (response, params): Promise => { + if (!response.ok) { + const error = await response.json() + throw new Error(error.errors?.[0]?.message || 'Failed to add contact') + } + + const data = await response.json() + + return { + success: true, + output: { + jobId: data.job_id, + email: params?.email || '', + firstName: params?.firstName, + lastName: params?.lastName, + message: + 'Contact is being added. This is an asynchronous operation. Use the job ID to track status.', + }, + } + }, + + outputs: { + jobId: { type: 'string', description: 'Job ID for tracking the async contact creation' }, + email: { type: 'string', description: 'Contact email address' }, + firstName: { type: 'string', description: 'Contact first name' }, + lastName: { type: 'string', description: 'Contact last name' }, + message: { type: 'string', description: 'Status message' }, + }, +} diff --git a/apps/sim/tools/sendgrid/add_contacts_to_list.ts b/apps/sim/tools/sendgrid/add_contacts_to_list.ts new file mode 100644 index 0000000000..28b4105ce2 --- /dev/null +++ b/apps/sim/tools/sendgrid/add_contacts_to_list.ts @@ -0,0 +1,74 @@ +import type { AddContactsToListParams, SendGridContactObject } from '@/tools/sendgrid/types' +import type { ToolConfig, ToolResponse } from '@/tools/types' + +export const sendGridAddContactsToListTool: ToolConfig = { + id: 'sendgrid_add_contacts_to_list', + name: 'SendGrid Add Contacts to List', + description: + 'Add or update contacts and assign them to a list in SendGrid (uses PUT /v3/marketing/contacts)', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'SendGrid API key', + }, + listId: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'List ID to add contacts to', + }, + contacts: { + type: 'json', + required: true, + visibility: 'user-or-llm', + description: + 'JSON array of contact objects. Each contact must have at least: email (or phone_number_id/external_id/anonymous_id). Example: [{"email": "user@example.com", "first_name": "John"}]', + }, + }, + + request: { + url: () => 'https://api.sendgrid.com/v3/marketing/contacts', + method: 'PUT', + headers: (params) => ({ + Authorization: `Bearer ${params.apiKey}`, + 'Content-Type': 'application/json', + }), + body: (params) => { + const contactsArray: SendGridContactObject[] = + typeof params.contacts === 'string' ? JSON.parse(params.contacts) : params.contacts + + return { + body: JSON.stringify({ + list_ids: [params.listId], + contacts: contactsArray, + }), + } + }, + }, + + transformResponse: async (response): Promise => { + if (!response.ok) { + const error = (await response.json()) as { errors?: Array<{ message?: string }> } + throw new Error(error.errors?.[0]?.message || 'Failed to add contacts to list') + } + + const data = (await response.json()) as { job_id: string } + + return { + success: true, + output: { + jobId: data.job_id, + message: 'Contacts are being added to the list. This is an asynchronous operation.', + }, + } + }, + + outputs: { + jobId: { type: 'string', description: 'Job ID for tracking the async operation' }, + message: { type: 'string', description: 'Status message' }, + }, +} diff --git a/apps/sim/tools/sendgrid/create_list.ts b/apps/sim/tools/sendgrid/create_list.ts new file mode 100644 index 0000000000..5bb8d7600a --- /dev/null +++ b/apps/sim/tools/sendgrid/create_list.ts @@ -0,0 +1,64 @@ +import type { CreateListParams, ListResult, SendGridList } from '@/tools/sendgrid/types' +import type { ToolConfig } from '@/tools/types' + +export const sendGridCreateListTool: ToolConfig = { + id: 'sendgrid_create_list', + name: 'SendGrid Create List', + description: 'Create a new contact list in SendGrid', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'SendGrid API key', + }, + name: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'List name', + }, + }, + + request: { + url: () => 'https://api.sendgrid.com/v3/marketing/lists', + method: 'POST', + headers: (params) => ({ + Authorization: `Bearer ${params.apiKey}`, + 'Content-Type': 'application/json', + }), + body: (params) => { + return { + body: JSON.stringify({ + name: params.name, + }), + } + }, + }, + + transformResponse: async (response): Promise => { + if (!response.ok) { + const error = (await response.json()) as { errors?: Array<{ message?: string }> } + throw new Error(error.errors?.[0]?.message || 'Failed to create list') + } + + const data = (await response.json()) as SendGridList + + return { + success: true, + output: { + id: data.id, + name: data.name, + contactCount: data.contact_count, + }, + } + }, + + outputs: { + id: { type: 'string', description: 'List ID' }, + name: { type: 'string', description: 'List name' }, + contactCount: { type: 'number', description: 'Number of contacts in the list' }, + }, +} diff --git a/apps/sim/tools/sendgrid/create_template.ts b/apps/sim/tools/sendgrid/create_template.ts new file mode 100644 index 0000000000..7352c41c13 --- /dev/null +++ b/apps/sim/tools/sendgrid/create_template.ts @@ -0,0 +1,75 @@ +import type { CreateTemplateParams, SendGridTemplate, TemplateResult } from '@/tools/sendgrid/types' +import type { ToolConfig } from '@/tools/types' + +export const sendGridCreateTemplateTool: ToolConfig = { + id: 'sendgrid_create_template', + name: 'SendGrid Create Template', + description: 'Create a new email template in SendGrid', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'SendGrid API key', + }, + name: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'Template name', + }, + generation: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Template generation type (legacy or dynamic, default: dynamic)', + }, + }, + + request: { + url: () => 'https://api.sendgrid.com/v3/templates', + method: 'POST', + headers: (params) => ({ + Authorization: `Bearer ${params.apiKey}`, + 'Content-Type': 'application/json', + }), + body: (params) => { + return { + body: JSON.stringify({ + name: params.name, + generation: params.generation || 'dynamic', + }), + } + }, + }, + + transformResponse: async (response): Promise => { + if (!response.ok) { + const error = (await response.json()) as { errors?: Array<{ message?: string }> } + throw new Error(error.errors?.[0]?.message || 'Failed to create template') + } + + const data = (await response.json()) as SendGridTemplate + + return { + success: true, + output: { + id: data.id, + name: data.name, + generation: data.generation, + updatedAt: data.updated_at, + versions: data.versions || [], + }, + } + }, + + outputs: { + id: { type: 'string', description: 'Template ID' }, + name: { type: 'string', description: 'Template name' }, + generation: { type: 'string', description: 'Template generation' }, + updatedAt: { type: 'string', description: 'Last update timestamp' }, + versions: { type: 'json', description: 'Array of template versions' }, + }, +} diff --git a/apps/sim/tools/sendgrid/create_template_version.ts b/apps/sim/tools/sendgrid/create_template_version.ts new file mode 100644 index 0000000000..e41f43bb58 --- /dev/null +++ b/apps/sim/tools/sendgrid/create_template_version.ts @@ -0,0 +1,121 @@ +import type { + CreateTemplateVersionParams, + SendGridTemplateVersionRequest, + TemplateVersionResult, +} from '@/tools/sendgrid/types' +import type { ToolConfig } from '@/tools/types' + +export const sendGridCreateTemplateVersionTool: ToolConfig< + CreateTemplateVersionParams, + TemplateVersionResult +> = { + id: 'sendgrid_create_template_version', + name: 'SendGrid Create Template Version', + description: 'Create a new version of an email template in SendGrid', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'SendGrid API key', + }, + templateId: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'Template ID', + }, + name: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'Version name', + }, + subject: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'Email subject line', + }, + htmlContent: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'HTML content of the template', + }, + plainContent: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Plain text content of the template', + }, + active: { + type: 'boolean', + required: false, + visibility: 'user-or-llm', + description: 'Whether this version is active (default: true)', + }, + }, + + request: { + url: (params) => `https://api.sendgrid.com/v3/templates/${params.templateId}/versions`, + method: 'POST', + headers: (params) => ({ + Authorization: `Bearer ${params.apiKey}`, + 'Content-Type': 'application/json', + }), + body: (params) => { + const body: SendGridTemplateVersionRequest = { + name: params.name, + subject: params.subject, + active: params.active !== undefined ? params.active : 1, + } + + if (params.htmlContent) { + body.html_content = params.htmlContent + } + + if (params.plainContent) { + body.plain_content = params.plainContent + } + + return { body: JSON.stringify(body) } + }, + }, + + transformResponse: async (response): Promise => { + if (!response.ok) { + const error = await response.json() + throw new Error(error.errors?.[0]?.message || 'Failed to create template version') + } + + const data = await response.json() + + return { + success: true, + output: { + id: data.id, + templateId: data.template_id, + name: data.name, + subject: data.subject, + active: data.active === 1, + htmlContent: data.html_content, + plainContent: data.plain_content, + updatedAt: data.updated_at, + }, + } + }, + + outputs: { + id: { type: 'string', description: 'Version ID' }, + templateId: { type: 'string', description: 'Template ID' }, + name: { type: 'string', description: 'Version name' }, + subject: { type: 'string', description: 'Email subject' }, + active: { type: 'boolean', description: 'Whether this version is active' }, + htmlContent: { type: 'string', description: 'HTML content' }, + plainContent: { type: 'string', description: 'Plain text content' }, + updatedAt: { type: 'string', description: 'Last update timestamp' }, + }, +} diff --git a/apps/sim/tools/sendgrid/delete_contacts.ts b/apps/sim/tools/sendgrid/delete_contacts.ts new file mode 100644 index 0000000000..c8eb811dc6 --- /dev/null +++ b/apps/sim/tools/sendgrid/delete_contacts.ts @@ -0,0 +1,58 @@ +import type { DeleteContactParams } from '@/tools/sendgrid/types' +import type { ToolConfig, ToolResponse } from '@/tools/types' + +export const sendGridDeleteContactsTool: ToolConfig = { + id: 'sendgrid_delete_contacts', + name: 'SendGrid Delete Contacts', + description: 'Delete one or more contacts from SendGrid', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'SendGrid API key', + }, + contactIds: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'Comma-separated contact IDs to delete', + }, + }, + + request: { + url: (params) => { + const ids = params.contactIds + .split(',') + .map((id) => id.trim()) + .join(',') + return `https://api.sendgrid.com/v3/marketing/contacts?ids=${encodeURIComponent(ids)}` + }, + method: 'DELETE', + headers: (params) => ({ + Authorization: `Bearer ${params.apiKey}`, + }), + }, + + transformResponse: async (response): Promise => { + if (!response.ok) { + const error = (await response.json()) as { errors?: Array<{ message?: string }> } + throw new Error(error.errors?.[0]?.message || 'Failed to delete contacts') + } + + const data = (await response.json()) as { job_id: string } + + return { + success: true, + output: { + jobId: data.job_id, + }, + } + }, + + outputs: { + jobId: { type: 'string', description: 'Job ID for the deletion request' }, + }, +} diff --git a/apps/sim/tools/sendgrid/delete_list.ts b/apps/sim/tools/sendgrid/delete_list.ts new file mode 100644 index 0000000000..2e473bc677 --- /dev/null +++ b/apps/sim/tools/sendgrid/delete_list.ts @@ -0,0 +1,51 @@ +import type { DeleteListParams } from '@/tools/sendgrid/types' +import type { ToolConfig, ToolResponse } from '@/tools/types' + +export const sendGridDeleteListTool: ToolConfig = { + id: 'sendgrid_delete_list', + name: 'SendGrid Delete List', + description: 'Delete a contact list from SendGrid', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'SendGrid API key', + }, + listId: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'List ID to delete', + }, + }, + + request: { + url: (params) => `https://api.sendgrid.com/v3/marketing/lists/${params.listId}`, + method: 'DELETE', + headers: (params) => ({ + Authorization: `Bearer ${params.apiKey}`, + }), + }, + + transformResponse: async (response): Promise => { + if (!response.ok) { + const error = (await response.json()) as { errors?: Array<{ message?: string }> } + throw new Error(error.errors?.[0]?.message || 'Failed to delete list') + } + + // API returns 204 No Content on success + return { + success: true, + output: { + message: 'List deleted successfully', + }, + } + }, + + outputs: { + message: { type: 'string', description: 'Success message' }, + }, +} diff --git a/apps/sim/tools/sendgrid/delete_template.ts b/apps/sim/tools/sendgrid/delete_template.ts new file mode 100644 index 0000000000..1d282672be --- /dev/null +++ b/apps/sim/tools/sendgrid/delete_template.ts @@ -0,0 +1,46 @@ +import type { DeleteTemplateParams } from '@/tools/sendgrid/types' +import type { ToolConfig, ToolResponse } from '@/tools/types' + +export const sendGridDeleteTemplateTool: ToolConfig = { + id: 'sendgrid_delete_template', + name: 'SendGrid Delete Template', + description: 'Delete an email template from SendGrid', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'SendGrid API key', + }, + templateId: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'Template ID to delete', + }, + }, + + request: { + url: (params) => `https://api.sendgrid.com/v3/templates/${params.templateId}`, + method: 'DELETE', + headers: (params) => ({ + Authorization: `Bearer ${params.apiKey}`, + }), + }, + + transformResponse: async (response): Promise => { + if (!response.ok) { + const error = (await response.json()) as { errors?: Array<{ message?: string }> } + throw new Error(error.errors?.[0]?.message || 'Failed to delete template') + } + + return { + success: true, + output: {}, + } + }, + + outputs: {}, +} diff --git a/apps/sim/tools/sendgrid/get_contact.ts b/apps/sim/tools/sendgrid/get_contact.ts new file mode 100644 index 0000000000..f2870d854f --- /dev/null +++ b/apps/sim/tools/sendgrid/get_contact.ts @@ -0,0 +1,66 @@ +import type { ContactResult, GetContactParams, SendGridContact } from '@/tools/sendgrid/types' +import type { ToolConfig } from '@/tools/types' + +export const sendGridGetContactTool: ToolConfig = { + id: 'sendgrid_get_contact', + name: 'SendGrid Get Contact', + description: 'Get a specific contact by ID from SendGrid', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'SendGrid API key', + }, + contactId: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'Contact ID', + }, + }, + + request: { + url: (params) => `https://api.sendgrid.com/v3/marketing/contacts/${params.contactId}`, + method: 'GET', + headers: (params) => ({ + Authorization: `Bearer ${params.apiKey}`, + }), + }, + + transformResponse: async (response): Promise => { + if (!response.ok) { + const error = (await response.json()) as { errors?: Array<{ message?: string }> } + throw new Error(error.errors?.[0]?.message || 'Failed to get contact') + } + + const data = (await response.json()) as SendGridContact + + return { + success: true, + output: { + id: data.id, + email: data.email, + firstName: data.first_name, + lastName: data.last_name, + createdAt: data.created_at, + updatedAt: data.updated_at, + listIds: data.list_ids, + customFields: data.custom_fields, + }, + } + }, + + outputs: { + id: { type: 'string', description: 'Contact ID' }, + email: { type: 'string', description: 'Contact email address' }, + firstName: { type: 'string', description: 'Contact first name' }, + lastName: { type: 'string', description: 'Contact last name' }, + createdAt: { type: 'string', description: 'Creation timestamp' }, + updatedAt: { type: 'string', description: 'Last update timestamp' }, + listIds: { type: 'json', description: 'Array of list IDs the contact belongs to' }, + customFields: { type: 'json', description: 'Custom field values' }, + }, +} diff --git a/apps/sim/tools/sendgrid/get_list.ts b/apps/sim/tools/sendgrid/get_list.ts new file mode 100644 index 0000000000..1a1c03d5de --- /dev/null +++ b/apps/sim/tools/sendgrid/get_list.ts @@ -0,0 +1,56 @@ +import type { GetListParams, ListResult, SendGridList } from '@/tools/sendgrid/types' +import type { ToolConfig } from '@/tools/types' + +export const sendGridGetListTool: ToolConfig = { + id: 'sendgrid_get_list', + name: 'SendGrid Get List', + description: 'Get a specific list by ID from SendGrid', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'SendGrid API key', + }, + listId: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'List ID', + }, + }, + + request: { + url: (params) => `https://api.sendgrid.com/v3/marketing/lists/${params.listId}`, + method: 'GET', + headers: (params) => ({ + Authorization: `Bearer ${params.apiKey}`, + }), + }, + + transformResponse: async (response): Promise => { + if (!response.ok) { + const error = (await response.json()) as { errors?: Array<{ message?: string }> } + throw new Error(error.errors?.[0]?.message || 'Failed to get list') + } + + const data = (await response.json()) as SendGridList + + return { + success: true, + output: { + id: data.id, + name: data.name, + contactCount: data.contact_count, + }, + } + }, + + outputs: { + id: { type: 'string', description: 'List ID' }, + name: { type: 'string', description: 'List name' }, + contactCount: { type: 'number', description: 'Number of contacts in the list' }, + }, +} diff --git a/apps/sim/tools/sendgrid/get_template.ts b/apps/sim/tools/sendgrid/get_template.ts new file mode 100644 index 0000000000..0f29270c76 --- /dev/null +++ b/apps/sim/tools/sendgrid/get_template.ts @@ -0,0 +1,60 @@ +import type { GetTemplateParams, SendGridTemplate, TemplateResult } from '@/tools/sendgrid/types' +import type { ToolConfig } from '@/tools/types' + +export const sendGridGetTemplateTool: ToolConfig = { + id: 'sendgrid_get_template', + name: 'SendGrid Get Template', + description: 'Get a specific template by ID from SendGrid', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'SendGrid API key', + }, + templateId: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'Template ID', + }, + }, + + request: { + url: (params) => `https://api.sendgrid.com/v3/templates/${params.templateId}`, + method: 'GET', + headers: (params) => ({ + Authorization: `Bearer ${params.apiKey}`, + }), + }, + + transformResponse: async (response): Promise => { + if (!response.ok) { + const error = (await response.json()) as { errors?: Array<{ message?: string }> } + throw new Error(error.errors?.[0]?.message || 'Failed to get template') + } + + const data = (await response.json()) as SendGridTemplate + + return { + success: true, + output: { + id: data.id, + name: data.name, + generation: data.generation, + updatedAt: data.updated_at, + versions: data.versions || [], + }, + } + }, + + outputs: { + id: { type: 'string', description: 'Template ID' }, + name: { type: 'string', description: 'Template name' }, + generation: { type: 'string', description: 'Template generation' }, + updatedAt: { type: 'string', description: 'Last update timestamp' }, + versions: { type: 'json', description: 'Array of template versions' }, + }, +} diff --git a/apps/sim/tools/sendgrid/index.ts b/apps/sim/tools/sendgrid/index.ts new file mode 100644 index 0000000000..0a716cc07b --- /dev/null +++ b/apps/sim/tools/sendgrid/index.ts @@ -0,0 +1,23 @@ +// Mail Send + +// Contact Management +export { sendGridAddContactTool } from './add_contact' +export { sendGridAddContactsToListTool } from './add_contacts_to_list' +// List Management +export { sendGridCreateListTool } from './create_list' +// Template Management +export { sendGridCreateTemplateTool } from './create_template' +export { sendGridCreateTemplateVersionTool } from './create_template_version' +export { sendGridDeleteContactsTool } from './delete_contacts' +export { sendGridDeleteListTool } from './delete_list' +export { sendGridDeleteTemplateTool } from './delete_template' +export { sendGridGetContactTool } from './get_contact' +export { sendGridGetListTool } from './get_list' +export { sendGridGetTemplateTool } from './get_template' +export { sendGridListAllListsTool } from './list_all_lists' +export { sendGridListTemplatesTool } from './list_templates' +export { sendGridRemoveContactsFromListTool } from './remove_contacts_from_list' +export { sendGridSearchContactsTool } from './search_contacts' +export { sendGridSendMailTool } from './send_mail' +// Types +export * from './types' diff --git a/apps/sim/tools/sendgrid/list_all_lists.ts b/apps/sim/tools/sendgrid/list_all_lists.ts new file mode 100644 index 0000000000..76adb3d100 --- /dev/null +++ b/apps/sim/tools/sendgrid/list_all_lists.ts @@ -0,0 +1,58 @@ +import type { ListAllListsParams, ListsResult, SendGridList } from '@/tools/sendgrid/types' +import type { ToolConfig } from '@/tools/types' + +export const sendGridListAllListsTool: ToolConfig = { + id: 'sendgrid_list_all_lists', + name: 'SendGrid List All Lists', + description: 'Get all contact lists from SendGrid', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'SendGrid API key', + }, + pageSize: { + type: 'number', + required: false, + visibility: 'user-or-llm', + description: 'Number of lists to return per page (default: 100)', + }, + }, + + request: { + url: (params) => { + const url = new URL('https://api.sendgrid.com/v3/marketing/lists') + if (params.pageSize) { + url.searchParams.append('page_size', params.pageSize.toString()) + } + return url.toString() + }, + method: 'GET', + headers: (params) => ({ + Authorization: `Bearer ${params.apiKey}`, + }), + }, + + transformResponse: async (response): Promise => { + if (!response.ok) { + const error = (await response.json()) as { errors?: Array<{ message?: string }> } + throw new Error(error.errors?.[0]?.message || 'Failed to list all lists') + } + + const data = (await response.json()) as { result?: SendGridList[] } + + return { + success: true, + output: { + lists: data.result || [], + }, + } + }, + + outputs: { + lists: { type: 'json', description: 'Array of lists' }, + }, +} diff --git a/apps/sim/tools/sendgrid/list_templates.ts b/apps/sim/tools/sendgrid/list_templates.ts new file mode 100644 index 0000000000..2d8b6c3bd2 --- /dev/null +++ b/apps/sim/tools/sendgrid/list_templates.ts @@ -0,0 +1,70 @@ +import type { ListTemplatesParams, SendGridTemplate, TemplatesResult } from '@/tools/sendgrid/types' +import type { ToolConfig } from '@/tools/types' + +export const sendGridListTemplatesTool: ToolConfig = { + id: 'sendgrid_list_templates', + name: 'SendGrid List Templates', + description: 'Get all email templates from SendGrid', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'SendGrid API key', + }, + generations: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Filter by generation (legacy, dynamic, or both)', + }, + pageSize: { + type: 'number', + required: false, + visibility: 'user-or-llm', + description: 'Number of templates to return per page (default: 20)', + }, + }, + + request: { + url: (params) => { + const url = new URL('https://api.sendgrid.com/v3/templates') + if (params.generations) { + url.searchParams.append('generations', params.generations) + } + if (params.pageSize) { + url.searchParams.append('page_size', params.pageSize.toString()) + } + return url.toString() + }, + method: 'GET', + headers: (params) => ({ + Authorization: `Bearer ${params.apiKey}`, + }), + }, + + transformResponse: async (response): Promise => { + if (!response.ok) { + const error = (await response.json()) as { errors?: Array<{ message?: string }> } + throw new Error(error.errors?.[0]?.message || 'Failed to list templates') + } + + const data = (await response.json()) as { + result?: SendGridTemplate[] + templates?: SendGridTemplate[] + } + + return { + success: true, + output: { + templates: data.result || data.templates || [], + }, + } + }, + + outputs: { + templates: { type: 'json', description: 'Array of templates' }, + }, +} diff --git a/apps/sim/tools/sendgrid/remove_contacts_from_list.ts b/apps/sim/tools/sendgrid/remove_contacts_from_list.ts new file mode 100644 index 0000000000..cf0d461838 --- /dev/null +++ b/apps/sim/tools/sendgrid/remove_contacts_from_list.ts @@ -0,0 +1,67 @@ +import type { RemoveContactsFromListParams } from '@/tools/sendgrid/types' +import type { ToolConfig, ToolResponse } from '@/tools/types' + +export const sendGridRemoveContactsFromListTool: ToolConfig< + RemoveContactsFromListParams, + ToolResponse +> = { + id: 'sendgrid_remove_contacts_from_list', + name: 'SendGrid Remove Contacts from List', + description: 'Remove contacts from a specific list in SendGrid', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'SendGrid API key', + }, + listId: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'List ID', + }, + contactIds: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'Comma-separated contact IDs to remove from the list', + }, + }, + + request: { + url: (params) => { + const contactIds = params.contactIds + .split(',') + .map((id) => id.trim()) + .join(',') + return `https://api.sendgrid.com/v3/marketing/lists/${params.listId}/contacts?contact_ids=${encodeURIComponent(contactIds)}` + }, + method: 'DELETE', + headers: (params) => ({ + Authorization: `Bearer ${params.apiKey}`, + }), + }, + + transformResponse: async (response): Promise => { + if (!response.ok) { + const error = (await response.json()) as { errors?: Array<{ message?: string }> } + throw new Error(error.errors?.[0]?.message || 'Failed to remove contacts from list') + } + + const data = (await response.json()) as { job_id?: string } + + return { + success: true, + output: { + jobId: data.job_id, + }, + } + }, + + outputs: { + jobId: { type: 'string', description: 'Job ID for the request' }, + }, +} diff --git a/apps/sim/tools/sendgrid/search_contacts.ts b/apps/sim/tools/sendgrid/search_contacts.ts new file mode 100644 index 0000000000..0f18ddab5e --- /dev/null +++ b/apps/sim/tools/sendgrid/search_contacts.ts @@ -0,0 +1,66 @@ +import type { ContactsResult, SearchContactsParams, SendGridContact } from '@/tools/sendgrid/types' +import type { ToolConfig } from '@/tools/types' + +export const sendGridSearchContactsTool: ToolConfig = { + id: 'sendgrid_search_contacts', + name: 'SendGrid Search Contacts', + description: 'Search for contacts in SendGrid using a query', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'SendGrid API key', + }, + query: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: + "Search query (e.g., \"email LIKE '%example.com%' AND CONTAINS(list_ids, 'list-id')\")", + }, + }, + + request: { + url: () => 'https://api.sendgrid.com/v3/marketing/contacts/search', + method: 'POST', + headers: (params) => ({ + Authorization: `Bearer ${params.apiKey}`, + 'Content-Type': 'application/json', + }), + body: (params) => { + return { + body: JSON.stringify({ + query: params.query, + }), + } + }, + }, + + transformResponse: async (response): Promise => { + if (!response.ok) { + const error = (await response.json()) as { errors?: Array<{ message?: string }> } + throw new Error(error.errors?.[0]?.message || 'Failed to search contacts') + } + + const data = (await response.json()) as { + result?: SendGridContact[] + contact_count?: number + } + + return { + success: true, + output: { + contacts: data.result || [], + contactCount: data.contact_count, + }, + } + }, + + outputs: { + contacts: { type: 'json', description: 'Array of matching contacts' }, + contactCount: { type: 'number', description: 'Total number of contacts found' }, + }, +} diff --git a/apps/sim/tools/sendgrid/send_mail.ts b/apps/sim/tools/sendgrid/send_mail.ts new file mode 100644 index 0000000000..abce5e4186 --- /dev/null +++ b/apps/sim/tools/sendgrid/send_mail.ts @@ -0,0 +1,212 @@ +import type { + SendGridMailBody, + SendGridPersonalization, + SendMailParams, + SendMailResult, +} from '@/tools/sendgrid/types' +import type { ToolConfig } from '@/tools/types' + +export const sendGridSendMailTool: ToolConfig = { + id: 'sendgrid_send_mail', + name: 'SendGrid Send Mail', + description: 'Send an email using SendGrid API', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'SendGrid API key', + }, + from: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'Sender email address (must be verified in SendGrid)', + }, + fromName: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Sender name', + }, + to: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'Recipient email address', + }, + toName: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Recipient name', + }, + subject: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Email subject (required unless using a template with pre-defined subject)', + }, + content: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Email body content (required unless using a template with pre-defined content)', + }, + contentType: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Content type (text/plain or text/html)', + }, + cc: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'CC email address', + }, + bcc: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'BCC email address', + }, + replyTo: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Reply-to email address', + }, + replyToName: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Reply-to name', + }, + attachments: { + type: 'file[]', + required: false, + visibility: 'user-only', + description: 'Files to attach to the email', + }, + templateId: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'SendGrid template ID to use', + }, + dynamicTemplateData: { + type: 'json', + required: false, + visibility: 'user-or-llm', + description: 'JSON object of dynamic template data', + }, + }, + + request: { + url: () => 'https://api.sendgrid.com/v3/mail/send', + method: 'POST', + headers: (params) => ({ + Authorization: `Bearer ${params.apiKey}`, + 'Content-Type': 'application/json', + }), + body: (params) => { + const personalizations: SendGridPersonalization = { + to: [ + { + email: params.to, + ...(params.toName && { name: params.toName }), + }, + ], + } + + if (params.cc) { + personalizations.cc = [{ email: params.cc }] + } + + if (params.bcc) { + personalizations.bcc = [{ email: params.bcc }] + } + + if (params.templateId && params.dynamicTemplateData) { + try { + personalizations.dynamic_template_data = + typeof params.dynamicTemplateData === 'string' + ? JSON.parse(params.dynamicTemplateData) + : params.dynamicTemplateData + } catch (e) { + // If parsing fails, use as-is + } + } + + const mailBody: SendGridMailBody = { + personalizations: [personalizations], + from: { + email: params.from, + ...(params.fromName && { name: params.fromName }), + }, + subject: params.subject, + } + + if (params.templateId) { + mailBody.template_id = params.templateId + } else { + mailBody.content = [ + { + type: params.contentType || 'text/plain', + value: params.content, + }, + ] + } + + if (params.replyTo) { + mailBody.reply_to = { + email: params.replyTo, + ...(params.replyToName && { name: params.replyToName }), + } + } + + if (params.attachments) { + try { + mailBody.attachments = + typeof params.attachments === 'string' + ? JSON.parse(params.attachments) + : params.attachments + } catch (e) { + // If parsing fails, skip attachments + } + } + + return { body: JSON.stringify(mailBody) } + }, + }, + + transformResponse: async (response, params): Promise => { + if (!response.ok) { + const error = await response.json() + throw new Error(error.errors?.[0]?.message || 'Failed to send email') + } + + // SendGrid returns 202 Accepted with X-Message-Id header + const messageId = response.headers.get('X-Message-Id') + + return { + success: true, + output: { + success: true, + messageId: messageId || undefined, + to: params?.to || '', + subject: params?.subject || '', + }, + } + }, + + outputs: { + success: { type: 'boolean', description: 'Whether the email was sent successfully' }, + messageId: { type: 'string', description: 'SendGrid message ID' }, + to: { type: 'string', description: 'Recipient email address' }, + subject: { type: 'string', description: 'Email subject' }, + }, +} diff --git a/apps/sim/tools/sendgrid/types.ts b/apps/sim/tools/sendgrid/types.ts new file mode 100644 index 0000000000..a3f2928831 --- /dev/null +++ b/apps/sim/tools/sendgrid/types.ts @@ -0,0 +1,270 @@ +import type { ToolResponse } from '@/tools/types' + +// Shared type definitions +export interface SendGridContact { + id: string + email: string + first_name?: string + last_name?: string + created_at?: string + updated_at?: string + list_ids?: string[] + custom_fields?: Record +} + +export interface SendGridList { + id: string + name: string + contact_count: number + _metadata?: { + self?: string + } +} + +export interface SendGridTemplateVersion { + id: string + template_id: string + name: string + subject: string + active: number | boolean + html_content?: string + plain_content?: string + updated_at?: string +} + +export interface SendGridTemplate { + id: string + name: string + generation: 'legacy' | 'dynamic' + created_at?: string + updated_at?: string + versions?: SendGridTemplateVersion[] +} + +export interface SendGridPersonalization { + to: Array<{ email: string; name?: string }> + cc?: Array<{ email: string }> + bcc?: Array<{ email: string }> + dynamic_template_data?: Record +} + +export interface SendGridMailBody { + personalizations: SendGridPersonalization[] + from: { email: string; name?: string } + subject?: string + template_id?: string + content?: Array<{ type: 'text/plain' | 'text/html'; value?: string }> + reply_to?: { email: string; name?: string } + attachments?: any[] +} + +export interface SendGridContactObject { + email: string + first_name?: string + last_name?: string + [key: string]: unknown +} + +export interface SendGridContactRequest { + contacts: SendGridContactObject[] + list_ids?: string[] +} + +export interface SendGridTemplateVersionRequest { + name: string + subject: string + active: number | boolean + html_content?: string + plain_content?: string +} + +// Common types +export interface SendGridBaseParams { + apiKey: string +} + +export interface SendMailParams extends SendGridBaseParams { + from: string + fromName?: string + to: string + toName?: string + subject?: string + content?: string + contentType?: 'text/plain' | 'text/html' + cc?: string + bcc?: string + replyTo?: string + replyToName?: string + attachments?: string + templateId?: string + dynamicTemplateData?: string +} + +export interface SendMailResult extends ToolResponse { + output: { + success: boolean + messageId?: string + to: string + subject: string + } +} + +// Contact Management types +export interface AddContactParams extends SendGridBaseParams { + email: string + firstName?: string + lastName?: string + customFields?: string // JSON string + listIds?: string // Comma-separated list IDs +} + +export interface UpdateContactParams extends SendGridBaseParams { + contactId?: string + email: string + firstName?: string + lastName?: string + customFields?: string // JSON string + listIds?: string // Comma-separated list IDs +} + +export interface SearchContactsParams extends SendGridBaseParams { + query: string +} + +export interface GetContactParams extends SendGridBaseParams { + contactId: string +} + +export interface DeleteContactParams extends SendGridBaseParams { + contactIds: string // Comma-separated contact IDs +} + +export interface ContactResult extends ToolResponse { + output: { + id?: string + jobId?: string + email: string + firstName?: string + lastName?: string + createdAt?: string + updatedAt?: string + listIds?: string[] + customFields?: Record + message?: string + } +} + +export interface ContactsResult extends ToolResponse { + output: { + contacts: SendGridContact[] + contactCount?: number + } +} + +// List Management types +export interface CreateListParams extends SendGridBaseParams { + name: string +} + +export interface GetListParams extends SendGridBaseParams { + listId: string +} + +export interface UpdateListParams extends SendGridBaseParams { + listId: string + name: string +} + +export interface DeleteListParams extends SendGridBaseParams { + listId: string +} + +export interface ListAllListsParams extends SendGridBaseParams { + pageSize?: number +} + +export interface AddContactsToListParams extends SendGridBaseParams { + listId: string + contacts: string // JSON string array of contact objects with at least email +} + +export interface RemoveContactsFromListParams extends SendGridBaseParams { + listId: string + contactIds: string // Comma-separated contact IDs +} + +export interface ListResult extends ToolResponse { + output: { + id: string + name: string + contactCount?: number + } +} + +export interface ListsResult extends ToolResponse { + output: { + lists: SendGridList[] + } +} + +// Template types +export interface CreateTemplateParams extends SendGridBaseParams { + name: string + generation: 'legacy' | 'dynamic' +} + +export interface GetTemplateParams extends SendGridBaseParams { + templateId: string +} + +export interface UpdateTemplateParams extends SendGridBaseParams { + templateId: string + name: string +} + +export interface DeleteTemplateParams extends SendGridBaseParams { + templateId: string +} + +export interface ListTemplatesParams extends SendGridBaseParams { + generations?: string // 'legacy' or 'dynamic' or both + pageSize?: number +} + +export interface CreateTemplateVersionParams extends SendGridBaseParams { + templateId: string + name: string + subject: string + htmlContent?: string + plainContent?: string + active?: boolean +} + +export interface TemplateResult extends ToolResponse { + output: { + id: string + name: string + generation: string + updatedAt?: string + versions?: SendGridTemplateVersion[] + } +} + +export interface TemplatesResult extends ToolResponse { + output: { + templates: SendGridTemplate[] + } +} + +export interface TemplateVersionResult extends ToolResponse { + output: { + id: string + templateId: string + name: string + subject: string + active: boolean + htmlContent?: string + plainContent?: string + updatedAt?: string + } +} diff --git a/apps/sim/tools/smtp/index.ts b/apps/sim/tools/smtp/index.ts new file mode 100644 index 0000000000..795e624955 --- /dev/null +++ b/apps/sim/tools/smtp/index.ts @@ -0,0 +1,2 @@ +export { smtpSendMailTool } from './send_mail' +export type { SmtpConnectionConfig, SmtpSendMailParams, SmtpSendMailResult } from './types' diff --git a/apps/sim/tools/smtp/send_mail.ts b/apps/sim/tools/smtp/send_mail.ts new file mode 100644 index 0000000000..bc189d62d5 --- /dev/null +++ b/apps/sim/tools/smtp/send_mail.ts @@ -0,0 +1,177 @@ +import type { SmtpSendMailParams, SmtpSendMailResult } from '@/tools/smtp/types' +import type { ToolConfig } from '@/tools/types' + +export const smtpSendMailTool: ToolConfig = { + id: 'smtp_send_mail', + name: 'SMTP Send Mail', + description: 'Send emails via SMTP server', + version: '1.0.0', + + params: { + smtpHost: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'SMTP server hostname (e.g., smtp.gmail.com)', + }, + smtpPort: { + type: 'number', + required: true, + visibility: 'user-only', + description: 'SMTP server port (587 for TLS, 465 for SSL)', + }, + smtpUsername: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'SMTP authentication username', + }, + smtpPassword: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'SMTP authentication password', + }, + smtpSecure: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Security protocol (TLS, SSL, or None)', + }, + + from: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'Sender email address', + }, + to: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'Recipient email address', + }, + subject: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'Email subject', + }, + body: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'Email body content', + }, + contentType: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Content type (text or html)', + }, + + // Optional Fields + fromName: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Display name for sender', + }, + cc: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'CC recipients (comma-separated)', + }, + bcc: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'BCC recipients (comma-separated)', + }, + replyTo: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Reply-to email address', + }, + attachments: { + type: 'file[]', + required: false, + visibility: 'user-only', + description: 'Files to attach to the email', + }, + }, + + request: { + url: '/api/tools/smtp/send', + method: 'POST', + headers: () => ({ + 'Content-Type': 'application/json', + }), + body: (params: SmtpSendMailParams) => ({ + smtpHost: params.smtpHost, + smtpPort: params.smtpPort, + smtpUsername: params.smtpUsername, + smtpPassword: params.smtpPassword, + smtpSecure: params.smtpSecure, + from: params.from, + to: params.to, + subject: params.subject, + body: params.body, + contentType: params.contentType || 'text', + fromName: params.fromName, + cc: params.cc, + bcc: params.bcc, + replyTo: params.replyTo, + attachments: params.attachments, + }), + }, + + transformResponse: async (response) => { + const data = await response.json() + + if (!response.ok) { + return { + success: false, + output: { + success: false, + }, + error: data.error || 'Failed to send email via SMTP', + } + } + + return { + success: true, + output: { + success: true, + messageId: data.messageId, + to: data.to, + subject: data.subject, + }, + } + }, + + outputs: { + success: { + type: 'boolean', + description: 'Whether the email was sent successfully', + }, + messageId: { + type: 'string', + description: 'Message ID from SMTP server', + }, + to: { + type: 'string', + description: 'Recipient email address', + }, + subject: { + type: 'string', + description: 'Email subject', + }, + error: { + type: 'string', + description: 'Error message if sending failed', + }, + }, +} diff --git a/apps/sim/tools/smtp/types.ts b/apps/sim/tools/smtp/types.ts new file mode 100644 index 0000000000..9792262a96 --- /dev/null +++ b/apps/sim/tools/smtp/types.ts @@ -0,0 +1,34 @@ +import type { ToolResponse } from '@/tools/types' + +export interface SmtpConnectionConfig { + smtpHost: string + smtpPort: number + smtpUsername: string + smtpPassword: string + smtpSecure: 'TLS' | 'SSL' | 'None' +} + +export interface SmtpSendMailParams extends SmtpConnectionConfig { + // Email content + from: string + to: string + subject: string + body: string + contentType?: 'text' | 'html' + + // Optional fields + fromName?: string + cc?: string + bcc?: string + replyTo?: string + attachments?: any[] +} + +export interface SmtpSendMailResult extends ToolResponse { + output: { + success: boolean + messageId?: string + to?: string + subject?: string + } +} diff --git a/bun.lock b/bun.lock index 7beee8de41..231c8e38ad 100644 --- a/bun.lock +++ b/bun.lock @@ -16,6 +16,7 @@ "fluent-ffmpeg": "2.1.3", "mongodb": "6.19.0", "neo4j-driver": "6.0.1", + "nodemailer": "7.0.11", "onedollarstats": "0.0.10", "postgres": "^3.4.5", "remark-gfm": "4.0.1", @@ -27,6 +28,7 @@ "@next/env": "15.4.1", "@octokit/rest": "^21.0.0", "@tailwindcss/typography": "0.5.19", + "@types/nodemailer": "7.0.4", "drizzle-kit": "^0.31.4", "husky": "9.1.7", "lint-staged": "16.0.0", @@ -313,6 +315,8 @@ "@aws-sdk/client-s3": ["@aws-sdk/client-s3@3.899.0", "", { "dependencies": { "@aws-crypto/sha1-browser": "5.2.0", "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "3.899.0", "@aws-sdk/credential-provider-node": "3.899.0", "@aws-sdk/middleware-bucket-endpoint": "3.893.0", "@aws-sdk/middleware-expect-continue": "3.893.0", "@aws-sdk/middleware-flexible-checksums": "3.899.0", "@aws-sdk/middleware-host-header": "3.893.0", "@aws-sdk/middleware-location-constraint": "3.893.0", "@aws-sdk/middleware-logger": "3.893.0", "@aws-sdk/middleware-recursion-detection": "3.893.0", "@aws-sdk/middleware-sdk-s3": "3.899.0", "@aws-sdk/middleware-ssec": "3.893.0", "@aws-sdk/middleware-user-agent": "3.899.0", "@aws-sdk/region-config-resolver": "3.893.0", "@aws-sdk/signature-v4-multi-region": "3.899.0", "@aws-sdk/types": "3.893.0", "@aws-sdk/util-endpoints": "3.895.0", "@aws-sdk/util-user-agent-browser": "3.893.0", "@aws-sdk/util-user-agent-node": "3.899.0", "@aws-sdk/xml-builder": "3.894.0", "@smithy/config-resolver": "^4.2.2", "@smithy/core": "^3.13.0", "@smithy/eventstream-serde-browser": "^4.1.1", "@smithy/eventstream-serde-config-resolver": "^4.2.1", "@smithy/eventstream-serde-node": "^4.1.1", "@smithy/fetch-http-handler": "^5.2.1", "@smithy/hash-blob-browser": "^4.1.1", "@smithy/hash-node": "^4.1.1", "@smithy/hash-stream-node": "^4.1.1", "@smithy/invalid-dependency": "^4.1.1", "@smithy/md5-js": "^4.1.1", "@smithy/middleware-content-length": "^4.1.1", "@smithy/middleware-endpoint": "^4.2.5", "@smithy/middleware-retry": "^4.3.1", "@smithy/middleware-serde": "^4.1.1", "@smithy/middleware-stack": "^4.1.1", "@smithy/node-config-provider": "^4.2.2", "@smithy/node-http-handler": "^4.2.1", "@smithy/protocol-http": "^5.2.1", "@smithy/smithy-client": "^4.6.5", "@smithy/types": "^4.5.0", "@smithy/url-parser": "^4.1.1", "@smithy/util-base64": "^4.1.0", "@smithy/util-body-length-browser": "^4.1.0", "@smithy/util-body-length-node": "^4.1.0", "@smithy/util-defaults-mode-browser": "^4.1.5", "@smithy/util-defaults-mode-node": "^4.1.5", "@smithy/util-endpoints": "^3.1.2", "@smithy/util-middleware": "^4.1.1", "@smithy/util-retry": "^4.1.2", "@smithy/util-stream": "^4.3.2", "@smithy/util-utf8": "^4.1.0", "@smithy/util-waiter": "^4.1.1", "@smithy/uuid": "^1.0.0", "tslib": "^2.6.2" } }, "sha512-m/XQT0Rew4ff1Xmug+8n7f3uwom2DhbPwKWjUpluKo8JNCJJTIlfFSe1tnSimeE7RdLcIigK0YpvE50OjZZHGw=="], + "@aws-sdk/client-sesv2": ["@aws-sdk/client-sesv2@3.940.0", "", { "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "3.940.0", "@aws-sdk/credential-provider-node": "3.940.0", "@aws-sdk/middleware-host-header": "3.936.0", "@aws-sdk/middleware-logger": "3.936.0", "@aws-sdk/middleware-recursion-detection": "3.936.0", "@aws-sdk/middleware-user-agent": "3.940.0", "@aws-sdk/region-config-resolver": "3.936.0", "@aws-sdk/signature-v4-multi-region": "3.940.0", "@aws-sdk/types": "3.936.0", "@aws-sdk/util-endpoints": "3.936.0", "@aws-sdk/util-user-agent-browser": "3.936.0", "@aws-sdk/util-user-agent-node": "3.940.0", "@smithy/config-resolver": "^4.4.3", "@smithy/core": "^3.18.5", "@smithy/fetch-http-handler": "^5.3.6", "@smithy/hash-node": "^4.2.5", "@smithy/invalid-dependency": "^4.2.5", "@smithy/middleware-content-length": "^4.2.5", "@smithy/middleware-endpoint": "^4.3.12", "@smithy/middleware-retry": "^4.4.12", "@smithy/middleware-serde": "^4.2.6", "@smithy/middleware-stack": "^4.2.5", "@smithy/node-config-provider": "^4.3.5", "@smithy/node-http-handler": "^4.4.5", "@smithy/protocol-http": "^5.3.5", "@smithy/smithy-client": "^4.9.8", "@smithy/types": "^4.9.0", "@smithy/url-parser": "^4.2.5", "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", "@smithy/util-body-length-node": "^4.2.1", "@smithy/util-defaults-mode-browser": "^4.3.11", "@smithy/util-defaults-mode-node": "^4.2.14", "@smithy/util-endpoints": "^3.2.5", "@smithy/util-middleware": "^4.2.5", "@smithy/util-retry": "^4.2.5", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-jDQ4x2HwB2/UXBS7CTeSDiIb+sVsYGDyxTeXdrRAtqNdGv8kC54fbwokDiJ/mnMyB2gyXWw57BqeDJNkZuLmsw=="], + "@aws-sdk/client-sso": ["@aws-sdk/client-sso@3.899.0", "", { "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "3.899.0", "@aws-sdk/middleware-host-header": "3.893.0", "@aws-sdk/middleware-logger": "3.893.0", "@aws-sdk/middleware-recursion-detection": "3.893.0", "@aws-sdk/middleware-user-agent": "3.899.0", "@aws-sdk/region-config-resolver": "3.893.0", "@aws-sdk/types": "3.893.0", "@aws-sdk/util-endpoints": "3.895.0", "@aws-sdk/util-user-agent-browser": "3.893.0", "@aws-sdk/util-user-agent-node": "3.899.0", "@smithy/config-resolver": "^4.2.2", "@smithy/core": "^3.13.0", "@smithy/fetch-http-handler": "^5.2.1", "@smithy/hash-node": "^4.1.1", "@smithy/invalid-dependency": "^4.1.1", "@smithy/middleware-content-length": "^4.1.1", "@smithy/middleware-endpoint": "^4.2.5", "@smithy/middleware-retry": "^4.3.1", "@smithy/middleware-serde": "^4.1.1", "@smithy/middleware-stack": "^4.1.1", "@smithy/node-config-provider": "^4.2.2", "@smithy/node-http-handler": "^4.2.1", "@smithy/protocol-http": "^5.2.1", "@smithy/smithy-client": "^4.6.5", "@smithy/types": "^4.5.0", "@smithy/url-parser": "^4.1.1", "@smithy/util-base64": "^4.1.0", "@smithy/util-body-length-browser": "^4.1.0", "@smithy/util-body-length-node": "^4.1.0", "@smithy/util-defaults-mode-browser": "^4.1.5", "@smithy/util-defaults-mode-node": "^4.1.5", "@smithy/util-endpoints": "^3.1.2", "@smithy/util-middleware": "^4.1.1", "@smithy/util-retry": "^4.1.2", "@smithy/util-utf8": "^4.1.0", "tslib": "^2.6.2" } }, "sha512-EKz/iiVDv2OC8/3ONcXG3+rhphx9Heh7KXQdsZzsAXGVn6mWtrHQLrWjgONckmK4LrD07y4+5WlJlGkMxSMA5A=="], "@aws-sdk/core": ["@aws-sdk/core@3.899.0", "", { "dependencies": { "@aws-sdk/types": "3.893.0", "@aws-sdk/xml-builder": "3.894.0", "@smithy/core": "^3.13.0", "@smithy/node-config-provider": "^4.2.2", "@smithy/property-provider": "^4.1.1", "@smithy/protocol-http": "^5.2.1", "@smithy/signature-v4": "^5.2.1", "@smithy/smithy-client": "^4.6.5", "@smithy/types": "^4.5.0", "@smithy/util-base64": "^4.1.0", "@smithy/util-middleware": "^4.1.1", "@smithy/util-utf8": "^4.1.0", "tslib": "^2.6.2" } }, "sha512-Enp5Zw37xaRlnscyaelaUZNxVqyE3CTS8gjahFbW2bbzVtRD2itHBVgq8A3lvKiFb7Feoxa71aTe0fQ1I6AhQQ=="], @@ -323,6 +327,8 @@ "@aws-sdk/credential-provider-ini": ["@aws-sdk/credential-provider-ini@3.899.0", "", { "dependencies": { "@aws-sdk/core": "3.899.0", "@aws-sdk/credential-provider-env": "3.899.0", "@aws-sdk/credential-provider-http": "3.899.0", "@aws-sdk/credential-provider-process": "3.899.0", "@aws-sdk/credential-provider-sso": "3.899.0", "@aws-sdk/credential-provider-web-identity": "3.899.0", "@aws-sdk/nested-clients": "3.899.0", "@aws-sdk/types": "3.893.0", "@smithy/credential-provider-imds": "^4.1.2", "@smithy/property-provider": "^4.1.1", "@smithy/shared-ini-file-loader": "^4.2.0", "@smithy/types": "^4.5.0", "tslib": "^2.6.2" } }, "sha512-B8oFNFTDV0j1yiJiqzkC2ybml+theNnmsLrTLBhJbnBLWkxEcmVGKVIMnATW9BUCBhHmEtDiogdNIzSwP8tbMw=="], + "@aws-sdk/credential-provider-login": ["@aws-sdk/credential-provider-login@3.940.0", "", { "dependencies": { "@aws-sdk/core": "3.940.0", "@aws-sdk/nested-clients": "3.940.0", "@aws-sdk/types": "3.936.0", "@smithy/property-provider": "^4.2.5", "@smithy/protocol-http": "^5.3.5", "@smithy/shared-ini-file-loader": "^4.4.0", "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-fOKC3VZkwa9T2l2VFKWRtfHQPQuISqqNl35ZhcXjWKVwRwl/o7THPMkqI4XwgT2noGa7LLYVbWMwnsgSsBqglg=="], + "@aws-sdk/credential-provider-node": ["@aws-sdk/credential-provider-node@3.899.0", "", { "dependencies": { "@aws-sdk/credential-provider-env": "3.899.0", "@aws-sdk/credential-provider-http": "3.899.0", "@aws-sdk/credential-provider-ini": "3.899.0", "@aws-sdk/credential-provider-process": "3.899.0", "@aws-sdk/credential-provider-sso": "3.899.0", "@aws-sdk/credential-provider-web-identity": "3.899.0", "@aws-sdk/types": "3.893.0", "@smithy/credential-provider-imds": "^4.1.2", "@smithy/property-provider": "^4.1.1", "@smithy/shared-ini-file-loader": "^4.2.0", "@smithy/types": "^4.5.0", "tslib": "^2.6.2" } }, "sha512-nHBnZ2ZCOqTGJ2A9xpVj8iK6+WV+j0JNv3XGEkIuL4mqtGEPJlEex/0mD/hqc1VF8wZzojji2OQ3892m1mUOSA=="], "@aws-sdk/credential-provider-process": ["@aws-sdk/credential-provider-process@3.899.0", "", { "dependencies": { "@aws-sdk/core": "3.899.0", "@aws-sdk/types": "3.893.0", "@smithy/property-provider": "^4.1.1", "@smithy/shared-ini-file-loader": "^4.2.0", "@smithy/types": "^4.5.0", "tslib": "^2.6.2" } }, "sha512-1PWSejKcJQUKBNPIqSHlEW4w8vSjmb+3kNJqCinJybjp5uP5BJgBp6QNcb8Nv30VBM0bn3ajVd76LCq4ZshQAw=="], @@ -1367,6 +1373,8 @@ "@types/node-fetch": ["@types/node-fetch@2.6.13", "", { "dependencies": { "@types/node": "*", "form-data": "^4.0.4" } }, "sha512-QGpRVpzSaUs30JBSGPjOg4Uveu384erbHBoT1zeONvyCfwQxIkUshLAOqN/k9EjGviPRmWTTe6aH2qySWKTVSw=="], + "@types/nodemailer": ["@types/nodemailer@7.0.4", "", { "dependencies": { "@aws-sdk/client-sesv2": "^3.839.0", "@types/node": "*" } }, "sha512-ee8fxWqOchH+Hv6MDDNNy028kwvVnLplrStm4Zf/3uHWw5zzo8FoYYeffpJtGs2wWysEumMH0ZIdMGMY1eMAow=="], + "@types/papaparse": ["@types/papaparse@5.3.16", "", { "dependencies": { "@types/node": "*" } }, "sha512-T3VuKMC2H0lgsjI9buTB3uuKj3EMD2eap1MOuEQuBQ44EnDx/IkGhU6EwiTf9zG3za4SKlmwKAImdDKdNnCsXg=="], "@types/prismjs": ["@types/prismjs@1.26.5", "", {}, "sha512-AUZTa7hQ2KY5L7AmtSiqxlhWxb4ina0yd8hNbl4TWuqnv/pFP0nDMb3YrfSBf4hJVGLh2YEIBfKaBW/9UEl6IQ=="], @@ -2497,6 +2505,8 @@ "node-rsa": ["node-rsa@1.1.1", "", { "dependencies": { "asn1": "^0.2.4" } }, "sha512-Jd4cvbJMryN21r5HgxQOpMEqv+ooke/korixNNK3mGqfGJmy0M77WDDzo/05969+OkMy3XW1UuZsSmW9KQm7Fw=="], + "nodemailer": ["nodemailer@7.0.11", "", {}, "sha512-gnXhNRE0FNhD7wPSCGhdNh46Hs6nm+uTyg+Kq0cZukNQiYdnCsoQjodNP9BQVG9XrcK/v6/MgpAPBUFyzh9pvw=="], + "normalize-path": ["normalize-path@3.0.0", "", {}, "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="], "normalize-range": ["normalize-range@0.1.2", "", {}, "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA=="], @@ -3241,6 +3251,94 @@ "@aws-crypto/util/@smithy/util-utf8": ["@smithy/util-utf8@2.3.0", "", { "dependencies": { "@smithy/util-buffer-from": "^2.2.0", "tslib": "^2.6.2" } }, "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A=="], + "@aws-sdk/client-sesv2/@aws-sdk/core": ["@aws-sdk/core@3.940.0", "", { "dependencies": { "@aws-sdk/types": "3.936.0", "@aws-sdk/xml-builder": "3.930.0", "@smithy/core": "^3.18.5", "@smithy/node-config-provider": "^4.3.5", "@smithy/property-provider": "^4.2.5", "@smithy/protocol-http": "^5.3.5", "@smithy/signature-v4": "^5.3.5", "@smithy/smithy-client": "^4.9.8", "@smithy/types": "^4.9.0", "@smithy/util-base64": "^4.3.0", "@smithy/util-middleware": "^4.2.5", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-KsGD2FLaX5ngJao1mHxodIVU9VYd1E8810fcYiGwO1PFHDzf5BEkp6D9IdMeQwT8Q6JLYtiiT1Y/o3UCScnGoA=="], + + "@aws-sdk/client-sesv2/@aws-sdk/credential-provider-node": ["@aws-sdk/credential-provider-node@3.940.0", "", { "dependencies": { "@aws-sdk/credential-provider-env": "3.940.0", "@aws-sdk/credential-provider-http": "3.940.0", "@aws-sdk/credential-provider-ini": "3.940.0", "@aws-sdk/credential-provider-process": "3.940.0", "@aws-sdk/credential-provider-sso": "3.940.0", "@aws-sdk/credential-provider-web-identity": "3.940.0", "@aws-sdk/types": "3.936.0", "@smithy/credential-provider-imds": "^4.2.5", "@smithy/property-provider": "^4.2.5", "@smithy/shared-ini-file-loader": "^4.4.0", "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-M8NFAvgvO6xZjiti5kztFiAYmSmSlG3eUfr4ZHSfXYZUA/KUdZU/D6xJyaLnU8cYRWBludb6K9XPKKVwKfqm4g=="], + + "@aws-sdk/client-sesv2/@aws-sdk/middleware-host-header": ["@aws-sdk/middleware-host-header@3.936.0", "", { "dependencies": { "@aws-sdk/types": "3.936.0", "@smithy/protocol-http": "^5.3.5", "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-tAaObaAnsP1XnLGndfkGWFuzrJYuk9W0b/nLvol66t8FZExIAf/WdkT2NNAWOYxljVs++oHnyHBCxIlaHrzSiw=="], + + "@aws-sdk/client-sesv2/@aws-sdk/middleware-logger": ["@aws-sdk/middleware-logger@3.936.0", "", { "dependencies": { "@aws-sdk/types": "3.936.0", "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-aPSJ12d3a3Ea5nyEnLbijCaaYJT2QjQ9iW+zGh5QcZYXmOGWbKVyPSxmVOboZQG+c1M8t6d2O7tqrwzIq8L8qw=="], + + "@aws-sdk/client-sesv2/@aws-sdk/middleware-recursion-detection": ["@aws-sdk/middleware-recursion-detection@3.936.0", "", { "dependencies": { "@aws-sdk/types": "3.936.0", "@aws/lambda-invoke-store": "^0.2.0", "@smithy/protocol-http": "^5.3.5", "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-l4aGbHpXM45YNgXggIux1HgsCVAvvBoqHPkqLnqMl9QVapfuSTjJHfDYDsx1Xxct6/m7qSMUzanBALhiaGO2fA=="], + + "@aws-sdk/client-sesv2/@aws-sdk/middleware-user-agent": ["@aws-sdk/middleware-user-agent@3.940.0", "", { "dependencies": { "@aws-sdk/core": "3.940.0", "@aws-sdk/types": "3.936.0", "@aws-sdk/util-endpoints": "3.936.0", "@smithy/core": "^3.18.5", "@smithy/protocol-http": "^5.3.5", "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-nJbLrUj6fY+l2W2rIB9P4Qvpiy0tnTdg/dmixRxrU1z3e8wBdspJlyE+AZN4fuVbeL6rrRrO/zxQC1bB3cw5IA=="], + + "@aws-sdk/client-sesv2/@aws-sdk/region-config-resolver": ["@aws-sdk/region-config-resolver@3.936.0", "", { "dependencies": { "@aws-sdk/types": "3.936.0", "@smithy/config-resolver": "^4.4.3", "@smithy/node-config-provider": "^4.3.5", "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-wOKhzzWsshXGduxO4pqSiNyL9oUtk4BEvjWm9aaq6Hmfdoydq6v6t0rAGHWPjFwy9z2haovGRi3C8IxdMB4muw=="], + + "@aws-sdk/client-sesv2/@aws-sdk/signature-v4-multi-region": ["@aws-sdk/signature-v4-multi-region@3.940.0", "", { "dependencies": { "@aws-sdk/middleware-sdk-s3": "3.940.0", "@aws-sdk/types": "3.936.0", "@smithy/protocol-http": "^5.3.5", "@smithy/signature-v4": "^5.3.5", "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-ugHZEoktD/bG6mdgmhzLDjMP2VrYRAUPRPF1DpCyiZexkH7DCU7XrSJyXMvkcf0DHV+URk0q2sLf/oqn1D2uYw=="], + + "@aws-sdk/client-sesv2/@aws-sdk/types": ["@aws-sdk/types@3.936.0", "", { "dependencies": { "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-uz0/VlMd2pP5MepdrHizd+T+OKfyK4r3OA9JI+L/lPKg0YFQosdJNCKisr6o70E3dh8iMpFYxF1UN/4uZsyARg=="], + + "@aws-sdk/client-sesv2/@aws-sdk/util-endpoints": ["@aws-sdk/util-endpoints@3.936.0", "", { "dependencies": { "@aws-sdk/types": "3.936.0", "@smithy/types": "^4.9.0", "@smithy/url-parser": "^4.2.5", "@smithy/util-endpoints": "^3.2.5", "tslib": "^2.6.2" } }, "sha512-0Zx3Ntdpu+z9Wlm7JKUBOzS9EunwKAb4KdGUQQxDqh5Lc3ta5uBoub+FgmVuzwnmBu9U1Os8UuwVTH0Lgu+P5w=="], + + "@aws-sdk/client-sesv2/@aws-sdk/util-user-agent-browser": ["@aws-sdk/util-user-agent-browser@3.936.0", "", { "dependencies": { "@aws-sdk/types": "3.936.0", "@smithy/types": "^4.9.0", "bowser": "^2.11.0", "tslib": "^2.6.2" } }, "sha512-eZ/XF6NxMtu+iCma58GRNRxSq4lHo6zHQLOZRIeL/ghqYJirqHdenMOwrzPettj60KWlv827RVebP9oNVrwZbw=="], + + "@aws-sdk/client-sesv2/@aws-sdk/util-user-agent-node": ["@aws-sdk/util-user-agent-node@3.940.0", "", { "dependencies": { "@aws-sdk/middleware-user-agent": "3.940.0", "@aws-sdk/types": "3.936.0", "@smithy/node-config-provider": "^4.3.5", "@smithy/types": "^4.9.0", "tslib": "^2.6.2" }, "peerDependencies": { "aws-crt": ">=1.0.0" }, "optionalPeers": ["aws-crt"] }, "sha512-dlD/F+L/jN26I8Zg5x0oDGJiA+/WEQmnSE27fi5ydvYnpfQLwThtQo9SsNS47XSR/SOULaaoC9qx929rZuo74A=="], + + "@aws-sdk/client-sesv2/@smithy/config-resolver": ["@smithy/config-resolver@4.4.3", "", { "dependencies": { "@smithy/node-config-provider": "^4.3.5", "@smithy/types": "^4.9.0", "@smithy/util-config-provider": "^4.2.0", "@smithy/util-endpoints": "^3.2.5", "@smithy/util-middleware": "^4.2.5", "tslib": "^2.6.2" } }, "sha512-ezHLe1tKLUxDJo2LHtDuEDyWXolw8WGOR92qb4bQdWq/zKenO5BvctZGrVJBK08zjezSk7bmbKFOXIVyChvDLw=="], + + "@aws-sdk/client-sesv2/@smithy/core": ["@smithy/core@3.18.5", "", { "dependencies": { "@smithy/middleware-serde": "^4.2.6", "@smithy/protocol-http": "^5.3.5", "@smithy/types": "^4.9.0", "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", "@smithy/util-middleware": "^4.2.5", "@smithy/util-stream": "^4.5.6", "@smithy/util-utf8": "^4.2.0", "@smithy/uuid": "^1.1.0", "tslib": "^2.6.2" } }, "sha512-6gnIz3h+PEPQGDj8MnRSjDvKBah042jEoPgjFGJ4iJLBE78L4lY/n98x14XyPF4u3lN179Ub/ZKFY5za9GeLQw=="], + + "@aws-sdk/client-sesv2/@smithy/fetch-http-handler": ["@smithy/fetch-http-handler@5.3.6", "", { "dependencies": { "@smithy/protocol-http": "^5.3.5", "@smithy/querystring-builder": "^4.2.5", "@smithy/types": "^4.9.0", "@smithy/util-base64": "^4.3.0", "tslib": "^2.6.2" } }, "sha512-3+RG3EA6BBJ/ofZUeTFJA7mHfSYrZtQIrDP9dI8Lf7X6Jbos2jptuLrAAteDiFVrmbEmLSuRG/bUKzfAXk7dhg=="], + + "@aws-sdk/client-sesv2/@smithy/hash-node": ["@smithy/hash-node@4.2.5", "", { "dependencies": { "@smithy/types": "^4.9.0", "@smithy/util-buffer-from": "^4.2.0", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-DpYX914YOfA3UDT9CN1BM787PcHfWRBB43fFGCYrZFUH0Jv+5t8yYl+Pd5PW4+QzoGEDvn5d5QIO4j2HyYZQSA=="], + + "@aws-sdk/client-sesv2/@smithy/invalid-dependency": ["@smithy/invalid-dependency@4.2.5", "", { "dependencies": { "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-2L2erASEro1WC5nV+plwIMxrTXpvpfzl4e+Nre6vBVRR2HKeGGcvpJyyL3/PpiSg+cJG2KpTmZmq934Olb6e5A=="], + + "@aws-sdk/client-sesv2/@smithy/middleware-content-length": ["@smithy/middleware-content-length@4.2.5", "", { "dependencies": { "@smithy/protocol-http": "^5.3.5", "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-Y/RabVa5vbl5FuHYV2vUCwvh/dqzrEY/K2yWPSqvhFUwIY0atLqO4TienjBXakoy4zrKAMCZwg+YEqmH7jaN7A=="], + + "@aws-sdk/client-sesv2/@smithy/middleware-endpoint": ["@smithy/middleware-endpoint@4.3.12", "", { "dependencies": { "@smithy/core": "^3.18.5", "@smithy/middleware-serde": "^4.2.6", "@smithy/node-config-provider": "^4.3.5", "@smithy/shared-ini-file-loader": "^4.4.0", "@smithy/types": "^4.9.0", "@smithy/url-parser": "^4.2.5", "@smithy/util-middleware": "^4.2.5", "tslib": "^2.6.2" } }, "sha512-9pAX/H+VQPzNbouhDhkW723igBMLgrI8OtX+++M7iKJgg/zY/Ig3i1e6seCcx22FWhE6Q/S61BRdi2wXBORT+A=="], + + "@aws-sdk/client-sesv2/@smithy/middleware-retry": ["@smithy/middleware-retry@4.4.12", "", { "dependencies": { "@smithy/node-config-provider": "^4.3.5", "@smithy/protocol-http": "^5.3.5", "@smithy/service-error-classification": "^4.2.5", "@smithy/smithy-client": "^4.9.8", "@smithy/types": "^4.9.0", "@smithy/util-middleware": "^4.2.5", "@smithy/util-retry": "^4.2.5", "@smithy/uuid": "^1.1.0", "tslib": "^2.6.2" } }, "sha512-S4kWNKFowYd0lID7/DBqWHOQxmxlsf0jBaos9chQZUWTVOjSW1Ogyh8/ib5tM+agFDJ/TCxuCTvrnlc+9cIBcQ=="], + + "@aws-sdk/client-sesv2/@smithy/middleware-serde": ["@smithy/middleware-serde@4.2.6", "", { "dependencies": { "@smithy/protocol-http": "^5.3.5", "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-VkLoE/z7e2g8pirwisLz8XJWedUSY8my/qrp81VmAdyrhi94T+riBfwP+AOEEFR9rFTSonC/5D2eWNmFabHyGQ=="], + + "@aws-sdk/client-sesv2/@smithy/middleware-stack": ["@smithy/middleware-stack@4.2.5", "", { "dependencies": { "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-bYrutc+neOyWxtZdbB2USbQttZN0mXaOyYLIsaTbJhFsfpXyGWUxJpEuO1rJ8IIJm2qH4+xJT0mxUSsEDTYwdQ=="], + + "@aws-sdk/client-sesv2/@smithy/node-config-provider": ["@smithy/node-config-provider@4.3.5", "", { "dependencies": { "@smithy/property-provider": "^4.2.5", "@smithy/shared-ini-file-loader": "^4.4.0", "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-UTurh1C4qkVCtqggI36DGbLB2Kv8UlcFdMXDcWMbqVY2uRg0XmT9Pb4Vj6oSQ34eizO1fvR0RnFV4Axw4IrrAg=="], + + "@aws-sdk/client-sesv2/@smithy/node-http-handler": ["@smithy/node-http-handler@4.4.5", "", { "dependencies": { "@smithy/abort-controller": "^4.2.5", "@smithy/protocol-http": "^5.3.5", "@smithy/querystring-builder": "^4.2.5", "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-CMnzM9R2WqlqXQGtIlsHMEZfXKJVTIrqCNoSd/QpAyp+Dw0a1Vps13l6ma1fH8g7zSPNsA59B/kWgeylFuA/lw=="], + + "@aws-sdk/client-sesv2/@smithy/protocol-http": ["@smithy/protocol-http@5.3.5", "", { "dependencies": { "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-RlaL+sA0LNMp03bf7XPbFmT5gN+w3besXSWMkA8rcmxLSVfiEXElQi4O2IWwPfxzcHkxqrwBFMbngB8yx/RvaQ=="], + + "@aws-sdk/client-sesv2/@smithy/smithy-client": ["@smithy/smithy-client@4.9.8", "", { "dependencies": { "@smithy/core": "^3.18.5", "@smithy/middleware-endpoint": "^4.3.12", "@smithy/middleware-stack": "^4.2.5", "@smithy/protocol-http": "^5.3.5", "@smithy/types": "^4.9.0", "@smithy/util-stream": "^4.5.6", "tslib": "^2.6.2" } }, "sha512-8xgq3LgKDEFoIrLWBho/oYKyWByw9/corz7vuh1upv7ZBm0ZMjGYBhbn6v643WoIqA9UTcx5A5htEp/YatUwMA=="], + + "@aws-sdk/client-sesv2/@smithy/types": ["@smithy/types@4.9.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-MvUbdnXDTwykR8cB1WZvNNwqoWVaTRA0RLlLmf/cIFNMM2cKWz01X4Ly6SMC4Kks30r8tT3Cty0jmeWfiuyHTA=="], + + "@aws-sdk/client-sesv2/@smithy/url-parser": ["@smithy/url-parser@4.2.5", "", { "dependencies": { "@smithy/querystring-parser": "^4.2.5", "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-VaxMGsilqFnK1CeBX+LXnSuaMx4sTL/6znSZh2829txWieazdVxr54HmiyTsIbpOTLcf5nYpq9lpzmwRdxj6rQ=="], + + "@aws-sdk/client-sesv2/@smithy/util-base64": ["@smithy/util-base64@4.3.0", "", { "dependencies": { "@smithy/util-buffer-from": "^4.2.0", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-GkXZ59JfyxsIwNTWFnjmFEI8kZpRNIBfxKjv09+nkAWPt/4aGaEWMM04m4sxgNVWkbt2MdSvE3KF/PfX4nFedQ=="], + + "@aws-sdk/client-sesv2/@smithy/util-body-length-browser": ["@smithy/util-body-length-browser@4.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-Fkoh/I76szMKJnBXWPdFkQJl2r9SjPt3cMzLdOB6eJ4Pnpas8hVoWPYemX/peO0yrrvldgCUVJqOAjUrOLjbxg=="], + + "@aws-sdk/client-sesv2/@smithy/util-body-length-node": ["@smithy/util-body-length-node@4.2.1", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-h53dz/pISVrVrfxV1iqXlx5pRg3V2YWFcSQyPyXZRrZoZj4R4DeWRDo1a7dd3CPTcFi3kE+98tuNyD2axyZReA=="], + + "@aws-sdk/client-sesv2/@smithy/util-defaults-mode-browser": ["@smithy/util-defaults-mode-browser@4.3.11", "", { "dependencies": { "@smithy/property-provider": "^4.2.5", "@smithy/smithy-client": "^4.9.8", "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-yHv+r6wSQXEXTPVCIQTNmXVWs7ekBTpMVErjqZoWkYN75HIFN5y9+/+sYOejfAuvxWGvgzgxbTHa/oz61YTbKw=="], + + "@aws-sdk/client-sesv2/@smithy/util-defaults-mode-node": ["@smithy/util-defaults-mode-node@4.2.14", "", { "dependencies": { "@smithy/config-resolver": "^4.4.3", "@smithy/credential-provider-imds": "^4.2.5", "@smithy/node-config-provider": "^4.3.5", "@smithy/property-provider": "^4.2.5", "@smithy/smithy-client": "^4.9.8", "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-ljZN3iRvaJUgulfvobIuG97q1iUuCMrvXAlkZ4msY+ZuVHQHDIqn7FKZCEj+bx8omz6kF5yQXms/xhzjIO5XiA=="], + + "@aws-sdk/client-sesv2/@smithy/util-endpoints": ["@smithy/util-endpoints@3.2.5", "", { "dependencies": { "@smithy/node-config-provider": "^4.3.5", "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-3O63AAWu2cSNQZp+ayl9I3NapW1p1rR5mlVHcF6hAB1dPZUQFfRPYtplWX/3xrzWthPGj5FqB12taJJCfH6s8A=="], + + "@aws-sdk/client-sesv2/@smithy/util-middleware": ["@smithy/util-middleware@4.2.5", "", { "dependencies": { "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-6Y3+rvBF7+PZOc40ybeZMcGln6xJGVeY60E7jy9Mv5iKpMJpHgRE6dKy9ScsVxvfAYuEX4Q9a65DQX90KaQ3bA=="], + + "@aws-sdk/client-sesv2/@smithy/util-retry": ["@smithy/util-retry@4.2.5", "", { "dependencies": { "@smithy/service-error-classification": "^4.2.5", "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-GBj3+EZBbN4NAqJ/7pAhsXdfzdlznOh8PydUijy6FpNIMnHPSMO2/rP4HKu+UFeikJxShERk528oy7GT79YiJg=="], + + "@aws-sdk/client-sesv2/@smithy/util-utf8": ["@smithy/util-utf8@4.2.0", "", { "dependencies": { "@smithy/util-buffer-from": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-zBPfuzoI8xyBtR2P6WQj63Rz8i3AmfAaJLuNG8dWsfvPe8lO4aCPYLn879mEgHndZH1zQ2oXmG8O1GGzzaoZiw=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/core": ["@aws-sdk/core@3.940.0", "", { "dependencies": { "@aws-sdk/types": "3.936.0", "@aws-sdk/xml-builder": "3.930.0", "@smithy/core": "^3.18.5", "@smithy/node-config-provider": "^4.3.5", "@smithy/property-provider": "^4.2.5", "@smithy/protocol-http": "^5.3.5", "@smithy/signature-v4": "^5.3.5", "@smithy/smithy-client": "^4.9.8", "@smithy/types": "^4.9.0", "@smithy/util-base64": "^4.3.0", "@smithy/util-middleware": "^4.2.5", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-KsGD2FLaX5ngJao1mHxodIVU9VYd1E8810fcYiGwO1PFHDzf5BEkp6D9IdMeQwT8Q6JLYtiiT1Y/o3UCScnGoA=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/nested-clients": ["@aws-sdk/nested-clients@3.940.0", "", { "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "3.940.0", "@aws-sdk/middleware-host-header": "3.936.0", "@aws-sdk/middleware-logger": "3.936.0", "@aws-sdk/middleware-recursion-detection": "3.936.0", "@aws-sdk/middleware-user-agent": "3.940.0", "@aws-sdk/region-config-resolver": "3.936.0", "@aws-sdk/types": "3.936.0", "@aws-sdk/util-endpoints": "3.936.0", "@aws-sdk/util-user-agent-browser": "3.936.0", "@aws-sdk/util-user-agent-node": "3.940.0", "@smithy/config-resolver": "^4.4.3", "@smithy/core": "^3.18.5", "@smithy/fetch-http-handler": "^5.3.6", "@smithy/hash-node": "^4.2.5", "@smithy/invalid-dependency": "^4.2.5", "@smithy/middleware-content-length": "^4.2.5", "@smithy/middleware-endpoint": "^4.3.12", "@smithy/middleware-retry": "^4.4.12", "@smithy/middleware-serde": "^4.2.6", "@smithy/middleware-stack": "^4.2.5", "@smithy/node-config-provider": "^4.3.5", "@smithy/node-http-handler": "^4.4.5", "@smithy/protocol-http": "^5.3.5", "@smithy/smithy-client": "^4.9.8", "@smithy/types": "^4.9.0", "@smithy/url-parser": "^4.2.5", "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", "@smithy/util-body-length-node": "^4.2.1", "@smithy/util-defaults-mode-browser": "^4.3.11", "@smithy/util-defaults-mode-node": "^4.2.14", "@smithy/util-endpoints": "^3.2.5", "@smithy/util-middleware": "^4.2.5", "@smithy/util-retry": "^4.2.5", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-x0mdv6DkjXqXEcQj3URbCltEzW6hoy/1uIL+i8gExP6YKrnhiZ7SzuB4gPls2UOpK5UqLiqXjhRLfBb1C9i4Dw=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/types": ["@aws-sdk/types@3.936.0", "", { "dependencies": { "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-uz0/VlMd2pP5MepdrHizd+T+OKfyK4r3OA9JI+L/lPKg0YFQosdJNCKisr6o70E3dh8iMpFYxF1UN/4uZsyARg=="], + + "@aws-sdk/credential-provider-login/@smithy/property-provider": ["@smithy/property-provider@4.2.5", "", { "dependencies": { "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-8iLN1XSE1rl4MuxvQ+5OSk/Zb5El7NJZ1td6Tn+8dQQHIjp59Lwl6bd0+nzw6SKm2wSSriH2v/I9LPzUic7EOg=="], + + "@aws-sdk/credential-provider-login/@smithy/protocol-http": ["@smithy/protocol-http@5.3.5", "", { "dependencies": { "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-RlaL+sA0LNMp03bf7XPbFmT5gN+w3besXSWMkA8rcmxLSVfiEXElQi4O2IWwPfxzcHkxqrwBFMbngB8yx/RvaQ=="], + + "@aws-sdk/credential-provider-login/@smithy/shared-ini-file-loader": ["@smithy/shared-ini-file-loader@4.4.0", "", { "dependencies": { "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-5WmZ5+kJgJDjwXXIzr1vDTG+RhF9wzSODQBfkrQ2VVkYALKGvZX1lgVSxEkgicSAFnFhPj5rudJV0zoinqS0bA=="], + + "@aws-sdk/credential-provider-login/@smithy/types": ["@smithy/types@4.9.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-MvUbdnXDTwykR8cB1WZvNNwqoWVaTRA0RLlLmf/cIFNMM2cKWz01X4Ly6SMC4Kks30r8tT3Cty0jmeWfiuyHTA=="], + "@azure/communication-email/tslib": ["tslib@1.14.1", "", {}, "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="], "@azure/communication-email/uuid": ["uuid@8.3.2", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="], @@ -3445,6 +3543,8 @@ "@types/node-fetch/@types/node": ["@types/node@24.2.1", "", { "dependencies": { "undici-types": "~7.10.0" } }, "sha512-DRh5K+ka5eJic8CjH7td8QpYEV6Zo10gfRkjHCO3weqZHWDtAaSTFtl4+VMqOJ4N5jcuhZ9/l+yy8rVgw7BQeQ=="], + "@types/nodemailer/@types/node": ["@types/node@24.2.1", "", { "dependencies": { "undici-types": "~7.10.0" } }, "sha512-DRh5K+ka5eJic8CjH7td8QpYEV6Zo10gfRkjHCO3weqZHWDtAaSTFtl4+VMqOJ4N5jcuhZ9/l+yy8rVgw7BQeQ=="], + "@types/papaparse/@types/node": ["@types/node@24.2.1", "", { "dependencies": { "undici-types": "~7.10.0" } }, "sha512-DRh5K+ka5eJic8CjH7td8QpYEV6Zo10gfRkjHCO3weqZHWDtAaSTFtl4+VMqOJ4N5jcuhZ9/l+yy8rVgw7BQeQ=="], "@types/through/@types/node": ["@types/node@24.2.1", "", { "dependencies": { "undici-types": "~7.10.0" } }, "sha512-DRh5K+ka5eJic8CjH7td8QpYEV6Zo10gfRkjHCO3weqZHWDtAaSTFtl4+VMqOJ4N5jcuhZ9/l+yy8rVgw7BQeQ=="], @@ -3701,6 +3801,154 @@ "@aws-crypto/util/@smithy/util-utf8/@smithy/util-buffer-from": ["@smithy/util-buffer-from@2.2.0", "", { "dependencies": { "@smithy/is-array-buffer": "^2.2.0", "tslib": "^2.6.2" } }, "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA=="], + "@aws-sdk/client-sesv2/@aws-sdk/core/@aws-sdk/xml-builder": ["@aws-sdk/xml-builder@3.930.0", "", { "dependencies": { "@smithy/types": "^4.9.0", "fast-xml-parser": "5.2.5", "tslib": "^2.6.2" } }, "sha512-YIfkD17GocxdmlUVc3ia52QhcWuRIUJonbF8A2CYfcWNV3HzvAqpcPeC0bYUhkK+8e8YO1ARnLKZQE0TlwzorA=="], + + "@aws-sdk/client-sesv2/@aws-sdk/core/@smithy/property-provider": ["@smithy/property-provider@4.2.5", "", { "dependencies": { "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-8iLN1XSE1rl4MuxvQ+5OSk/Zb5El7NJZ1td6Tn+8dQQHIjp59Lwl6bd0+nzw6SKm2wSSriH2v/I9LPzUic7EOg=="], + + "@aws-sdk/client-sesv2/@aws-sdk/core/@smithy/signature-v4": ["@smithy/signature-v4@5.3.5", "", { "dependencies": { "@smithy/is-array-buffer": "^4.2.0", "@smithy/protocol-http": "^5.3.5", "@smithy/types": "^4.9.0", "@smithy/util-hex-encoding": "^4.2.0", "@smithy/util-middleware": "^4.2.5", "@smithy/util-uri-escape": "^4.2.0", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-xSUfMu1FT7ccfSXkoLl/QRQBi2rOvi3tiBZU2Tdy3I6cgvZ6SEi9QNey+lqps/sJRnogIS+lq+B1gxxbra2a/w=="], + + "@aws-sdk/client-sesv2/@aws-sdk/credential-provider-node/@aws-sdk/credential-provider-env": ["@aws-sdk/credential-provider-env@3.940.0", "", { "dependencies": { "@aws-sdk/core": "3.940.0", "@aws-sdk/types": "3.936.0", "@smithy/property-provider": "^4.2.5", "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-/G3l5/wbZYP2XEQiOoIkRJmlv15f1P3MSd1a0gz27lHEMrOJOGq66rF1Ca4OJLzapWt3Fy9BPrZAepoAX11kMw=="], + + "@aws-sdk/client-sesv2/@aws-sdk/credential-provider-node/@aws-sdk/credential-provider-http": ["@aws-sdk/credential-provider-http@3.940.0", "", { "dependencies": { "@aws-sdk/core": "3.940.0", "@aws-sdk/types": "3.936.0", "@smithy/fetch-http-handler": "^5.3.6", "@smithy/node-http-handler": "^4.4.5", "@smithy/property-provider": "^4.2.5", "@smithy/protocol-http": "^5.3.5", "@smithy/smithy-client": "^4.9.8", "@smithy/types": "^4.9.0", "@smithy/util-stream": "^4.5.6", "tslib": "^2.6.2" } }, "sha512-dOrc03DHElNBD6N9Okt4U0zhrG4Wix5QUBSZPr5VN8SvmjD9dkrrxOkkJaMCl/bzrW7kbQEp7LuBdbxArMmOZQ=="], + + "@aws-sdk/client-sesv2/@aws-sdk/credential-provider-node/@aws-sdk/credential-provider-ini": ["@aws-sdk/credential-provider-ini@3.940.0", "", { "dependencies": { "@aws-sdk/core": "3.940.0", "@aws-sdk/credential-provider-env": "3.940.0", "@aws-sdk/credential-provider-http": "3.940.0", "@aws-sdk/credential-provider-login": "3.940.0", "@aws-sdk/credential-provider-process": "3.940.0", "@aws-sdk/credential-provider-sso": "3.940.0", "@aws-sdk/credential-provider-web-identity": "3.940.0", "@aws-sdk/nested-clients": "3.940.0", "@aws-sdk/types": "3.936.0", "@smithy/credential-provider-imds": "^4.2.5", "@smithy/property-provider": "^4.2.5", "@smithy/shared-ini-file-loader": "^4.4.0", "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-gn7PJQEzb/cnInNFTOaDoCN/hOKqMejNmLof1W5VW95Qk0TPO52lH8R4RmJPnRrwFMswOWswTOpR1roKNLIrcw=="], + + "@aws-sdk/client-sesv2/@aws-sdk/credential-provider-node/@aws-sdk/credential-provider-process": ["@aws-sdk/credential-provider-process@3.940.0", "", { "dependencies": { "@aws-sdk/core": "3.940.0", "@aws-sdk/types": "3.936.0", "@smithy/property-provider": "^4.2.5", "@smithy/shared-ini-file-loader": "^4.4.0", "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-pILBzt5/TYCqRsJb7vZlxmRIe0/T+FZPeml417EK75060ajDGnVJjHcuVdLVIeKoTKm9gmJc9l45gon6PbHyUQ=="], + + "@aws-sdk/client-sesv2/@aws-sdk/credential-provider-node/@aws-sdk/credential-provider-sso": ["@aws-sdk/credential-provider-sso@3.940.0", "", { "dependencies": { "@aws-sdk/client-sso": "3.940.0", "@aws-sdk/core": "3.940.0", "@aws-sdk/token-providers": "3.940.0", "@aws-sdk/types": "3.936.0", "@smithy/property-provider": "^4.2.5", "@smithy/shared-ini-file-loader": "^4.4.0", "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-q6JMHIkBlDCOMnA3RAzf8cGfup+8ukhhb50fNpghMs1SNBGhanmaMbZSgLigBRsPQW7fOk2l8jnzdVLS+BB9Uw=="], + + "@aws-sdk/client-sesv2/@aws-sdk/credential-provider-node/@aws-sdk/credential-provider-web-identity": ["@aws-sdk/credential-provider-web-identity@3.940.0", "", { "dependencies": { "@aws-sdk/core": "3.940.0", "@aws-sdk/nested-clients": "3.940.0", "@aws-sdk/types": "3.936.0", "@smithy/property-provider": "^4.2.5", "@smithy/shared-ini-file-loader": "^4.4.0", "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-9QLTIkDJHHaYL0nyymO41H8g3ui1yz6Y3GmAN1gYQa6plXisuFBnGAbmKVj7zNvjWaOKdF0dV3dd3AFKEDoJ/w=="], + + "@aws-sdk/client-sesv2/@aws-sdk/credential-provider-node/@smithy/credential-provider-imds": ["@smithy/credential-provider-imds@4.2.5", "", { "dependencies": { "@smithy/node-config-provider": "^4.3.5", "@smithy/property-provider": "^4.2.5", "@smithy/types": "^4.9.0", "@smithy/url-parser": "^4.2.5", "tslib": "^2.6.2" } }, "sha512-BZwotjoZWn9+36nimwm/OLIcVe+KYRwzMjfhd4QT7QxPm9WY0HiOV8t/Wlh+HVUif0SBVV7ksq8//hPaBC/okQ=="], + + "@aws-sdk/client-sesv2/@aws-sdk/credential-provider-node/@smithy/property-provider": ["@smithy/property-provider@4.2.5", "", { "dependencies": { "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-8iLN1XSE1rl4MuxvQ+5OSk/Zb5El7NJZ1td6Tn+8dQQHIjp59Lwl6bd0+nzw6SKm2wSSriH2v/I9LPzUic7EOg=="], + + "@aws-sdk/client-sesv2/@aws-sdk/credential-provider-node/@smithy/shared-ini-file-loader": ["@smithy/shared-ini-file-loader@4.4.0", "", { "dependencies": { "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-5WmZ5+kJgJDjwXXIzr1vDTG+RhF9wzSODQBfkrQ2VVkYALKGvZX1lgVSxEkgicSAFnFhPj5rudJV0zoinqS0bA=="], + + "@aws-sdk/client-sesv2/@aws-sdk/middleware-recursion-detection/@aws/lambda-invoke-store": ["@aws/lambda-invoke-store@0.2.1", "", {}, "sha512-sIyFcoPZkTtNu9xFeEoynMef3bPJIAbOfUh+ueYcfhVl6xm2VRtMcMclSxmZCMnHHd4hlYKJeq/aggmBEWynww=="], + + "@aws-sdk/client-sesv2/@aws-sdk/signature-v4-multi-region/@aws-sdk/middleware-sdk-s3": ["@aws-sdk/middleware-sdk-s3@3.940.0", "", { "dependencies": { "@aws-sdk/core": "3.940.0", "@aws-sdk/types": "3.936.0", "@aws-sdk/util-arn-parser": "3.893.0", "@smithy/core": "^3.18.5", "@smithy/node-config-provider": "^4.3.5", "@smithy/protocol-http": "^5.3.5", "@smithy/signature-v4": "^5.3.5", "@smithy/smithy-client": "^4.9.8", "@smithy/types": "^4.9.0", "@smithy/util-config-provider": "^4.2.0", "@smithy/util-middleware": "^4.2.5", "@smithy/util-stream": "^4.5.6", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-JYkLjgS1wLoKHJ40G63+afM1ehmsPsjcmrHirKh8+kSCx4ip7+nL1e/twV4Zicxr8RJi9Y0Ahq5mDvneilDDKQ=="], + + "@aws-sdk/client-sesv2/@aws-sdk/signature-v4-multi-region/@smithy/signature-v4": ["@smithy/signature-v4@5.3.5", "", { "dependencies": { "@smithy/is-array-buffer": "^4.2.0", "@smithy/protocol-http": "^5.3.5", "@smithy/types": "^4.9.0", "@smithy/util-hex-encoding": "^4.2.0", "@smithy/util-middleware": "^4.2.5", "@smithy/util-uri-escape": "^4.2.0", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-xSUfMu1FT7ccfSXkoLl/QRQBi2rOvi3tiBZU2Tdy3I6cgvZ6SEi9QNey+lqps/sJRnogIS+lq+B1gxxbra2a/w=="], + + "@aws-sdk/client-sesv2/@smithy/config-resolver/@smithy/util-config-provider": ["@smithy/util-config-provider@4.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-YEjpl6XJ36FTKmD+kRJJWYvrHeUvm5ykaUS5xK+6oXffQPHeEM4/nXlZPe+Wu0lsgRUcNZiliYNh/y7q9c2y6Q=="], + + "@aws-sdk/client-sesv2/@smithy/core/@smithy/util-stream": ["@smithy/util-stream@4.5.6", "", { "dependencies": { "@smithy/fetch-http-handler": "^5.3.6", "@smithy/node-http-handler": "^4.4.5", "@smithy/types": "^4.9.0", "@smithy/util-base64": "^4.3.0", "@smithy/util-buffer-from": "^4.2.0", "@smithy/util-hex-encoding": "^4.2.0", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-qWw/UM59TiaFrPevefOZ8CNBKbYEP6wBAIlLqxn3VAIo9rgnTNc4ASbVrqDmhuwI87usnjhdQrxodzAGFFzbRQ=="], + + "@aws-sdk/client-sesv2/@smithy/core/@smithy/uuid": ["@smithy/uuid@1.1.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-4aUIteuyxtBUhVdiQqcDhKFitwfd9hqoSDYY2KRXiWtgoWJ9Bmise+KfEPDiVHWeJepvF8xJO9/9+WDIciMFFw=="], + + "@aws-sdk/client-sesv2/@smithy/fetch-http-handler/@smithy/querystring-builder": ["@smithy/querystring-builder@4.2.5", "", { "dependencies": { "@smithy/types": "^4.9.0", "@smithy/util-uri-escape": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-y98otMI1saoajeik2kLfGyRp11e5U/iJYH/wLCh3aTV/XutbGT9nziKGkgCaMD1ghK7p6htHMm6b6scl9JRUWg=="], + + "@aws-sdk/client-sesv2/@smithy/hash-node/@smithy/util-buffer-from": ["@smithy/util-buffer-from@4.2.0", "", { "dependencies": { "@smithy/is-array-buffer": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-kAY9hTKulTNevM2nlRtxAG2FQ3B2OR6QIrPY3zE5LqJy1oxzmgBGsHLWTcNhWXKchgA0WHW+mZkQrng/pgcCew=="], + + "@aws-sdk/client-sesv2/@smithy/middleware-endpoint/@smithy/shared-ini-file-loader": ["@smithy/shared-ini-file-loader@4.4.0", "", { "dependencies": { "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-5WmZ5+kJgJDjwXXIzr1vDTG+RhF9wzSODQBfkrQ2VVkYALKGvZX1lgVSxEkgicSAFnFhPj5rudJV0zoinqS0bA=="], + + "@aws-sdk/client-sesv2/@smithy/middleware-retry/@smithy/service-error-classification": ["@smithy/service-error-classification@4.2.5", "", { "dependencies": { "@smithy/types": "^4.9.0" } }, "sha512-8fEvK+WPE3wUAcDvqDQG1Vk3ANLR8Px979te96m84CbKAjBVf25rPYSzb4xU4hlTyho7VhOGnh5i62D/JVF0JQ=="], + + "@aws-sdk/client-sesv2/@smithy/middleware-retry/@smithy/uuid": ["@smithy/uuid@1.1.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-4aUIteuyxtBUhVdiQqcDhKFitwfd9hqoSDYY2KRXiWtgoWJ9Bmise+KfEPDiVHWeJepvF8xJO9/9+WDIciMFFw=="], + + "@aws-sdk/client-sesv2/@smithy/node-config-provider/@smithy/property-provider": ["@smithy/property-provider@4.2.5", "", { "dependencies": { "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-8iLN1XSE1rl4MuxvQ+5OSk/Zb5El7NJZ1td6Tn+8dQQHIjp59Lwl6bd0+nzw6SKm2wSSriH2v/I9LPzUic7EOg=="], + + "@aws-sdk/client-sesv2/@smithy/node-config-provider/@smithy/shared-ini-file-loader": ["@smithy/shared-ini-file-loader@4.4.0", "", { "dependencies": { "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-5WmZ5+kJgJDjwXXIzr1vDTG+RhF9wzSODQBfkrQ2VVkYALKGvZX1lgVSxEkgicSAFnFhPj5rudJV0zoinqS0bA=="], + + "@aws-sdk/client-sesv2/@smithy/node-http-handler/@smithy/abort-controller": ["@smithy/abort-controller@4.2.5", "", { "dependencies": { "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-j7HwVkBw68YW8UmFRcjZOmssE77Rvk0GWAIN1oFBhsaovQmZWYCIcGa9/pwRB0ExI8Sk9MWNALTjftjHZea7VA=="], + + "@aws-sdk/client-sesv2/@smithy/node-http-handler/@smithy/querystring-builder": ["@smithy/querystring-builder@4.2.5", "", { "dependencies": { "@smithy/types": "^4.9.0", "@smithy/util-uri-escape": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-y98otMI1saoajeik2kLfGyRp11e5U/iJYH/wLCh3aTV/XutbGT9nziKGkgCaMD1ghK7p6htHMm6b6scl9JRUWg=="], + + "@aws-sdk/client-sesv2/@smithy/smithy-client/@smithy/util-stream": ["@smithy/util-stream@4.5.6", "", { "dependencies": { "@smithy/fetch-http-handler": "^5.3.6", "@smithy/node-http-handler": "^4.4.5", "@smithy/types": "^4.9.0", "@smithy/util-base64": "^4.3.0", "@smithy/util-buffer-from": "^4.2.0", "@smithy/util-hex-encoding": "^4.2.0", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-qWw/UM59TiaFrPevefOZ8CNBKbYEP6wBAIlLqxn3VAIo9rgnTNc4ASbVrqDmhuwI87usnjhdQrxodzAGFFzbRQ=="], + + "@aws-sdk/client-sesv2/@smithy/url-parser/@smithy/querystring-parser": ["@smithy/querystring-parser@4.2.5", "", { "dependencies": { "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-031WCTdPYgiQRYNPXznHXof2YM0GwL6SeaSyTH/P72M1Vz73TvCNH2Nq8Iu2IEPq9QP2yx0/nrw5YmSeAi/AjQ=="], + + "@aws-sdk/client-sesv2/@smithy/util-base64/@smithy/util-buffer-from": ["@smithy/util-buffer-from@4.2.0", "", { "dependencies": { "@smithy/is-array-buffer": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-kAY9hTKulTNevM2nlRtxAG2FQ3B2OR6QIrPY3zE5LqJy1oxzmgBGsHLWTcNhWXKchgA0WHW+mZkQrng/pgcCew=="], + + "@aws-sdk/client-sesv2/@smithy/util-defaults-mode-browser/@smithy/property-provider": ["@smithy/property-provider@4.2.5", "", { "dependencies": { "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-8iLN1XSE1rl4MuxvQ+5OSk/Zb5El7NJZ1td6Tn+8dQQHIjp59Lwl6bd0+nzw6SKm2wSSriH2v/I9LPzUic7EOg=="], + + "@aws-sdk/client-sesv2/@smithy/util-defaults-mode-node/@smithy/credential-provider-imds": ["@smithy/credential-provider-imds@4.2.5", "", { "dependencies": { "@smithy/node-config-provider": "^4.3.5", "@smithy/property-provider": "^4.2.5", "@smithy/types": "^4.9.0", "@smithy/url-parser": "^4.2.5", "tslib": "^2.6.2" } }, "sha512-BZwotjoZWn9+36nimwm/OLIcVe+KYRwzMjfhd4QT7QxPm9WY0HiOV8t/Wlh+HVUif0SBVV7ksq8//hPaBC/okQ=="], + + "@aws-sdk/client-sesv2/@smithy/util-defaults-mode-node/@smithy/property-provider": ["@smithy/property-provider@4.2.5", "", { "dependencies": { "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-8iLN1XSE1rl4MuxvQ+5OSk/Zb5El7NJZ1td6Tn+8dQQHIjp59Lwl6bd0+nzw6SKm2wSSriH2v/I9LPzUic7EOg=="], + + "@aws-sdk/client-sesv2/@smithy/util-retry/@smithy/service-error-classification": ["@smithy/service-error-classification@4.2.5", "", { "dependencies": { "@smithy/types": "^4.9.0" } }, "sha512-8fEvK+WPE3wUAcDvqDQG1Vk3ANLR8Px979te96m84CbKAjBVf25rPYSzb4xU4hlTyho7VhOGnh5i62D/JVF0JQ=="], + + "@aws-sdk/client-sesv2/@smithy/util-utf8/@smithy/util-buffer-from": ["@smithy/util-buffer-from@4.2.0", "", { "dependencies": { "@smithy/is-array-buffer": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-kAY9hTKulTNevM2nlRtxAG2FQ3B2OR6QIrPY3zE5LqJy1oxzmgBGsHLWTcNhWXKchgA0WHW+mZkQrng/pgcCew=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/core/@aws-sdk/xml-builder": ["@aws-sdk/xml-builder@3.930.0", "", { "dependencies": { "@smithy/types": "^4.9.0", "fast-xml-parser": "5.2.5", "tslib": "^2.6.2" } }, "sha512-YIfkD17GocxdmlUVc3ia52QhcWuRIUJonbF8A2CYfcWNV3HzvAqpcPeC0bYUhkK+8e8YO1ARnLKZQE0TlwzorA=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/core/@smithy/core": ["@smithy/core@3.18.5", "", { "dependencies": { "@smithy/middleware-serde": "^4.2.6", "@smithy/protocol-http": "^5.3.5", "@smithy/types": "^4.9.0", "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", "@smithy/util-middleware": "^4.2.5", "@smithy/util-stream": "^4.5.6", "@smithy/util-utf8": "^4.2.0", "@smithy/uuid": "^1.1.0", "tslib": "^2.6.2" } }, "sha512-6gnIz3h+PEPQGDj8MnRSjDvKBah042jEoPgjFGJ4iJLBE78L4lY/n98x14XyPF4u3lN179Ub/ZKFY5za9GeLQw=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/core/@smithy/node-config-provider": ["@smithy/node-config-provider@4.3.5", "", { "dependencies": { "@smithy/property-provider": "^4.2.5", "@smithy/shared-ini-file-loader": "^4.4.0", "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-UTurh1C4qkVCtqggI36DGbLB2Kv8UlcFdMXDcWMbqVY2uRg0XmT9Pb4Vj6oSQ34eizO1fvR0RnFV4Axw4IrrAg=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/core/@smithy/signature-v4": ["@smithy/signature-v4@5.3.5", "", { "dependencies": { "@smithy/is-array-buffer": "^4.2.0", "@smithy/protocol-http": "^5.3.5", "@smithy/types": "^4.9.0", "@smithy/util-hex-encoding": "^4.2.0", "@smithy/util-middleware": "^4.2.5", "@smithy/util-uri-escape": "^4.2.0", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-xSUfMu1FT7ccfSXkoLl/QRQBi2rOvi3tiBZU2Tdy3I6cgvZ6SEi9QNey+lqps/sJRnogIS+lq+B1gxxbra2a/w=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/core/@smithy/smithy-client": ["@smithy/smithy-client@4.9.8", "", { "dependencies": { "@smithy/core": "^3.18.5", "@smithy/middleware-endpoint": "^4.3.12", "@smithy/middleware-stack": "^4.2.5", "@smithy/protocol-http": "^5.3.5", "@smithy/types": "^4.9.0", "@smithy/util-stream": "^4.5.6", "tslib": "^2.6.2" } }, "sha512-8xgq3LgKDEFoIrLWBho/oYKyWByw9/corz7vuh1upv7ZBm0ZMjGYBhbn6v643WoIqA9UTcx5A5htEp/YatUwMA=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/core/@smithy/util-base64": ["@smithy/util-base64@4.3.0", "", { "dependencies": { "@smithy/util-buffer-from": "^4.2.0", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-GkXZ59JfyxsIwNTWFnjmFEI8kZpRNIBfxKjv09+nkAWPt/4aGaEWMM04m4sxgNVWkbt2MdSvE3KF/PfX4nFedQ=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/core/@smithy/util-middleware": ["@smithy/util-middleware@4.2.5", "", { "dependencies": { "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-6Y3+rvBF7+PZOc40ybeZMcGln6xJGVeY60E7jy9Mv5iKpMJpHgRE6dKy9ScsVxvfAYuEX4Q9a65DQX90KaQ3bA=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/core/@smithy/util-utf8": ["@smithy/util-utf8@4.2.0", "", { "dependencies": { "@smithy/util-buffer-from": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-zBPfuzoI8xyBtR2P6WQj63Rz8i3AmfAaJLuNG8dWsfvPe8lO4aCPYLn879mEgHndZH1zQ2oXmG8O1GGzzaoZiw=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/nested-clients/@aws-sdk/middleware-host-header": ["@aws-sdk/middleware-host-header@3.936.0", "", { "dependencies": { "@aws-sdk/types": "3.936.0", "@smithy/protocol-http": "^5.3.5", "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-tAaObaAnsP1XnLGndfkGWFuzrJYuk9W0b/nLvol66t8FZExIAf/WdkT2NNAWOYxljVs++oHnyHBCxIlaHrzSiw=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/nested-clients/@aws-sdk/middleware-logger": ["@aws-sdk/middleware-logger@3.936.0", "", { "dependencies": { "@aws-sdk/types": "3.936.0", "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-aPSJ12d3a3Ea5nyEnLbijCaaYJT2QjQ9iW+zGh5QcZYXmOGWbKVyPSxmVOboZQG+c1M8t6d2O7tqrwzIq8L8qw=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/nested-clients/@aws-sdk/middleware-recursion-detection": ["@aws-sdk/middleware-recursion-detection@3.936.0", "", { "dependencies": { "@aws-sdk/types": "3.936.0", "@aws/lambda-invoke-store": "^0.2.0", "@smithy/protocol-http": "^5.3.5", "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-l4aGbHpXM45YNgXggIux1HgsCVAvvBoqHPkqLnqMl9QVapfuSTjJHfDYDsx1Xxct6/m7qSMUzanBALhiaGO2fA=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/nested-clients/@aws-sdk/middleware-user-agent": ["@aws-sdk/middleware-user-agent@3.940.0", "", { "dependencies": { "@aws-sdk/core": "3.940.0", "@aws-sdk/types": "3.936.0", "@aws-sdk/util-endpoints": "3.936.0", "@smithy/core": "^3.18.5", "@smithy/protocol-http": "^5.3.5", "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-nJbLrUj6fY+l2W2rIB9P4Qvpiy0tnTdg/dmixRxrU1z3e8wBdspJlyE+AZN4fuVbeL6rrRrO/zxQC1bB3cw5IA=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/nested-clients/@aws-sdk/region-config-resolver": ["@aws-sdk/region-config-resolver@3.936.0", "", { "dependencies": { "@aws-sdk/types": "3.936.0", "@smithy/config-resolver": "^4.4.3", "@smithy/node-config-provider": "^4.3.5", "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-wOKhzzWsshXGduxO4pqSiNyL9oUtk4BEvjWm9aaq6Hmfdoydq6v6t0rAGHWPjFwy9z2haovGRi3C8IxdMB4muw=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/nested-clients/@aws-sdk/util-endpoints": ["@aws-sdk/util-endpoints@3.936.0", "", { "dependencies": { "@aws-sdk/types": "3.936.0", "@smithy/types": "^4.9.0", "@smithy/url-parser": "^4.2.5", "@smithy/util-endpoints": "^3.2.5", "tslib": "^2.6.2" } }, "sha512-0Zx3Ntdpu+z9Wlm7JKUBOzS9EunwKAb4KdGUQQxDqh5Lc3ta5uBoub+FgmVuzwnmBu9U1Os8UuwVTH0Lgu+P5w=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/nested-clients/@aws-sdk/util-user-agent-browser": ["@aws-sdk/util-user-agent-browser@3.936.0", "", { "dependencies": { "@aws-sdk/types": "3.936.0", "@smithy/types": "^4.9.0", "bowser": "^2.11.0", "tslib": "^2.6.2" } }, "sha512-eZ/XF6NxMtu+iCma58GRNRxSq4lHo6zHQLOZRIeL/ghqYJirqHdenMOwrzPettj60KWlv827RVebP9oNVrwZbw=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/nested-clients/@aws-sdk/util-user-agent-node": ["@aws-sdk/util-user-agent-node@3.940.0", "", { "dependencies": { "@aws-sdk/middleware-user-agent": "3.940.0", "@aws-sdk/types": "3.936.0", "@smithy/node-config-provider": "^4.3.5", "@smithy/types": "^4.9.0", "tslib": "^2.6.2" }, "peerDependencies": { "aws-crt": ">=1.0.0" }, "optionalPeers": ["aws-crt"] }, "sha512-dlD/F+L/jN26I8Zg5x0oDGJiA+/WEQmnSE27fi5ydvYnpfQLwThtQo9SsNS47XSR/SOULaaoC9qx929rZuo74A=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/nested-clients/@smithy/config-resolver": ["@smithy/config-resolver@4.4.3", "", { "dependencies": { "@smithy/node-config-provider": "^4.3.5", "@smithy/types": "^4.9.0", "@smithy/util-config-provider": "^4.2.0", "@smithy/util-endpoints": "^3.2.5", "@smithy/util-middleware": "^4.2.5", "tslib": "^2.6.2" } }, "sha512-ezHLe1tKLUxDJo2LHtDuEDyWXolw8WGOR92qb4bQdWq/zKenO5BvctZGrVJBK08zjezSk7bmbKFOXIVyChvDLw=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/nested-clients/@smithy/core": ["@smithy/core@3.18.5", "", { "dependencies": { "@smithy/middleware-serde": "^4.2.6", "@smithy/protocol-http": "^5.3.5", "@smithy/types": "^4.9.0", "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", "@smithy/util-middleware": "^4.2.5", "@smithy/util-stream": "^4.5.6", "@smithy/util-utf8": "^4.2.0", "@smithy/uuid": "^1.1.0", "tslib": "^2.6.2" } }, "sha512-6gnIz3h+PEPQGDj8MnRSjDvKBah042jEoPgjFGJ4iJLBE78L4lY/n98x14XyPF4u3lN179Ub/ZKFY5za9GeLQw=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/nested-clients/@smithy/fetch-http-handler": ["@smithy/fetch-http-handler@5.3.6", "", { "dependencies": { "@smithy/protocol-http": "^5.3.5", "@smithy/querystring-builder": "^4.2.5", "@smithy/types": "^4.9.0", "@smithy/util-base64": "^4.3.0", "tslib": "^2.6.2" } }, "sha512-3+RG3EA6BBJ/ofZUeTFJA7mHfSYrZtQIrDP9dI8Lf7X6Jbos2jptuLrAAteDiFVrmbEmLSuRG/bUKzfAXk7dhg=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/nested-clients/@smithy/hash-node": ["@smithy/hash-node@4.2.5", "", { "dependencies": { "@smithy/types": "^4.9.0", "@smithy/util-buffer-from": "^4.2.0", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-DpYX914YOfA3UDT9CN1BM787PcHfWRBB43fFGCYrZFUH0Jv+5t8yYl+Pd5PW4+QzoGEDvn5d5QIO4j2HyYZQSA=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/nested-clients/@smithy/invalid-dependency": ["@smithy/invalid-dependency@4.2.5", "", { "dependencies": { "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-2L2erASEro1WC5nV+plwIMxrTXpvpfzl4e+Nre6vBVRR2HKeGGcvpJyyL3/PpiSg+cJG2KpTmZmq934Olb6e5A=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/nested-clients/@smithy/middleware-content-length": ["@smithy/middleware-content-length@4.2.5", "", { "dependencies": { "@smithy/protocol-http": "^5.3.5", "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-Y/RabVa5vbl5FuHYV2vUCwvh/dqzrEY/K2yWPSqvhFUwIY0atLqO4TienjBXakoy4zrKAMCZwg+YEqmH7jaN7A=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/nested-clients/@smithy/middleware-endpoint": ["@smithy/middleware-endpoint@4.3.12", "", { "dependencies": { "@smithy/core": "^3.18.5", "@smithy/middleware-serde": "^4.2.6", "@smithy/node-config-provider": "^4.3.5", "@smithy/shared-ini-file-loader": "^4.4.0", "@smithy/types": "^4.9.0", "@smithy/url-parser": "^4.2.5", "@smithy/util-middleware": "^4.2.5", "tslib": "^2.6.2" } }, "sha512-9pAX/H+VQPzNbouhDhkW723igBMLgrI8OtX+++M7iKJgg/zY/Ig3i1e6seCcx22FWhE6Q/S61BRdi2wXBORT+A=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/nested-clients/@smithy/middleware-retry": ["@smithy/middleware-retry@4.4.12", "", { "dependencies": { "@smithy/node-config-provider": "^4.3.5", "@smithy/protocol-http": "^5.3.5", "@smithy/service-error-classification": "^4.2.5", "@smithy/smithy-client": "^4.9.8", "@smithy/types": "^4.9.0", "@smithy/util-middleware": "^4.2.5", "@smithy/util-retry": "^4.2.5", "@smithy/uuid": "^1.1.0", "tslib": "^2.6.2" } }, "sha512-S4kWNKFowYd0lID7/DBqWHOQxmxlsf0jBaos9chQZUWTVOjSW1Ogyh8/ib5tM+agFDJ/TCxuCTvrnlc+9cIBcQ=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/nested-clients/@smithy/middleware-serde": ["@smithy/middleware-serde@4.2.6", "", { "dependencies": { "@smithy/protocol-http": "^5.3.5", "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-VkLoE/z7e2g8pirwisLz8XJWedUSY8my/qrp81VmAdyrhi94T+riBfwP+AOEEFR9rFTSonC/5D2eWNmFabHyGQ=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/nested-clients/@smithy/middleware-stack": ["@smithy/middleware-stack@4.2.5", "", { "dependencies": { "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-bYrutc+neOyWxtZdbB2USbQttZN0mXaOyYLIsaTbJhFsfpXyGWUxJpEuO1rJ8IIJm2qH4+xJT0mxUSsEDTYwdQ=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/nested-clients/@smithy/node-config-provider": ["@smithy/node-config-provider@4.3.5", "", { "dependencies": { "@smithy/property-provider": "^4.2.5", "@smithy/shared-ini-file-loader": "^4.4.0", "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-UTurh1C4qkVCtqggI36DGbLB2Kv8UlcFdMXDcWMbqVY2uRg0XmT9Pb4Vj6oSQ34eizO1fvR0RnFV4Axw4IrrAg=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/nested-clients/@smithy/node-http-handler": ["@smithy/node-http-handler@4.4.5", "", { "dependencies": { "@smithy/abort-controller": "^4.2.5", "@smithy/protocol-http": "^5.3.5", "@smithy/querystring-builder": "^4.2.5", "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-CMnzM9R2WqlqXQGtIlsHMEZfXKJVTIrqCNoSd/QpAyp+Dw0a1Vps13l6ma1fH8g7zSPNsA59B/kWgeylFuA/lw=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/nested-clients/@smithy/smithy-client": ["@smithy/smithy-client@4.9.8", "", { "dependencies": { "@smithy/core": "^3.18.5", "@smithy/middleware-endpoint": "^4.3.12", "@smithy/middleware-stack": "^4.2.5", "@smithy/protocol-http": "^5.3.5", "@smithy/types": "^4.9.0", "@smithy/util-stream": "^4.5.6", "tslib": "^2.6.2" } }, "sha512-8xgq3LgKDEFoIrLWBho/oYKyWByw9/corz7vuh1upv7ZBm0ZMjGYBhbn6v643WoIqA9UTcx5A5htEp/YatUwMA=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/nested-clients/@smithy/url-parser": ["@smithy/url-parser@4.2.5", "", { "dependencies": { "@smithy/querystring-parser": "^4.2.5", "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-VaxMGsilqFnK1CeBX+LXnSuaMx4sTL/6znSZh2829txWieazdVxr54HmiyTsIbpOTLcf5nYpq9lpzmwRdxj6rQ=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/nested-clients/@smithy/util-base64": ["@smithy/util-base64@4.3.0", "", { "dependencies": { "@smithy/util-buffer-from": "^4.2.0", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-GkXZ59JfyxsIwNTWFnjmFEI8kZpRNIBfxKjv09+nkAWPt/4aGaEWMM04m4sxgNVWkbt2MdSvE3KF/PfX4nFedQ=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/nested-clients/@smithy/util-body-length-browser": ["@smithy/util-body-length-browser@4.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-Fkoh/I76szMKJnBXWPdFkQJl2r9SjPt3cMzLdOB6eJ4Pnpas8hVoWPYemX/peO0yrrvldgCUVJqOAjUrOLjbxg=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/nested-clients/@smithy/util-body-length-node": ["@smithy/util-body-length-node@4.2.1", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-h53dz/pISVrVrfxV1iqXlx5pRg3V2YWFcSQyPyXZRrZoZj4R4DeWRDo1a7dd3CPTcFi3kE+98tuNyD2axyZReA=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/nested-clients/@smithy/util-defaults-mode-browser": ["@smithy/util-defaults-mode-browser@4.3.11", "", { "dependencies": { "@smithy/property-provider": "^4.2.5", "@smithy/smithy-client": "^4.9.8", "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-yHv+r6wSQXEXTPVCIQTNmXVWs7ekBTpMVErjqZoWkYN75HIFN5y9+/+sYOejfAuvxWGvgzgxbTHa/oz61YTbKw=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/nested-clients/@smithy/util-defaults-mode-node": ["@smithy/util-defaults-mode-node@4.2.14", "", { "dependencies": { "@smithy/config-resolver": "^4.4.3", "@smithy/credential-provider-imds": "^4.2.5", "@smithy/node-config-provider": "^4.3.5", "@smithy/property-provider": "^4.2.5", "@smithy/smithy-client": "^4.9.8", "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-ljZN3iRvaJUgulfvobIuG97q1iUuCMrvXAlkZ4msY+ZuVHQHDIqn7FKZCEj+bx8omz6kF5yQXms/xhzjIO5XiA=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/nested-clients/@smithy/util-endpoints": ["@smithy/util-endpoints@3.2.5", "", { "dependencies": { "@smithy/node-config-provider": "^4.3.5", "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-3O63AAWu2cSNQZp+ayl9I3NapW1p1rR5mlVHcF6hAB1dPZUQFfRPYtplWX/3xrzWthPGj5FqB12taJJCfH6s8A=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/nested-clients/@smithy/util-middleware": ["@smithy/util-middleware@4.2.5", "", { "dependencies": { "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-6Y3+rvBF7+PZOc40ybeZMcGln6xJGVeY60E7jy9Mv5iKpMJpHgRE6dKy9ScsVxvfAYuEX4Q9a65DQX90KaQ3bA=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/nested-clients/@smithy/util-retry": ["@smithy/util-retry@4.2.5", "", { "dependencies": { "@smithy/service-error-classification": "^4.2.5", "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-GBj3+EZBbN4NAqJ/7pAhsXdfzdlznOh8PydUijy6FpNIMnHPSMO2/rP4HKu+UFeikJxShERk528oy7GT79YiJg=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/nested-clients/@smithy/util-utf8": ["@smithy/util-utf8@4.2.0", "", { "dependencies": { "@smithy/util-buffer-from": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-zBPfuzoI8xyBtR2P6WQj63Rz8i3AmfAaJLuNG8dWsfvPe8lO4aCPYLn879mEgHndZH1zQ2oXmG8O1GGzzaoZiw=="], + "@babel/helper-compilation-targets/lru-cache/yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="], "@browserbasehq/sdk/@types/node/undici-types": ["undici-types@5.26.5", "", {}, "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="], @@ -3799,6 +4047,8 @@ "@types/node-fetch/@types/node/undici-types": ["undici-types@7.10.0", "", {}, "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag=="], + "@types/nodemailer/@types/node/undici-types": ["undici-types@7.10.0", "", {}, "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag=="], + "@types/papaparse/@types/node/undici-types": ["undici-types@7.10.0", "", {}, "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag=="], "@types/through/@types/node/undici-types": ["undici-types@7.10.0", "", {}, "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag=="], @@ -3941,6 +4191,106 @@ "@aws-crypto/util/@smithy/util-utf8/@smithy/util-buffer-from/@smithy/is-array-buffer": ["@smithy/is-array-buffer@2.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA=="], + "@aws-sdk/client-sesv2/@aws-sdk/core/@smithy/signature-v4/@smithy/is-array-buffer": ["@smithy/is-array-buffer@4.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-DZZZBvC7sjcYh4MazJSGiWMI2L7E0oCiRHREDzIxi/M2LY79/21iXt6aPLHge82wi5LsuRF5A06Ds3+0mlh6CQ=="], + + "@aws-sdk/client-sesv2/@aws-sdk/core/@smithy/signature-v4/@smithy/util-hex-encoding": ["@smithy/util-hex-encoding@4.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-CCQBwJIvXMLKxVbO88IukazJD9a4kQ9ZN7/UMGBjBcJYvatpWk+9g870El4cB8/EJxfe+k+y0GmR9CAzkF+Nbw=="], + + "@aws-sdk/client-sesv2/@aws-sdk/core/@smithy/signature-v4/@smithy/util-uri-escape": ["@smithy/util-uri-escape@4.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-igZpCKV9+E/Mzrpq6YacdTQ0qTiLm85gD6N/IrmyDvQFA4UnU3d5g3m8tMT/6zG/vVkWSU+VxeUyGonL62DuxA=="], + + "@aws-sdk/client-sesv2/@aws-sdk/credential-provider-node/@aws-sdk/credential-provider-http/@smithy/util-stream": ["@smithy/util-stream@4.5.6", "", { "dependencies": { "@smithy/fetch-http-handler": "^5.3.6", "@smithy/node-http-handler": "^4.4.5", "@smithy/types": "^4.9.0", "@smithy/util-base64": "^4.3.0", "@smithy/util-buffer-from": "^4.2.0", "@smithy/util-hex-encoding": "^4.2.0", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-qWw/UM59TiaFrPevefOZ8CNBKbYEP6wBAIlLqxn3VAIo9rgnTNc4ASbVrqDmhuwI87usnjhdQrxodzAGFFzbRQ=="], + + "@aws-sdk/client-sesv2/@aws-sdk/credential-provider-node/@aws-sdk/credential-provider-ini/@aws-sdk/nested-clients": ["@aws-sdk/nested-clients@3.940.0", "", { "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "3.940.0", "@aws-sdk/middleware-host-header": "3.936.0", "@aws-sdk/middleware-logger": "3.936.0", "@aws-sdk/middleware-recursion-detection": "3.936.0", "@aws-sdk/middleware-user-agent": "3.940.0", "@aws-sdk/region-config-resolver": "3.936.0", "@aws-sdk/types": "3.936.0", "@aws-sdk/util-endpoints": "3.936.0", "@aws-sdk/util-user-agent-browser": "3.936.0", "@aws-sdk/util-user-agent-node": "3.940.0", "@smithy/config-resolver": "^4.4.3", "@smithy/core": "^3.18.5", "@smithy/fetch-http-handler": "^5.3.6", "@smithy/hash-node": "^4.2.5", "@smithy/invalid-dependency": "^4.2.5", "@smithy/middleware-content-length": "^4.2.5", "@smithy/middleware-endpoint": "^4.3.12", "@smithy/middleware-retry": "^4.4.12", "@smithy/middleware-serde": "^4.2.6", "@smithy/middleware-stack": "^4.2.5", "@smithy/node-config-provider": "^4.3.5", "@smithy/node-http-handler": "^4.4.5", "@smithy/protocol-http": "^5.3.5", "@smithy/smithy-client": "^4.9.8", "@smithy/types": "^4.9.0", "@smithy/url-parser": "^4.2.5", "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", "@smithy/util-body-length-node": "^4.2.1", "@smithy/util-defaults-mode-browser": "^4.3.11", "@smithy/util-defaults-mode-node": "^4.2.14", "@smithy/util-endpoints": "^3.2.5", "@smithy/util-middleware": "^4.2.5", "@smithy/util-retry": "^4.2.5", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-x0mdv6DkjXqXEcQj3URbCltEzW6hoy/1uIL+i8gExP6YKrnhiZ7SzuB4gPls2UOpK5UqLiqXjhRLfBb1C9i4Dw=="], + + "@aws-sdk/client-sesv2/@aws-sdk/credential-provider-node/@aws-sdk/credential-provider-sso/@aws-sdk/client-sso": ["@aws-sdk/client-sso@3.940.0", "", { "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "3.940.0", "@aws-sdk/middleware-host-header": "3.936.0", "@aws-sdk/middleware-logger": "3.936.0", "@aws-sdk/middleware-recursion-detection": "3.936.0", "@aws-sdk/middleware-user-agent": "3.940.0", "@aws-sdk/region-config-resolver": "3.936.0", "@aws-sdk/types": "3.936.0", "@aws-sdk/util-endpoints": "3.936.0", "@aws-sdk/util-user-agent-browser": "3.936.0", "@aws-sdk/util-user-agent-node": "3.940.0", "@smithy/config-resolver": "^4.4.3", "@smithy/core": "^3.18.5", "@smithy/fetch-http-handler": "^5.3.6", "@smithy/hash-node": "^4.2.5", "@smithy/invalid-dependency": "^4.2.5", "@smithy/middleware-content-length": "^4.2.5", "@smithy/middleware-endpoint": "^4.3.12", "@smithy/middleware-retry": "^4.4.12", "@smithy/middleware-serde": "^4.2.6", "@smithy/middleware-stack": "^4.2.5", "@smithy/node-config-provider": "^4.3.5", "@smithy/node-http-handler": "^4.4.5", "@smithy/protocol-http": "^5.3.5", "@smithy/smithy-client": "^4.9.8", "@smithy/types": "^4.9.0", "@smithy/url-parser": "^4.2.5", "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", "@smithy/util-body-length-node": "^4.2.1", "@smithy/util-defaults-mode-browser": "^4.3.11", "@smithy/util-defaults-mode-node": "^4.2.14", "@smithy/util-endpoints": "^3.2.5", "@smithy/util-middleware": "^4.2.5", "@smithy/util-retry": "^4.2.5", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-SdqJGWVhmIURvCSgkDditHRO+ozubwZk9aCX9MK8qxyOndhobCndW1ozl3hX9psvMAo9Q4bppjuqy/GHWpjB+A=="], + + "@aws-sdk/client-sesv2/@aws-sdk/credential-provider-node/@aws-sdk/credential-provider-sso/@aws-sdk/token-providers": ["@aws-sdk/token-providers@3.940.0", "", { "dependencies": { "@aws-sdk/core": "3.940.0", "@aws-sdk/nested-clients": "3.940.0", "@aws-sdk/types": "3.936.0", "@smithy/property-provider": "^4.2.5", "@smithy/shared-ini-file-loader": "^4.4.0", "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-k5qbRe/ZFjW9oWEdzLIa2twRVIEx7p/9rutofyrRysrtEnYh3HAWCngAnwbgKMoiwa806UzcTRx0TjyEpnKcCg=="], + + "@aws-sdk/client-sesv2/@aws-sdk/credential-provider-node/@aws-sdk/credential-provider-web-identity/@aws-sdk/nested-clients": ["@aws-sdk/nested-clients@3.940.0", "", { "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "3.940.0", "@aws-sdk/middleware-host-header": "3.936.0", "@aws-sdk/middleware-logger": "3.936.0", "@aws-sdk/middleware-recursion-detection": "3.936.0", "@aws-sdk/middleware-user-agent": "3.940.0", "@aws-sdk/region-config-resolver": "3.936.0", "@aws-sdk/types": "3.936.0", "@aws-sdk/util-endpoints": "3.936.0", "@aws-sdk/util-user-agent-browser": "3.936.0", "@aws-sdk/util-user-agent-node": "3.940.0", "@smithy/config-resolver": "^4.4.3", "@smithy/core": "^3.18.5", "@smithy/fetch-http-handler": "^5.3.6", "@smithy/hash-node": "^4.2.5", "@smithy/invalid-dependency": "^4.2.5", "@smithy/middleware-content-length": "^4.2.5", "@smithy/middleware-endpoint": "^4.3.12", "@smithy/middleware-retry": "^4.4.12", "@smithy/middleware-serde": "^4.2.6", "@smithy/middleware-stack": "^4.2.5", "@smithy/node-config-provider": "^4.3.5", "@smithy/node-http-handler": "^4.4.5", "@smithy/protocol-http": "^5.3.5", "@smithy/smithy-client": "^4.9.8", "@smithy/types": "^4.9.0", "@smithy/url-parser": "^4.2.5", "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", "@smithy/util-body-length-node": "^4.2.1", "@smithy/util-defaults-mode-browser": "^4.3.11", "@smithy/util-defaults-mode-node": "^4.2.14", "@smithy/util-endpoints": "^3.2.5", "@smithy/util-middleware": "^4.2.5", "@smithy/util-retry": "^4.2.5", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-x0mdv6DkjXqXEcQj3URbCltEzW6hoy/1uIL+i8gExP6YKrnhiZ7SzuB4gPls2UOpK5UqLiqXjhRLfBb1C9i4Dw=="], + + "@aws-sdk/client-sesv2/@aws-sdk/signature-v4-multi-region/@aws-sdk/middleware-sdk-s3/@smithy/util-config-provider": ["@smithy/util-config-provider@4.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-YEjpl6XJ36FTKmD+kRJJWYvrHeUvm5ykaUS5xK+6oXffQPHeEM4/nXlZPe+Wu0lsgRUcNZiliYNh/y7q9c2y6Q=="], + + "@aws-sdk/client-sesv2/@aws-sdk/signature-v4-multi-region/@aws-sdk/middleware-sdk-s3/@smithy/util-stream": ["@smithy/util-stream@4.5.6", "", { "dependencies": { "@smithy/fetch-http-handler": "^5.3.6", "@smithy/node-http-handler": "^4.4.5", "@smithy/types": "^4.9.0", "@smithy/util-base64": "^4.3.0", "@smithy/util-buffer-from": "^4.2.0", "@smithy/util-hex-encoding": "^4.2.0", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-qWw/UM59TiaFrPevefOZ8CNBKbYEP6wBAIlLqxn3VAIo9rgnTNc4ASbVrqDmhuwI87usnjhdQrxodzAGFFzbRQ=="], + + "@aws-sdk/client-sesv2/@aws-sdk/signature-v4-multi-region/@smithy/signature-v4/@smithy/is-array-buffer": ["@smithy/is-array-buffer@4.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-DZZZBvC7sjcYh4MazJSGiWMI2L7E0oCiRHREDzIxi/M2LY79/21iXt6aPLHge82wi5LsuRF5A06Ds3+0mlh6CQ=="], + + "@aws-sdk/client-sesv2/@aws-sdk/signature-v4-multi-region/@smithy/signature-v4/@smithy/util-hex-encoding": ["@smithy/util-hex-encoding@4.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-CCQBwJIvXMLKxVbO88IukazJD9a4kQ9ZN7/UMGBjBcJYvatpWk+9g870El4cB8/EJxfe+k+y0GmR9CAzkF+Nbw=="], + + "@aws-sdk/client-sesv2/@aws-sdk/signature-v4-multi-region/@smithy/signature-v4/@smithy/util-uri-escape": ["@smithy/util-uri-escape@4.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-igZpCKV9+E/Mzrpq6YacdTQ0qTiLm85gD6N/IrmyDvQFA4UnU3d5g3m8tMT/6zG/vVkWSU+VxeUyGonL62DuxA=="], + + "@aws-sdk/client-sesv2/@smithy/core/@smithy/util-stream/@smithy/util-buffer-from": ["@smithy/util-buffer-from@4.2.0", "", { "dependencies": { "@smithy/is-array-buffer": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-kAY9hTKulTNevM2nlRtxAG2FQ3B2OR6QIrPY3zE5LqJy1oxzmgBGsHLWTcNhWXKchgA0WHW+mZkQrng/pgcCew=="], + + "@aws-sdk/client-sesv2/@smithy/core/@smithy/util-stream/@smithy/util-hex-encoding": ["@smithy/util-hex-encoding@4.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-CCQBwJIvXMLKxVbO88IukazJD9a4kQ9ZN7/UMGBjBcJYvatpWk+9g870El4cB8/EJxfe+k+y0GmR9CAzkF+Nbw=="], + + "@aws-sdk/client-sesv2/@smithy/fetch-http-handler/@smithy/querystring-builder/@smithy/util-uri-escape": ["@smithy/util-uri-escape@4.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-igZpCKV9+E/Mzrpq6YacdTQ0qTiLm85gD6N/IrmyDvQFA4UnU3d5g3m8tMT/6zG/vVkWSU+VxeUyGonL62DuxA=="], + + "@aws-sdk/client-sesv2/@smithy/hash-node/@smithy/util-buffer-from/@smithy/is-array-buffer": ["@smithy/is-array-buffer@4.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-DZZZBvC7sjcYh4MazJSGiWMI2L7E0oCiRHREDzIxi/M2LY79/21iXt6aPLHge82wi5LsuRF5A06Ds3+0mlh6CQ=="], + + "@aws-sdk/client-sesv2/@smithy/node-http-handler/@smithy/querystring-builder/@smithy/util-uri-escape": ["@smithy/util-uri-escape@4.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-igZpCKV9+E/Mzrpq6YacdTQ0qTiLm85gD6N/IrmyDvQFA4UnU3d5g3m8tMT/6zG/vVkWSU+VxeUyGonL62DuxA=="], + + "@aws-sdk/client-sesv2/@smithy/smithy-client/@smithy/util-stream/@smithy/util-buffer-from": ["@smithy/util-buffer-from@4.2.0", "", { "dependencies": { "@smithy/is-array-buffer": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-kAY9hTKulTNevM2nlRtxAG2FQ3B2OR6QIrPY3zE5LqJy1oxzmgBGsHLWTcNhWXKchgA0WHW+mZkQrng/pgcCew=="], + + "@aws-sdk/client-sesv2/@smithy/smithy-client/@smithy/util-stream/@smithy/util-hex-encoding": ["@smithy/util-hex-encoding@4.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-CCQBwJIvXMLKxVbO88IukazJD9a4kQ9ZN7/UMGBjBcJYvatpWk+9g870El4cB8/EJxfe+k+y0GmR9CAzkF+Nbw=="], + + "@aws-sdk/client-sesv2/@smithy/util-base64/@smithy/util-buffer-from/@smithy/is-array-buffer": ["@smithy/is-array-buffer@4.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-DZZZBvC7sjcYh4MazJSGiWMI2L7E0oCiRHREDzIxi/M2LY79/21iXt6aPLHge82wi5LsuRF5A06Ds3+0mlh6CQ=="], + + "@aws-sdk/client-sesv2/@smithy/util-utf8/@smithy/util-buffer-from/@smithy/is-array-buffer": ["@smithy/is-array-buffer@4.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-DZZZBvC7sjcYh4MazJSGiWMI2L7E0oCiRHREDzIxi/M2LY79/21iXt6aPLHge82wi5LsuRF5A06Ds3+0mlh6CQ=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/core/@smithy/core/@smithy/middleware-serde": ["@smithy/middleware-serde@4.2.6", "", { "dependencies": { "@smithy/protocol-http": "^5.3.5", "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-VkLoE/z7e2g8pirwisLz8XJWedUSY8my/qrp81VmAdyrhi94T+riBfwP+AOEEFR9rFTSonC/5D2eWNmFabHyGQ=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/core/@smithy/core/@smithy/util-body-length-browser": ["@smithy/util-body-length-browser@4.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-Fkoh/I76szMKJnBXWPdFkQJl2r9SjPt3cMzLdOB6eJ4Pnpas8hVoWPYemX/peO0yrrvldgCUVJqOAjUrOLjbxg=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/core/@smithy/core/@smithy/util-stream": ["@smithy/util-stream@4.5.6", "", { "dependencies": { "@smithy/fetch-http-handler": "^5.3.6", "@smithy/node-http-handler": "^4.4.5", "@smithy/types": "^4.9.0", "@smithy/util-base64": "^4.3.0", "@smithy/util-buffer-from": "^4.2.0", "@smithy/util-hex-encoding": "^4.2.0", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-qWw/UM59TiaFrPevefOZ8CNBKbYEP6wBAIlLqxn3VAIo9rgnTNc4ASbVrqDmhuwI87usnjhdQrxodzAGFFzbRQ=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/core/@smithy/core/@smithy/uuid": ["@smithy/uuid@1.1.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-4aUIteuyxtBUhVdiQqcDhKFitwfd9hqoSDYY2KRXiWtgoWJ9Bmise+KfEPDiVHWeJepvF8xJO9/9+WDIciMFFw=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/core/@smithy/signature-v4/@smithy/is-array-buffer": ["@smithy/is-array-buffer@4.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-DZZZBvC7sjcYh4MazJSGiWMI2L7E0oCiRHREDzIxi/M2LY79/21iXt6aPLHge82wi5LsuRF5A06Ds3+0mlh6CQ=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/core/@smithy/signature-v4/@smithy/util-hex-encoding": ["@smithy/util-hex-encoding@4.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-CCQBwJIvXMLKxVbO88IukazJD9a4kQ9ZN7/UMGBjBcJYvatpWk+9g870El4cB8/EJxfe+k+y0GmR9CAzkF+Nbw=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/core/@smithy/signature-v4/@smithy/util-uri-escape": ["@smithy/util-uri-escape@4.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-igZpCKV9+E/Mzrpq6YacdTQ0qTiLm85gD6N/IrmyDvQFA4UnU3d5g3m8tMT/6zG/vVkWSU+VxeUyGonL62DuxA=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/core/@smithy/smithy-client/@smithy/middleware-endpoint": ["@smithy/middleware-endpoint@4.3.12", "", { "dependencies": { "@smithy/core": "^3.18.5", "@smithy/middleware-serde": "^4.2.6", "@smithy/node-config-provider": "^4.3.5", "@smithy/shared-ini-file-loader": "^4.4.0", "@smithy/types": "^4.9.0", "@smithy/url-parser": "^4.2.5", "@smithy/util-middleware": "^4.2.5", "tslib": "^2.6.2" } }, "sha512-9pAX/H+VQPzNbouhDhkW723igBMLgrI8OtX+++M7iKJgg/zY/Ig3i1e6seCcx22FWhE6Q/S61BRdi2wXBORT+A=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/core/@smithy/smithy-client/@smithy/middleware-stack": ["@smithy/middleware-stack@4.2.5", "", { "dependencies": { "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-bYrutc+neOyWxtZdbB2USbQttZN0mXaOyYLIsaTbJhFsfpXyGWUxJpEuO1rJ8IIJm2qH4+xJT0mxUSsEDTYwdQ=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/core/@smithy/smithy-client/@smithy/util-stream": ["@smithy/util-stream@4.5.6", "", { "dependencies": { "@smithy/fetch-http-handler": "^5.3.6", "@smithy/node-http-handler": "^4.4.5", "@smithy/types": "^4.9.0", "@smithy/util-base64": "^4.3.0", "@smithy/util-buffer-from": "^4.2.0", "@smithy/util-hex-encoding": "^4.2.0", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-qWw/UM59TiaFrPevefOZ8CNBKbYEP6wBAIlLqxn3VAIo9rgnTNc4ASbVrqDmhuwI87usnjhdQrxodzAGFFzbRQ=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/core/@smithy/util-base64/@smithy/util-buffer-from": ["@smithy/util-buffer-from@4.2.0", "", { "dependencies": { "@smithy/is-array-buffer": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-kAY9hTKulTNevM2nlRtxAG2FQ3B2OR6QIrPY3zE5LqJy1oxzmgBGsHLWTcNhWXKchgA0WHW+mZkQrng/pgcCew=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/core/@smithy/util-utf8/@smithy/util-buffer-from": ["@smithy/util-buffer-from@4.2.0", "", { "dependencies": { "@smithy/is-array-buffer": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-kAY9hTKulTNevM2nlRtxAG2FQ3B2OR6QIrPY3zE5LqJy1oxzmgBGsHLWTcNhWXKchgA0WHW+mZkQrng/pgcCew=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/nested-clients/@aws-sdk/middleware-recursion-detection/@aws/lambda-invoke-store": ["@aws/lambda-invoke-store@0.2.1", "", {}, "sha512-sIyFcoPZkTtNu9xFeEoynMef3bPJIAbOfUh+ueYcfhVl6xm2VRtMcMclSxmZCMnHHd4hlYKJeq/aggmBEWynww=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/nested-clients/@smithy/config-resolver/@smithy/util-config-provider": ["@smithy/util-config-provider@4.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-YEjpl6XJ36FTKmD+kRJJWYvrHeUvm5ykaUS5xK+6oXffQPHeEM4/nXlZPe+Wu0lsgRUcNZiliYNh/y7q9c2y6Q=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/nested-clients/@smithy/core/@smithy/util-stream": ["@smithy/util-stream@4.5.6", "", { "dependencies": { "@smithy/fetch-http-handler": "^5.3.6", "@smithy/node-http-handler": "^4.4.5", "@smithy/types": "^4.9.0", "@smithy/util-base64": "^4.3.0", "@smithy/util-buffer-from": "^4.2.0", "@smithy/util-hex-encoding": "^4.2.0", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-qWw/UM59TiaFrPevefOZ8CNBKbYEP6wBAIlLqxn3VAIo9rgnTNc4ASbVrqDmhuwI87usnjhdQrxodzAGFFzbRQ=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/nested-clients/@smithy/core/@smithy/uuid": ["@smithy/uuid@1.1.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-4aUIteuyxtBUhVdiQqcDhKFitwfd9hqoSDYY2KRXiWtgoWJ9Bmise+KfEPDiVHWeJepvF8xJO9/9+WDIciMFFw=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/nested-clients/@smithy/fetch-http-handler/@smithy/querystring-builder": ["@smithy/querystring-builder@4.2.5", "", { "dependencies": { "@smithy/types": "^4.9.0", "@smithy/util-uri-escape": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-y98otMI1saoajeik2kLfGyRp11e5U/iJYH/wLCh3aTV/XutbGT9nziKGkgCaMD1ghK7p6htHMm6b6scl9JRUWg=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/nested-clients/@smithy/hash-node/@smithy/util-buffer-from": ["@smithy/util-buffer-from@4.2.0", "", { "dependencies": { "@smithy/is-array-buffer": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-kAY9hTKulTNevM2nlRtxAG2FQ3B2OR6QIrPY3zE5LqJy1oxzmgBGsHLWTcNhWXKchgA0WHW+mZkQrng/pgcCew=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/nested-clients/@smithy/middleware-retry/@smithy/service-error-classification": ["@smithy/service-error-classification@4.2.5", "", { "dependencies": { "@smithy/types": "^4.9.0" } }, "sha512-8fEvK+WPE3wUAcDvqDQG1Vk3ANLR8Px979te96m84CbKAjBVf25rPYSzb4xU4hlTyho7VhOGnh5i62D/JVF0JQ=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/nested-clients/@smithy/middleware-retry/@smithy/uuid": ["@smithy/uuid@1.1.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-4aUIteuyxtBUhVdiQqcDhKFitwfd9hqoSDYY2KRXiWtgoWJ9Bmise+KfEPDiVHWeJepvF8xJO9/9+WDIciMFFw=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/nested-clients/@smithy/node-http-handler/@smithy/abort-controller": ["@smithy/abort-controller@4.2.5", "", { "dependencies": { "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-j7HwVkBw68YW8UmFRcjZOmssE77Rvk0GWAIN1oFBhsaovQmZWYCIcGa9/pwRB0ExI8Sk9MWNALTjftjHZea7VA=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/nested-clients/@smithy/node-http-handler/@smithy/querystring-builder": ["@smithy/querystring-builder@4.2.5", "", { "dependencies": { "@smithy/types": "^4.9.0", "@smithy/util-uri-escape": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-y98otMI1saoajeik2kLfGyRp11e5U/iJYH/wLCh3aTV/XutbGT9nziKGkgCaMD1ghK7p6htHMm6b6scl9JRUWg=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/nested-clients/@smithy/smithy-client/@smithy/util-stream": ["@smithy/util-stream@4.5.6", "", { "dependencies": { "@smithy/fetch-http-handler": "^5.3.6", "@smithy/node-http-handler": "^4.4.5", "@smithy/types": "^4.9.0", "@smithy/util-base64": "^4.3.0", "@smithy/util-buffer-from": "^4.2.0", "@smithy/util-hex-encoding": "^4.2.0", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-qWw/UM59TiaFrPevefOZ8CNBKbYEP6wBAIlLqxn3VAIo9rgnTNc4ASbVrqDmhuwI87usnjhdQrxodzAGFFzbRQ=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/nested-clients/@smithy/url-parser/@smithy/querystring-parser": ["@smithy/querystring-parser@4.2.5", "", { "dependencies": { "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-031WCTdPYgiQRYNPXznHXof2YM0GwL6SeaSyTH/P72M1Vz73TvCNH2Nq8Iu2IEPq9QP2yx0/nrw5YmSeAi/AjQ=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/nested-clients/@smithy/util-base64/@smithy/util-buffer-from": ["@smithy/util-buffer-from@4.2.0", "", { "dependencies": { "@smithy/is-array-buffer": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-kAY9hTKulTNevM2nlRtxAG2FQ3B2OR6QIrPY3zE5LqJy1oxzmgBGsHLWTcNhWXKchgA0WHW+mZkQrng/pgcCew=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/nested-clients/@smithy/util-defaults-mode-node/@smithy/credential-provider-imds": ["@smithy/credential-provider-imds@4.2.5", "", { "dependencies": { "@smithy/node-config-provider": "^4.3.5", "@smithy/property-provider": "^4.2.5", "@smithy/types": "^4.9.0", "@smithy/url-parser": "^4.2.5", "tslib": "^2.6.2" } }, "sha512-BZwotjoZWn9+36nimwm/OLIcVe+KYRwzMjfhd4QT7QxPm9WY0HiOV8t/Wlh+HVUif0SBVV7ksq8//hPaBC/okQ=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/nested-clients/@smithy/util-retry/@smithy/service-error-classification": ["@smithy/service-error-classification@4.2.5", "", { "dependencies": { "@smithy/types": "^4.9.0" } }, "sha512-8fEvK+WPE3wUAcDvqDQG1Vk3ANLR8Px979te96m84CbKAjBVf25rPYSzb4xU4hlTyho7VhOGnh5i62D/JVF0JQ=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/nested-clients/@smithy/util-utf8/@smithy/util-buffer-from": ["@smithy/util-buffer-from@4.2.0", "", { "dependencies": { "@smithy/is-array-buffer": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-kAY9hTKulTNevM2nlRtxAG2FQ3B2OR6QIrPY3zE5LqJy1oxzmgBGsHLWTcNhWXKchgA0WHW+mZkQrng/pgcCew=="], + "@browserbasehq/sdk/node-fetch/whatwg-url/tr46": ["tr46@0.0.3", "", {}, "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="], "@browserbasehq/sdk/node-fetch/whatwg-url/webidl-conversions": ["webidl-conversions@3.0.1", "", {}, "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="], @@ -4029,6 +4379,62 @@ "test-exclude/glob/path-scurry/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], + "@aws-sdk/client-sesv2/@aws-sdk/credential-provider-node/@aws-sdk/credential-provider-http/@smithy/util-stream/@smithy/util-buffer-from": ["@smithy/util-buffer-from@4.2.0", "", { "dependencies": { "@smithy/is-array-buffer": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-kAY9hTKulTNevM2nlRtxAG2FQ3B2OR6QIrPY3zE5LqJy1oxzmgBGsHLWTcNhWXKchgA0WHW+mZkQrng/pgcCew=="], + + "@aws-sdk/client-sesv2/@aws-sdk/credential-provider-node/@aws-sdk/credential-provider-http/@smithy/util-stream/@smithy/util-hex-encoding": ["@smithy/util-hex-encoding@4.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-CCQBwJIvXMLKxVbO88IukazJD9a4kQ9ZN7/UMGBjBcJYvatpWk+9g870El4cB8/EJxfe+k+y0GmR9CAzkF+Nbw=="], + + "@aws-sdk/client-sesv2/@aws-sdk/credential-provider-node/@aws-sdk/credential-provider-sso/@aws-sdk/token-providers/@aws-sdk/nested-clients": ["@aws-sdk/nested-clients@3.940.0", "", { "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "3.940.0", "@aws-sdk/middleware-host-header": "3.936.0", "@aws-sdk/middleware-logger": "3.936.0", "@aws-sdk/middleware-recursion-detection": "3.936.0", "@aws-sdk/middleware-user-agent": "3.940.0", "@aws-sdk/region-config-resolver": "3.936.0", "@aws-sdk/types": "3.936.0", "@aws-sdk/util-endpoints": "3.936.0", "@aws-sdk/util-user-agent-browser": "3.936.0", "@aws-sdk/util-user-agent-node": "3.940.0", "@smithy/config-resolver": "^4.4.3", "@smithy/core": "^3.18.5", "@smithy/fetch-http-handler": "^5.3.6", "@smithy/hash-node": "^4.2.5", "@smithy/invalid-dependency": "^4.2.5", "@smithy/middleware-content-length": "^4.2.5", "@smithy/middleware-endpoint": "^4.3.12", "@smithy/middleware-retry": "^4.4.12", "@smithy/middleware-serde": "^4.2.6", "@smithy/middleware-stack": "^4.2.5", "@smithy/node-config-provider": "^4.3.5", "@smithy/node-http-handler": "^4.4.5", "@smithy/protocol-http": "^5.3.5", "@smithy/smithy-client": "^4.9.8", "@smithy/types": "^4.9.0", "@smithy/url-parser": "^4.2.5", "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", "@smithy/util-body-length-node": "^4.2.1", "@smithy/util-defaults-mode-browser": "^4.3.11", "@smithy/util-defaults-mode-node": "^4.2.14", "@smithy/util-endpoints": "^3.2.5", "@smithy/util-middleware": "^4.2.5", "@smithy/util-retry": "^4.2.5", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-x0mdv6DkjXqXEcQj3URbCltEzW6hoy/1uIL+i8gExP6YKrnhiZ7SzuB4gPls2UOpK5UqLiqXjhRLfBb1C9i4Dw=="], + + "@aws-sdk/client-sesv2/@aws-sdk/signature-v4-multi-region/@aws-sdk/middleware-sdk-s3/@smithy/util-stream/@smithy/util-buffer-from": ["@smithy/util-buffer-from@4.2.0", "", { "dependencies": { "@smithy/is-array-buffer": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-kAY9hTKulTNevM2nlRtxAG2FQ3B2OR6QIrPY3zE5LqJy1oxzmgBGsHLWTcNhWXKchgA0WHW+mZkQrng/pgcCew=="], + + "@aws-sdk/client-sesv2/@aws-sdk/signature-v4-multi-region/@aws-sdk/middleware-sdk-s3/@smithy/util-stream/@smithy/util-hex-encoding": ["@smithy/util-hex-encoding@4.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-CCQBwJIvXMLKxVbO88IukazJD9a4kQ9ZN7/UMGBjBcJYvatpWk+9g870El4cB8/EJxfe+k+y0GmR9CAzkF+Nbw=="], + + "@aws-sdk/client-sesv2/@smithy/core/@smithy/util-stream/@smithy/util-buffer-from/@smithy/is-array-buffer": ["@smithy/is-array-buffer@4.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-DZZZBvC7sjcYh4MazJSGiWMI2L7E0oCiRHREDzIxi/M2LY79/21iXt6aPLHge82wi5LsuRF5A06Ds3+0mlh6CQ=="], + + "@aws-sdk/client-sesv2/@smithy/smithy-client/@smithy/util-stream/@smithy/util-buffer-from/@smithy/is-array-buffer": ["@smithy/is-array-buffer@4.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-DZZZBvC7sjcYh4MazJSGiWMI2L7E0oCiRHREDzIxi/M2LY79/21iXt6aPLHge82wi5LsuRF5A06Ds3+0mlh6CQ=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/core/@smithy/core/@smithy/util-stream/@smithy/fetch-http-handler": ["@smithy/fetch-http-handler@5.3.6", "", { "dependencies": { "@smithy/protocol-http": "^5.3.5", "@smithy/querystring-builder": "^4.2.5", "@smithy/types": "^4.9.0", "@smithy/util-base64": "^4.3.0", "tslib": "^2.6.2" } }, "sha512-3+RG3EA6BBJ/ofZUeTFJA7mHfSYrZtQIrDP9dI8Lf7X6Jbos2jptuLrAAteDiFVrmbEmLSuRG/bUKzfAXk7dhg=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/core/@smithy/core/@smithy/util-stream/@smithy/node-http-handler": ["@smithy/node-http-handler@4.4.5", "", { "dependencies": { "@smithy/abort-controller": "^4.2.5", "@smithy/protocol-http": "^5.3.5", "@smithy/querystring-builder": "^4.2.5", "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-CMnzM9R2WqlqXQGtIlsHMEZfXKJVTIrqCNoSd/QpAyp+Dw0a1Vps13l6ma1fH8g7zSPNsA59B/kWgeylFuA/lw=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/core/@smithy/core/@smithy/util-stream/@smithy/util-buffer-from": ["@smithy/util-buffer-from@4.2.0", "", { "dependencies": { "@smithy/is-array-buffer": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-kAY9hTKulTNevM2nlRtxAG2FQ3B2OR6QIrPY3zE5LqJy1oxzmgBGsHLWTcNhWXKchgA0WHW+mZkQrng/pgcCew=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/core/@smithy/core/@smithy/util-stream/@smithy/util-hex-encoding": ["@smithy/util-hex-encoding@4.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-CCQBwJIvXMLKxVbO88IukazJD9a4kQ9ZN7/UMGBjBcJYvatpWk+9g870El4cB8/EJxfe+k+y0GmR9CAzkF+Nbw=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/core/@smithy/smithy-client/@smithy/middleware-endpoint/@smithy/middleware-serde": ["@smithy/middleware-serde@4.2.6", "", { "dependencies": { "@smithy/protocol-http": "^5.3.5", "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-VkLoE/z7e2g8pirwisLz8XJWedUSY8my/qrp81VmAdyrhi94T+riBfwP+AOEEFR9rFTSonC/5D2eWNmFabHyGQ=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/core/@smithy/smithy-client/@smithy/middleware-endpoint/@smithy/url-parser": ["@smithy/url-parser@4.2.5", "", { "dependencies": { "@smithy/querystring-parser": "^4.2.5", "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-VaxMGsilqFnK1CeBX+LXnSuaMx4sTL/6znSZh2829txWieazdVxr54HmiyTsIbpOTLcf5nYpq9lpzmwRdxj6rQ=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/core/@smithy/smithy-client/@smithy/util-stream/@smithy/fetch-http-handler": ["@smithy/fetch-http-handler@5.3.6", "", { "dependencies": { "@smithy/protocol-http": "^5.3.5", "@smithy/querystring-builder": "^4.2.5", "@smithy/types": "^4.9.0", "@smithy/util-base64": "^4.3.0", "tslib": "^2.6.2" } }, "sha512-3+RG3EA6BBJ/ofZUeTFJA7mHfSYrZtQIrDP9dI8Lf7X6Jbos2jptuLrAAteDiFVrmbEmLSuRG/bUKzfAXk7dhg=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/core/@smithy/smithy-client/@smithy/util-stream/@smithy/node-http-handler": ["@smithy/node-http-handler@4.4.5", "", { "dependencies": { "@smithy/abort-controller": "^4.2.5", "@smithy/protocol-http": "^5.3.5", "@smithy/querystring-builder": "^4.2.5", "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-CMnzM9R2WqlqXQGtIlsHMEZfXKJVTIrqCNoSd/QpAyp+Dw0a1Vps13l6ma1fH8g7zSPNsA59B/kWgeylFuA/lw=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/core/@smithy/smithy-client/@smithy/util-stream/@smithy/util-buffer-from": ["@smithy/util-buffer-from@4.2.0", "", { "dependencies": { "@smithy/is-array-buffer": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-kAY9hTKulTNevM2nlRtxAG2FQ3B2OR6QIrPY3zE5LqJy1oxzmgBGsHLWTcNhWXKchgA0WHW+mZkQrng/pgcCew=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/core/@smithy/smithy-client/@smithy/util-stream/@smithy/util-hex-encoding": ["@smithy/util-hex-encoding@4.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-CCQBwJIvXMLKxVbO88IukazJD9a4kQ9ZN7/UMGBjBcJYvatpWk+9g870El4cB8/EJxfe+k+y0GmR9CAzkF+Nbw=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/core/@smithy/util-base64/@smithy/util-buffer-from/@smithy/is-array-buffer": ["@smithy/is-array-buffer@4.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-DZZZBvC7sjcYh4MazJSGiWMI2L7E0oCiRHREDzIxi/M2LY79/21iXt6aPLHge82wi5LsuRF5A06Ds3+0mlh6CQ=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/core/@smithy/util-utf8/@smithy/util-buffer-from/@smithy/is-array-buffer": ["@smithy/is-array-buffer@4.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-DZZZBvC7sjcYh4MazJSGiWMI2L7E0oCiRHREDzIxi/M2LY79/21iXt6aPLHge82wi5LsuRF5A06Ds3+0mlh6CQ=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/nested-clients/@smithy/core/@smithy/util-stream/@smithy/util-buffer-from": ["@smithy/util-buffer-from@4.2.0", "", { "dependencies": { "@smithy/is-array-buffer": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-kAY9hTKulTNevM2nlRtxAG2FQ3B2OR6QIrPY3zE5LqJy1oxzmgBGsHLWTcNhWXKchgA0WHW+mZkQrng/pgcCew=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/nested-clients/@smithy/core/@smithy/util-stream/@smithy/util-hex-encoding": ["@smithy/util-hex-encoding@4.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-CCQBwJIvXMLKxVbO88IukazJD9a4kQ9ZN7/UMGBjBcJYvatpWk+9g870El4cB8/EJxfe+k+y0GmR9CAzkF+Nbw=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/nested-clients/@smithy/fetch-http-handler/@smithy/querystring-builder/@smithy/util-uri-escape": ["@smithy/util-uri-escape@4.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-igZpCKV9+E/Mzrpq6YacdTQ0qTiLm85gD6N/IrmyDvQFA4UnU3d5g3m8tMT/6zG/vVkWSU+VxeUyGonL62DuxA=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/nested-clients/@smithy/hash-node/@smithy/util-buffer-from/@smithy/is-array-buffer": ["@smithy/is-array-buffer@4.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-DZZZBvC7sjcYh4MazJSGiWMI2L7E0oCiRHREDzIxi/M2LY79/21iXt6aPLHge82wi5LsuRF5A06Ds3+0mlh6CQ=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/nested-clients/@smithy/node-http-handler/@smithy/querystring-builder/@smithy/util-uri-escape": ["@smithy/util-uri-escape@4.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-igZpCKV9+E/Mzrpq6YacdTQ0qTiLm85gD6N/IrmyDvQFA4UnU3d5g3m8tMT/6zG/vVkWSU+VxeUyGonL62DuxA=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/nested-clients/@smithy/smithy-client/@smithy/util-stream/@smithy/util-buffer-from": ["@smithy/util-buffer-from@4.2.0", "", { "dependencies": { "@smithy/is-array-buffer": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-kAY9hTKulTNevM2nlRtxAG2FQ3B2OR6QIrPY3zE5LqJy1oxzmgBGsHLWTcNhWXKchgA0WHW+mZkQrng/pgcCew=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/nested-clients/@smithy/smithy-client/@smithy/util-stream/@smithy/util-hex-encoding": ["@smithy/util-hex-encoding@4.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-CCQBwJIvXMLKxVbO88IukazJD9a4kQ9ZN7/UMGBjBcJYvatpWk+9g870El4cB8/EJxfe+k+y0GmR9CAzkF+Nbw=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/nested-clients/@smithy/util-base64/@smithy/util-buffer-from/@smithy/is-array-buffer": ["@smithy/is-array-buffer@4.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-DZZZBvC7sjcYh4MazJSGiWMI2L7E0oCiRHREDzIxi/M2LY79/21iXt6aPLHge82wi5LsuRF5A06Ds3+0mlh6CQ=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/nested-clients/@smithy/util-utf8/@smithy/util-buffer-from/@smithy/is-array-buffer": ["@smithy/is-array-buffer@4.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-DZZZBvC7sjcYh4MazJSGiWMI2L7E0oCiRHREDzIxi/M2LY79/21iXt6aPLHge82wi5LsuRF5A06Ds3+0mlh6CQ=="], + "@trigger.dev/core/socket.io/engine.io/@types/node/undici-types": ["undici-types@7.10.0", "", {}, "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag=="], "lint-staged/listr2/cli-truncate/string-width/strip-ansi": ["strip-ansi@7.1.2", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA=="], @@ -4049,8 +4455,42 @@ "sim/tailwindcss/chokidar/readdirp/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], + "@aws-sdk/client-sesv2/@aws-sdk/credential-provider-node/@aws-sdk/credential-provider-http/@smithy/util-stream/@smithy/util-buffer-from/@smithy/is-array-buffer": ["@smithy/is-array-buffer@4.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-DZZZBvC7sjcYh4MazJSGiWMI2L7E0oCiRHREDzIxi/M2LY79/21iXt6aPLHge82wi5LsuRF5A06Ds3+0mlh6CQ=="], + + "@aws-sdk/client-sesv2/@aws-sdk/signature-v4-multi-region/@aws-sdk/middleware-sdk-s3/@smithy/util-stream/@smithy/util-buffer-from/@smithy/is-array-buffer": ["@smithy/is-array-buffer@4.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-DZZZBvC7sjcYh4MazJSGiWMI2L7E0oCiRHREDzIxi/M2LY79/21iXt6aPLHge82wi5LsuRF5A06Ds3+0mlh6CQ=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/core/@smithy/core/@smithy/util-stream/@smithy/fetch-http-handler/@smithy/querystring-builder": ["@smithy/querystring-builder@4.2.5", "", { "dependencies": { "@smithy/types": "^4.9.0", "@smithy/util-uri-escape": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-y98otMI1saoajeik2kLfGyRp11e5U/iJYH/wLCh3aTV/XutbGT9nziKGkgCaMD1ghK7p6htHMm6b6scl9JRUWg=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/core/@smithy/core/@smithy/util-stream/@smithy/node-http-handler/@smithy/abort-controller": ["@smithy/abort-controller@4.2.5", "", { "dependencies": { "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-j7HwVkBw68YW8UmFRcjZOmssE77Rvk0GWAIN1oFBhsaovQmZWYCIcGa9/pwRB0ExI8Sk9MWNALTjftjHZea7VA=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/core/@smithy/core/@smithy/util-stream/@smithy/node-http-handler/@smithy/querystring-builder": ["@smithy/querystring-builder@4.2.5", "", { "dependencies": { "@smithy/types": "^4.9.0", "@smithy/util-uri-escape": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-y98otMI1saoajeik2kLfGyRp11e5U/iJYH/wLCh3aTV/XutbGT9nziKGkgCaMD1ghK7p6htHMm6b6scl9JRUWg=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/core/@smithy/core/@smithy/util-stream/@smithy/util-buffer-from/@smithy/is-array-buffer": ["@smithy/is-array-buffer@4.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-DZZZBvC7sjcYh4MazJSGiWMI2L7E0oCiRHREDzIxi/M2LY79/21iXt6aPLHge82wi5LsuRF5A06Ds3+0mlh6CQ=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/core/@smithy/smithy-client/@smithy/middleware-endpoint/@smithy/url-parser/@smithy/querystring-parser": ["@smithy/querystring-parser@4.2.5", "", { "dependencies": { "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-031WCTdPYgiQRYNPXznHXof2YM0GwL6SeaSyTH/P72M1Vz73TvCNH2Nq8Iu2IEPq9QP2yx0/nrw5YmSeAi/AjQ=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/core/@smithy/smithy-client/@smithy/util-stream/@smithy/fetch-http-handler/@smithy/querystring-builder": ["@smithy/querystring-builder@4.2.5", "", { "dependencies": { "@smithy/types": "^4.9.0", "@smithy/util-uri-escape": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-y98otMI1saoajeik2kLfGyRp11e5U/iJYH/wLCh3aTV/XutbGT9nziKGkgCaMD1ghK7p6htHMm6b6scl9JRUWg=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/core/@smithy/smithy-client/@smithy/util-stream/@smithy/node-http-handler/@smithy/abort-controller": ["@smithy/abort-controller@4.2.5", "", { "dependencies": { "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-j7HwVkBw68YW8UmFRcjZOmssE77Rvk0GWAIN1oFBhsaovQmZWYCIcGa9/pwRB0ExI8Sk9MWNALTjftjHZea7VA=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/core/@smithy/smithy-client/@smithy/util-stream/@smithy/node-http-handler/@smithy/querystring-builder": ["@smithy/querystring-builder@4.2.5", "", { "dependencies": { "@smithy/types": "^4.9.0", "@smithy/util-uri-escape": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-y98otMI1saoajeik2kLfGyRp11e5U/iJYH/wLCh3aTV/XutbGT9nziKGkgCaMD1ghK7p6htHMm6b6scl9JRUWg=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/core/@smithy/smithy-client/@smithy/util-stream/@smithy/util-buffer-from/@smithy/is-array-buffer": ["@smithy/is-array-buffer@4.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-DZZZBvC7sjcYh4MazJSGiWMI2L7E0oCiRHREDzIxi/M2LY79/21iXt6aPLHge82wi5LsuRF5A06Ds3+0mlh6CQ=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/nested-clients/@smithy/core/@smithy/util-stream/@smithy/util-buffer-from/@smithy/is-array-buffer": ["@smithy/is-array-buffer@4.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-DZZZBvC7sjcYh4MazJSGiWMI2L7E0oCiRHREDzIxi/M2LY79/21iXt6aPLHge82wi5LsuRF5A06Ds3+0mlh6CQ=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/nested-clients/@smithy/smithy-client/@smithy/util-stream/@smithy/util-buffer-from/@smithy/is-array-buffer": ["@smithy/is-array-buffer@4.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-DZZZBvC7sjcYh4MazJSGiWMI2L7E0oCiRHREDzIxi/M2LY79/21iXt6aPLHge82wi5LsuRF5A06Ds3+0mlh6CQ=="], + "lint-staged/listr2/cli-truncate/string-width/strip-ansi/ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="], "lint-staged/listr2/log-update/cli-cursor/restore-cursor/onetime": ["onetime@7.0.0", "", { "dependencies": { "mimic-function": "^5.0.0" } }, "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/core/@smithy/core/@smithy/util-stream/@smithy/fetch-http-handler/@smithy/querystring-builder/@smithy/util-uri-escape": ["@smithy/util-uri-escape@4.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-igZpCKV9+E/Mzrpq6YacdTQ0qTiLm85gD6N/IrmyDvQFA4UnU3d5g3m8tMT/6zG/vVkWSU+VxeUyGonL62DuxA=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/core/@smithy/core/@smithy/util-stream/@smithy/node-http-handler/@smithy/querystring-builder/@smithy/util-uri-escape": ["@smithy/util-uri-escape@4.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-igZpCKV9+E/Mzrpq6YacdTQ0qTiLm85gD6N/IrmyDvQFA4UnU3d5g3m8tMT/6zG/vVkWSU+VxeUyGonL62DuxA=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/core/@smithy/smithy-client/@smithy/util-stream/@smithy/fetch-http-handler/@smithy/querystring-builder/@smithy/util-uri-escape": ["@smithy/util-uri-escape@4.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-igZpCKV9+E/Mzrpq6YacdTQ0qTiLm85gD6N/IrmyDvQFA4UnU3d5g3m8tMT/6zG/vVkWSU+VxeUyGonL62DuxA=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/core/@smithy/smithy-client/@smithy/util-stream/@smithy/node-http-handler/@smithy/querystring-builder/@smithy/util-uri-escape": ["@smithy/util-uri-escape@4.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-igZpCKV9+E/Mzrpq6YacdTQ0qTiLm85gD6N/IrmyDvQFA4UnU3d5g3m8tMT/6zG/vVkWSU+VxeUyGonL62DuxA=="], } } diff --git a/package.json b/package.json index 60219b7788..510943d58b 100644 --- a/package.json +++ b/package.json @@ -46,6 +46,7 @@ "fluent-ffmpeg": "2.1.3", "mongodb": "6.19.0", "neo4j-driver": "6.0.1", + "nodemailer": "7.0.11", "onedollarstats": "0.0.10", "postgres": "^3.4.5", "remark-gfm": "4.0.1", @@ -57,6 +58,7 @@ "@next/env": "15.4.1", "@octokit/rest": "^21.0.0", "@tailwindcss/typography": "0.5.19", + "@types/nodemailer": "7.0.4", "drizzle-kit": "^0.31.4", "husky": "9.1.7", "lint-staged": "16.0.0", From fc5f815c7a19201c5454307ac6eca533ec007480 Mon Sep 17 00:00:00 2001 From: Vikhyath Mondreti Date: Sat, 29 Nov 2025 18:27:12 -0800 Subject: [PATCH 02/16] fix(team-plans): track departed member usage so value not lost (#2118) * fix(team-plans): track departed member usage so value not lost * reset usage to 0 when they leave team * prep merge with stagig * regen migrations * fix org invite + ws selection' --------- Co-authored-by: Waleed --- .../[id]/members/[memberId]/route.ts | 48 +- .../team-management/team-management.tsx | 13 +- apps/sim/hooks/queries/organization.ts | 2 +- apps/sim/lib/billing/core/billing.ts | 21 +- .../lib/billing/validation/seat-management.ts | 120 - apps/sim/lib/billing/webhooks/invoices.ts | 13 +- packages/db/migrations/0114_wise_sunfire.sql | 1 + .../db/migrations/meta/0114_snapshot.json | 7695 +++++++++++++++++ packages/db/migrations/meta/_journal.json | 7 + packages/db/schema.ts | 3 +- 10 files changed, 7784 insertions(+), 139 deletions(-) create mode 100644 packages/db/migrations/0114_wise_sunfire.sql create mode 100644 packages/db/migrations/meta/0114_snapshot.json diff --git a/apps/sim/app/api/organizations/[id]/members/[memberId]/route.ts b/apps/sim/app/api/organizations/[id]/members/[memberId]/route.ts index b8ee55b243..104d8368bf 100644 --- a/apps/sim/app/api/organizations/[id]/members/[memberId]/route.ts +++ b/apps/sim/app/api/organizations/[id]/members/[memberId]/route.ts @@ -1,6 +1,12 @@ import { db } from '@sim/db' -import { member, subscription as subscriptionTable, user, userStats } from '@sim/db/schema' -import { and, eq } from 'drizzle-orm' +import { + member, + organization, + subscription as subscriptionTable, + user, + userStats, +} from '@sim/db/schema' +import { and, eq, sql } from 'drizzle-orm' import { type NextRequest, NextResponse } from 'next/server' import { z } from 'zod' import { getSession } from '@/lib/auth' @@ -297,6 +303,44 @@ export async function DELETE( return NextResponse.json({ error: 'Cannot remove organization owner' }, { status: 400 }) } + // Capture departed member's usage and reset their cost to prevent double billing + try { + const departingUserStats = await db + .select({ currentPeriodCost: userStats.currentPeriodCost }) + .from(userStats) + .where(eq(userStats.userId, memberId)) + .limit(1) + + if (departingUserStats.length > 0 && departingUserStats[0].currentPeriodCost) { + const usage = Number.parseFloat(departingUserStats[0].currentPeriodCost) + if (usage > 0) { + await db + .update(organization) + .set({ + departedMemberUsage: sql`${organization.departedMemberUsage} + ${usage}`, + }) + .where(eq(organization.id, organizationId)) + + await db + .update(userStats) + .set({ currentPeriodCost: '0' }) + .where(eq(userStats.userId, memberId)) + + logger.info('Captured departed member usage and reset user cost', { + organizationId, + memberId, + usage, + }) + } + } + } catch (usageCaptureError) { + logger.error('Failed to capture departed member usage', { + organizationId, + memberId, + error: usageCaptureError, + }) + } + // Remove member const removedMember = await db .delete(member) diff --git a/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components-new/settings-modal/components/team-management/team-management.tsx b/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components-new/settings-modal/components/team-management/team-management.tsx index d0e38f80a1..784758df48 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components-new/settings-modal/components/team-management/team-management.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components-new/settings-modal/components/team-management/team-management.tsx @@ -123,8 +123,8 @@ export function TeamManagement() { const workspaceInvitations = selectedWorkspaces.length > 0 ? selectedWorkspaces.map((w) => ({ - id: w.workspaceId, - name: adminWorkspaces.find((uw) => uw.id === w.workspaceId)?.name || '', + workspaceId: w.workspaceId, + permission: w.permission as 'admin' | 'write' | 'read', })) : undefined @@ -145,14 +145,7 @@ export function TeamManagement() { } catch (error) { logger.error('Failed to invite member', error) } - }, [ - session?.user?.id, - activeOrganization?.id, - inviteEmail, - selectedWorkspaces, - adminWorkspaces, - inviteMutation, - ]) + }, [session?.user?.id, activeOrganization?.id, inviteEmail, selectedWorkspaces, inviteMutation]) const handleWorkspaceToggle = useCallback((workspaceId: string, permission: string) => { setSelectedWorkspaces((prev) => { diff --git a/apps/sim/hooks/queries/organization.ts b/apps/sim/hooks/queries/organization.ts index f77273152b..95d13115e3 100644 --- a/apps/sim/hooks/queries/organization.ts +++ b/apps/sim/hooks/queries/organization.ts @@ -257,7 +257,7 @@ export function useUpdateOrganizationUsageLimit() { */ interface InviteMemberParams { email: string - workspaceInvitations?: Array<{ id: string; name: string }> + workspaceInvitations?: Array<{ workspaceId: string; permission: 'admin' | 'write' | 'read' }> orgId: string } diff --git a/apps/sim/lib/billing/core/billing.ts b/apps/sim/lib/billing/core/billing.ts index 4fdc1eb2c7..03fe712c1a 100644 --- a/apps/sim/lib/billing/core/billing.ts +++ b/apps/sim/lib/billing/core/billing.ts @@ -1,5 +1,5 @@ import { db } from '@sim/db' -import { member, subscription, user, userStats } from '@sim/db/schema' +import { member, organization, subscription, user, userStats } from '@sim/db/schema' import { and, eq } from 'drizzle-orm' import { getHighestPrioritySubscription } from '@/lib/billing/core/subscription' import { getUserUsageData } from '@/lib/billing/core/usage' @@ -120,7 +120,6 @@ export async function calculateSubscriptionOverage(sub: { let totalOverage = 0 if (sub.plan === 'team') { - // Team plan: sum all member usage const members = await db .select({ userId: member.userId }) .from(member) @@ -132,13 +131,27 @@ export async function calculateSubscriptionOverage(sub: { totalTeamUsage += usage.currentUsage } + const orgData = await db + .select({ departedMemberUsage: organization.departedMemberUsage }) + .from(organization) + .where(eq(organization.id, sub.referenceId)) + .limit(1) + + const departedUsage = + orgData.length > 0 && orgData[0].departedMemberUsage + ? Number.parseFloat(orgData[0].departedMemberUsage) + : 0 + + const totalUsageWithDeparted = totalTeamUsage + departedUsage const { basePrice } = getPlanPricing(sub.plan) const baseSubscriptionAmount = (sub.seats || 1) * basePrice - totalOverage = Math.max(0, totalTeamUsage - baseSubscriptionAmount) + totalOverage = Math.max(0, totalUsageWithDeparted - baseSubscriptionAmount) logger.info('Calculated team overage', { subscriptionId: sub.id, - totalTeamUsage, + currentMemberUsage: totalTeamUsage, + departedMemberUsage: departedUsage, + totalUsage: totalUsageWithDeparted, baseSubscriptionAmount, totalOverage, }) diff --git a/apps/sim/lib/billing/validation/seat-management.ts b/apps/sim/lib/billing/validation/seat-management.ts index bc4791f51b..be4dd4b31d 100644 --- a/apps/sim/lib/billing/validation/seat-management.ts +++ b/apps/sim/lib/billing/validation/seat-management.ts @@ -239,126 +239,6 @@ export async function validateBulkInvitations( } } -/** - * Update organization seat count in subscription - */ -export async function updateOrganizationSeats( - organizationId: string, - newSeatCount: number, - updatedBy: string -): Promise<{ success: boolean; error?: string }> { - try { - const subscriptionRecord = await getOrganizationSubscription(organizationId) - - if (!subscriptionRecord) { - return { success: false, error: 'No active subscription found' } - } - - const memberCount = await db - .select({ count: count() }) - .from(member) - .where(eq(member.organizationId, organizationId)) - - const currentMembers = memberCount[0]?.count || 0 - - if (newSeatCount < currentMembers) { - return { - success: false, - error: `Cannot reduce seats below current member count (${currentMembers})`, - } - } - - await db - .update(subscription) - .set({ - seats: newSeatCount, - }) - .where(eq(subscription.id, subscriptionRecord.id)) - - logger.info('Organization seat count updated', { - organizationId, - oldSeatCount: subscriptionRecord.seats, - newSeatCount, - updatedBy, - }) - - return { success: true } - } catch (error) { - logger.error('Failed to update organization seats', { - organizationId, - newSeatCount, - updatedBy, - error, - }) - - return { - success: false, - error: error instanceof Error ? error.message : 'Unknown error', - } - } -} - -/** - * Check if a user can be removed from an organization - */ -export async function validateMemberRemoval( - organizationId: string, - userIdToRemove: string, - removedBy: string -): Promise<{ canRemove: boolean; reason?: string }> { - try { - const memberRecord = await db - .select({ role: member.role }) - .from(member) - .where(and(eq(member.organizationId, organizationId), eq(member.userId, userIdToRemove))) - .limit(1) - - if (memberRecord.length === 0) { - return { canRemove: false, reason: 'Member not found in organization' } - } - - if (memberRecord[0].role === 'owner') { - return { canRemove: false, reason: 'Cannot remove organization owner' } - } - - const removerMemberRecord = await db - .select({ role: member.role }) - .from(member) - .where(and(eq(member.organizationId, organizationId), eq(member.userId, removedBy))) - .limit(1) - - if (removerMemberRecord.length === 0) { - return { canRemove: false, reason: 'You are not a member of this organization' } - } - - const removerRole = removerMemberRecord[0].role - const targetRole = memberRecord[0].role - - if (removerRole === 'owner') { - return userIdToRemove === removedBy - ? { canRemove: false, reason: 'Cannot remove yourself as owner' } - : { canRemove: true } - } - - if (removerRole === 'admin') { - return targetRole === 'member' - ? { canRemove: true } - : { canRemove: false, reason: 'Insufficient permissions to remove this member' } - } - - return { canRemove: false, reason: 'Insufficient permissions' } - } catch (error) { - logger.error('Failed to validate member removal', { - organizationId, - userIdToRemove, - removedBy, - error, - }) - - return { canRemove: false, reason: 'Validation failed' } - } -} - /** * Get seat usage analytics for an organization */ diff --git a/apps/sim/lib/billing/webhooks/invoices.ts b/apps/sim/lib/billing/webhooks/invoices.ts index 5c95b4be81..9d39d8817c 100644 --- a/apps/sim/lib/billing/webhooks/invoices.ts +++ b/apps/sim/lib/billing/webhooks/invoices.ts @@ -1,6 +1,12 @@ import { render } from '@react-email/components' import { db } from '@sim/db' -import { member, subscription as subscriptionTable, user, userStats } from '@sim/db/schema' +import { + member, + organization, + subscription as subscriptionTable, + user, + userStats, +} from '@sim/db/schema' import { and, eq, inArray } from 'drizzle-orm' import type Stripe from 'stripe' import PaymentFailedEmail from '@/components/emails/billing/payment-failed-email' @@ -291,6 +297,11 @@ export async function resetUsageForSubscription(sub: { plan: string | null; refe .where(eq(userStats.userId, m.userId)) } } + + await db + .update(organization) + .set({ departedMemberUsage: '0' }) + .where(eq(organization.id, sub.referenceId)) } else { const currentStats = await db .select({ diff --git a/packages/db/migrations/0114_wise_sunfire.sql b/packages/db/migrations/0114_wise_sunfire.sql new file mode 100644 index 0000000000..8d12ba0bf6 --- /dev/null +++ b/packages/db/migrations/0114_wise_sunfire.sql @@ -0,0 +1 @@ +ALTER TABLE "organization" ADD COLUMN "departed_member_usage" numeric DEFAULT '0' NOT NULL; \ No newline at end of file diff --git a/packages/db/migrations/meta/0114_snapshot.json b/packages/db/migrations/meta/0114_snapshot.json new file mode 100644 index 0000000000..0c0d06be62 --- /dev/null +++ b/packages/db/migrations/meta/0114_snapshot.json @@ -0,0 +1,7695 @@ +{ + "id": "eaeb84c0-4e54-4530-afb5-66ee0f62e163", + "prevId": "c3af7fcc-69b0-4fa5-843c-b8313e0d1212", + "version": "7", + "dialect": "postgresql", + "tables": { + "public.account": { + "name": "account", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "account_id": { + "name": "account_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "provider_id": { + "name": "provider_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "access_token": { + "name": "access_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "refresh_token": { + "name": "refresh_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "id_token": { + "name": "id_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "access_token_expires_at": { + "name": "access_token_expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "refresh_token_expires_at": { + "name": "refresh_token_expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "scope": { + "name": "scope", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "password": { + "name": "password", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "account_user_id_idx": { + "name": "account_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_account_on_account_id_provider_id": { + "name": "idx_account_on_account_id_provider_id", + "columns": [ + { + "expression": "account_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "provider_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "account_user_id_user_id_fk": { + "name": "account_user_id_user_id_fk", + "tableFrom": "account", + "tableTo": "user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.api_key": { + "name": "api_key", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_by": { + "name": "created_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'personal'" + }, + "last_used": { + "name": "last_used", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "api_key_user_id_user_id_fk": { + "name": "api_key_user_id_user_id_fk", + "tableFrom": "api_key", + "tableTo": "user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "api_key_workspace_id_workspace_id_fk": { + "name": "api_key_workspace_id_workspace_id_fk", + "tableFrom": "api_key", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "api_key_created_by_user_id_fk": { + "name": "api_key_created_by_user_id_fk", + "tableFrom": "api_key", + "tableTo": "user", + "columnsFrom": ["created_by"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "api_key_key_unique": { + "name": "api_key_key_unique", + "nullsNotDistinct": false, + "columns": ["key"] + } + }, + "policies": {}, + "checkConstraints": { + "workspace_type_check": { + "name": "workspace_type_check", + "value": "(type = 'workspace' AND workspace_id IS NOT NULL) OR (type = 'personal' AND workspace_id IS NULL)" + } + }, + "isRLSEnabled": false + }, + "public.chat": { + "name": "chat", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "identifier": { + "name": "identifier", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "is_active": { + "name": "is_active", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "customizations": { + "name": "customizations", + "type": "json", + "primaryKey": false, + "notNull": false, + "default": "'{}'" + }, + "auth_type": { + "name": "auth_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'public'" + }, + "password": { + "name": "password", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "allowed_emails": { + "name": "allowed_emails", + "type": "json", + "primaryKey": false, + "notNull": false, + "default": "'[]'" + }, + "output_configs": { + "name": "output_configs", + "type": "json", + "primaryKey": false, + "notNull": false, + "default": "'[]'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "identifier_idx": { + "name": "identifier_idx", + "columns": [ + { + "expression": "identifier", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "chat_workflow_id_workflow_id_fk": { + "name": "chat_workflow_id_workflow_id_fk", + "tableFrom": "chat", + "tableTo": "workflow", + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "chat_user_id_user_id_fk": { + "name": "chat_user_id_user_id_fk", + "tableFrom": "chat", + "tableTo": "user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.copilot_chats": { + "name": "copilot_chats", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "messages": { + "name": "messages", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'[]'" + }, + "model": { + "name": "model", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'claude-3-7-sonnet-latest'" + }, + "conversation_id": { + "name": "conversation_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "preview_yaml": { + "name": "preview_yaml", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "plan_artifact": { + "name": "plan_artifact", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "config": { + "name": "config", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "copilot_chats_user_id_idx": { + "name": "copilot_chats_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "copilot_chats_workflow_id_idx": { + "name": "copilot_chats_workflow_id_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "copilot_chats_user_workflow_idx": { + "name": "copilot_chats_user_workflow_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "copilot_chats_created_at_idx": { + "name": "copilot_chats_created_at_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "copilot_chats_updated_at_idx": { + "name": "copilot_chats_updated_at_idx", + "columns": [ + { + "expression": "updated_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "copilot_chats_user_id_user_id_fk": { + "name": "copilot_chats_user_id_user_id_fk", + "tableFrom": "copilot_chats", + "tableTo": "user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "copilot_chats_workflow_id_workflow_id_fk": { + "name": "copilot_chats_workflow_id_workflow_id_fk", + "tableFrom": "copilot_chats", + "tableTo": "workflow", + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.copilot_feedback": { + "name": "copilot_feedback", + "schema": "", + "columns": { + "feedback_id": { + "name": "feedback_id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "chat_id": { + "name": "chat_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "user_query": { + "name": "user_query", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "agent_response": { + "name": "agent_response", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "is_positive": { + "name": "is_positive", + "type": "boolean", + "primaryKey": false, + "notNull": true + }, + "feedback": { + "name": "feedback", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "workflow_yaml": { + "name": "workflow_yaml", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "copilot_feedback_user_id_idx": { + "name": "copilot_feedback_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "copilot_feedback_chat_id_idx": { + "name": "copilot_feedback_chat_id_idx", + "columns": [ + { + "expression": "chat_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "copilot_feedback_user_chat_idx": { + "name": "copilot_feedback_user_chat_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "chat_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "copilot_feedback_is_positive_idx": { + "name": "copilot_feedback_is_positive_idx", + "columns": [ + { + "expression": "is_positive", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "copilot_feedback_created_at_idx": { + "name": "copilot_feedback_created_at_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "copilot_feedback_user_id_user_id_fk": { + "name": "copilot_feedback_user_id_user_id_fk", + "tableFrom": "copilot_feedback", + "tableTo": "user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "copilot_feedback_chat_id_copilot_chats_id_fk": { + "name": "copilot_feedback_chat_id_copilot_chats_id_fk", + "tableFrom": "copilot_feedback", + "tableTo": "copilot_chats", + "columnsFrom": ["chat_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.custom_tools": { + "name": "custom_tools", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "schema": { + "name": "schema", + "type": "json", + "primaryKey": false, + "notNull": true + }, + "code": { + "name": "code", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "custom_tools_workspace_id_idx": { + "name": "custom_tools_workspace_id_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "custom_tools_workspace_title_unique": { + "name": "custom_tools_workspace_title_unique", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "title", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "custom_tools_workspace_id_workspace_id_fk": { + "name": "custom_tools_workspace_id_workspace_id_fk", + "tableFrom": "custom_tools", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "custom_tools_user_id_user_id_fk": { + "name": "custom_tools_user_id_user_id_fk", + "tableFrom": "custom_tools", + "tableTo": "user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.docs_embeddings": { + "name": "docs_embeddings", + "schema": "", + "columns": { + "chunk_id": { + "name": "chunk_id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "chunk_text": { + "name": "chunk_text", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "source_document": { + "name": "source_document", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "source_link": { + "name": "source_link", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "header_text": { + "name": "header_text", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "header_level": { + "name": "header_level", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "token_count": { + "name": "token_count", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "embedding": { + "name": "embedding", + "type": "vector(1536)", + "primaryKey": false, + "notNull": true + }, + "embedding_model": { + "name": "embedding_model", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'text-embedding-3-small'" + }, + "metadata": { + "name": "metadata", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "chunk_text_tsv": { + "name": "chunk_text_tsv", + "type": "tsvector", + "primaryKey": false, + "notNull": false, + "generated": { + "as": "to_tsvector('english', \"docs_embeddings\".\"chunk_text\")", + "type": "stored" + } + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "docs_emb_source_document_idx": { + "name": "docs_emb_source_document_idx", + "columns": [ + { + "expression": "source_document", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "docs_emb_header_level_idx": { + "name": "docs_emb_header_level_idx", + "columns": [ + { + "expression": "header_level", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "docs_emb_source_header_idx": { + "name": "docs_emb_source_header_idx", + "columns": [ + { + "expression": "source_document", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "header_level", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "docs_emb_model_idx": { + "name": "docs_emb_model_idx", + "columns": [ + { + "expression": "embedding_model", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "docs_emb_created_at_idx": { + "name": "docs_emb_created_at_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "docs_embedding_vector_hnsw_idx": { + "name": "docs_embedding_vector_hnsw_idx", + "columns": [ + { + "expression": "embedding", + "isExpression": false, + "asc": true, + "nulls": "last", + "opclass": "vector_cosine_ops" + } + ], + "isUnique": false, + "concurrently": false, + "method": "hnsw", + "with": { + "m": 16, + "ef_construction": 64 + } + }, + "docs_emb_metadata_gin_idx": { + "name": "docs_emb_metadata_gin_idx", + "columns": [ + { + "expression": "metadata", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "gin", + "with": {} + }, + "docs_emb_chunk_text_fts_idx": { + "name": "docs_emb_chunk_text_fts_idx", + "columns": [ + { + "expression": "chunk_text_tsv", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "gin", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "docs_embedding_not_null_check": { + "name": "docs_embedding_not_null_check", + "value": "\"embedding\" IS NOT NULL" + }, + "docs_header_level_check": { + "name": "docs_header_level_check", + "value": "\"header_level\" >= 1 AND \"header_level\" <= 6" + } + }, + "isRLSEnabled": false + }, + "public.document": { + "name": "document", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "knowledge_base_id": { + "name": "knowledge_base_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "filename": { + "name": "filename", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "file_url": { + "name": "file_url", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "file_size": { + "name": "file_size", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "mime_type": { + "name": "mime_type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "chunk_count": { + "name": "chunk_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "token_count": { + "name": "token_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "character_count": { + "name": "character_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "processing_status": { + "name": "processing_status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "processing_started_at": { + "name": "processing_started_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "processing_completed_at": { + "name": "processing_completed_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "processing_error": { + "name": "processing_error", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "enabled": { + "name": "enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "deleted_at": { + "name": "deleted_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "tag1": { + "name": "tag1", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tag2": { + "name": "tag2", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tag3": { + "name": "tag3", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tag4": { + "name": "tag4", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tag5": { + "name": "tag5", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tag6": { + "name": "tag6", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tag7": { + "name": "tag7", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "uploaded_at": { + "name": "uploaded_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "doc_kb_id_idx": { + "name": "doc_kb_id_idx", + "columns": [ + { + "expression": "knowledge_base_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "doc_filename_idx": { + "name": "doc_filename_idx", + "columns": [ + { + "expression": "filename", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "doc_processing_status_idx": { + "name": "doc_processing_status_idx", + "columns": [ + { + "expression": "knowledge_base_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "processing_status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "doc_tag1_idx": { + "name": "doc_tag1_idx", + "columns": [ + { + "expression": "tag1", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "doc_tag2_idx": { + "name": "doc_tag2_idx", + "columns": [ + { + "expression": "tag2", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "doc_tag3_idx": { + "name": "doc_tag3_idx", + "columns": [ + { + "expression": "tag3", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "doc_tag4_idx": { + "name": "doc_tag4_idx", + "columns": [ + { + "expression": "tag4", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "doc_tag5_idx": { + "name": "doc_tag5_idx", + "columns": [ + { + "expression": "tag5", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "doc_tag6_idx": { + "name": "doc_tag6_idx", + "columns": [ + { + "expression": "tag6", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "doc_tag7_idx": { + "name": "doc_tag7_idx", + "columns": [ + { + "expression": "tag7", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "document_knowledge_base_id_knowledge_base_id_fk": { + "name": "document_knowledge_base_id_knowledge_base_id_fk", + "tableFrom": "document", + "tableTo": "knowledge_base", + "columnsFrom": ["knowledge_base_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.embedding": { + "name": "embedding", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "knowledge_base_id": { + "name": "knowledge_base_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "document_id": { + "name": "document_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "chunk_index": { + "name": "chunk_index", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "chunk_hash": { + "name": "chunk_hash", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "content": { + "name": "content", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "content_length": { + "name": "content_length", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "token_count": { + "name": "token_count", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "embedding": { + "name": "embedding", + "type": "vector(1536)", + "primaryKey": false, + "notNull": false + }, + "embedding_model": { + "name": "embedding_model", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'text-embedding-3-small'" + }, + "start_offset": { + "name": "start_offset", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "end_offset": { + "name": "end_offset", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "tag1": { + "name": "tag1", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tag2": { + "name": "tag2", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tag3": { + "name": "tag3", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tag4": { + "name": "tag4", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tag5": { + "name": "tag5", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tag6": { + "name": "tag6", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tag7": { + "name": "tag7", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "enabled": { + "name": "enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "content_tsv": { + "name": "content_tsv", + "type": "tsvector", + "primaryKey": false, + "notNull": false, + "generated": { + "as": "to_tsvector('english', \"embedding\".\"content\")", + "type": "stored" + } + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "emb_kb_id_idx": { + "name": "emb_kb_id_idx", + "columns": [ + { + "expression": "knowledge_base_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "emb_doc_id_idx": { + "name": "emb_doc_id_idx", + "columns": [ + { + "expression": "document_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "emb_doc_chunk_idx": { + "name": "emb_doc_chunk_idx", + "columns": [ + { + "expression": "document_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "chunk_index", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "emb_kb_model_idx": { + "name": "emb_kb_model_idx", + "columns": [ + { + "expression": "knowledge_base_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "embedding_model", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "emb_kb_enabled_idx": { + "name": "emb_kb_enabled_idx", + "columns": [ + { + "expression": "knowledge_base_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "enabled", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "emb_doc_enabled_idx": { + "name": "emb_doc_enabled_idx", + "columns": [ + { + "expression": "document_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "enabled", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "embedding_vector_hnsw_idx": { + "name": "embedding_vector_hnsw_idx", + "columns": [ + { + "expression": "embedding", + "isExpression": false, + "asc": true, + "nulls": "last", + "opclass": "vector_cosine_ops" + } + ], + "isUnique": false, + "concurrently": false, + "method": "hnsw", + "with": { + "m": 16, + "ef_construction": 64 + } + }, + "emb_tag1_idx": { + "name": "emb_tag1_idx", + "columns": [ + { + "expression": "tag1", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "emb_tag2_idx": { + "name": "emb_tag2_idx", + "columns": [ + { + "expression": "tag2", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "emb_tag3_idx": { + "name": "emb_tag3_idx", + "columns": [ + { + "expression": "tag3", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "emb_tag4_idx": { + "name": "emb_tag4_idx", + "columns": [ + { + "expression": "tag4", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "emb_tag5_idx": { + "name": "emb_tag5_idx", + "columns": [ + { + "expression": "tag5", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "emb_tag6_idx": { + "name": "emb_tag6_idx", + "columns": [ + { + "expression": "tag6", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "emb_tag7_idx": { + "name": "emb_tag7_idx", + "columns": [ + { + "expression": "tag7", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "emb_content_fts_idx": { + "name": "emb_content_fts_idx", + "columns": [ + { + "expression": "content_tsv", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "gin", + "with": {} + } + }, + "foreignKeys": { + "embedding_knowledge_base_id_knowledge_base_id_fk": { + "name": "embedding_knowledge_base_id_knowledge_base_id_fk", + "tableFrom": "embedding", + "tableTo": "knowledge_base", + "columnsFrom": ["knowledge_base_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "embedding_document_id_document_id_fk": { + "name": "embedding_document_id_document_id_fk", + "tableFrom": "embedding", + "tableTo": "document", + "columnsFrom": ["document_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "embedding_not_null_check": { + "name": "embedding_not_null_check", + "value": "\"embedding\" IS NOT NULL" + } + }, + "isRLSEnabled": false + }, + "public.environment": { + "name": "environment", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "variables": { + "name": "variables", + "type": "json", + "primaryKey": false, + "notNull": true + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "environment_user_id_user_id_fk": { + "name": "environment_user_id_user_id_fk", + "tableFrom": "environment", + "tableTo": "user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "environment_user_id_unique": { + "name": "environment_user_id_unique", + "nullsNotDistinct": false, + "columns": ["user_id"] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.idempotency_key": { + "name": "idempotency_key", + "schema": "", + "columns": { + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "namespace": { + "name": "namespace", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'default'" + }, + "result": { + "name": "result", + "type": "json", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "idempotency_key_namespace_unique": { + "name": "idempotency_key_namespace_unique", + "columns": [ + { + "expression": "key", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "namespace", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idempotency_key_created_at_idx": { + "name": "idempotency_key_created_at_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idempotency_key_namespace_idx": { + "name": "idempotency_key_namespace_idx", + "columns": [ + { + "expression": "namespace", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.invitation": { + "name": "invitation", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "inviter_id": { + "name": "inviter_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "invitation_email_idx": { + "name": "invitation_email_idx", + "columns": [ + { + "expression": "email", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "invitation_organization_id_idx": { + "name": "invitation_organization_id_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "invitation_inviter_id_user_id_fk": { + "name": "invitation_inviter_id_user_id_fk", + "tableFrom": "invitation", + "tableTo": "user", + "columnsFrom": ["inviter_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "invitation_organization_id_organization_id_fk": { + "name": "invitation_organization_id_organization_id_fk", + "tableFrom": "invitation", + "tableTo": "organization", + "columnsFrom": ["organization_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.knowledge_base": { + "name": "knowledge_base", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "token_count": { + "name": "token_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "embedding_model": { + "name": "embedding_model", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'text-embedding-3-small'" + }, + "embedding_dimension": { + "name": "embedding_dimension", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 1536 + }, + "chunking_config": { + "name": "chunking_config", + "type": "json", + "primaryKey": false, + "notNull": true, + "default": "'{\"maxSize\": 1024, \"minSize\": 1, \"overlap\": 200}'" + }, + "deleted_at": { + "name": "deleted_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "kb_user_id_idx": { + "name": "kb_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "kb_workspace_id_idx": { + "name": "kb_workspace_id_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "kb_user_workspace_idx": { + "name": "kb_user_workspace_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "kb_deleted_at_idx": { + "name": "kb_deleted_at_idx", + "columns": [ + { + "expression": "deleted_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "knowledge_base_user_id_user_id_fk": { + "name": "knowledge_base_user_id_user_id_fk", + "tableFrom": "knowledge_base", + "tableTo": "user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "knowledge_base_workspace_id_workspace_id_fk": { + "name": "knowledge_base_workspace_id_workspace_id_fk", + "tableFrom": "knowledge_base", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.knowledge_base_tag_definitions": { + "name": "knowledge_base_tag_definitions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "knowledge_base_id": { + "name": "knowledge_base_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "tag_slot": { + "name": "tag_slot", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "display_name": { + "name": "display_name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "field_type": { + "name": "field_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'text'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "kb_tag_definitions_kb_slot_idx": { + "name": "kb_tag_definitions_kb_slot_idx", + "columns": [ + { + "expression": "knowledge_base_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "tag_slot", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "kb_tag_definitions_kb_display_name_idx": { + "name": "kb_tag_definitions_kb_display_name_idx", + "columns": [ + { + "expression": "knowledge_base_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "display_name", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "kb_tag_definitions_kb_id_idx": { + "name": "kb_tag_definitions_kb_id_idx", + "columns": [ + { + "expression": "knowledge_base_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "knowledge_base_tag_definitions_knowledge_base_id_knowledge_base_id_fk": { + "name": "knowledge_base_tag_definitions_knowledge_base_id_knowledge_base_id_fk", + "tableFrom": "knowledge_base_tag_definitions", + "tableTo": "knowledge_base", + "columnsFrom": ["knowledge_base_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.marketplace": { + "name": "marketplace", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "state": { + "name": "state", + "type": "json", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "author_id": { + "name": "author_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "author_name": { + "name": "author_name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "views": { + "name": "views", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "category": { + "name": "category", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "marketplace_workflow_id_workflow_id_fk": { + "name": "marketplace_workflow_id_workflow_id_fk", + "tableFrom": "marketplace", + "tableTo": "workflow", + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "marketplace_author_id_user_id_fk": { + "name": "marketplace_author_id_user_id_fk", + "tableFrom": "marketplace", + "tableTo": "user", + "columnsFrom": ["author_id"], + "columnsTo": ["id"], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.mcp_servers": { + "name": "mcp_servers", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_by": { + "name": "created_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "transport": { + "name": "transport", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "url": { + "name": "url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "headers": { + "name": "headers", + "type": "json", + "primaryKey": false, + "notNull": false, + "default": "'{}'" + }, + "timeout": { + "name": "timeout", + "type": "integer", + "primaryKey": false, + "notNull": false, + "default": 30000 + }, + "retries": { + "name": "retries", + "type": "integer", + "primaryKey": false, + "notNull": false, + "default": 3 + }, + "enabled": { + "name": "enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "last_connected": { + "name": "last_connected", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "connection_status": { + "name": "connection_status", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "'disconnected'" + }, + "last_error": { + "name": "last_error", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tool_count": { + "name": "tool_count", + "type": "integer", + "primaryKey": false, + "notNull": false, + "default": 0 + }, + "last_tools_refresh": { + "name": "last_tools_refresh", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "total_requests": { + "name": "total_requests", + "type": "integer", + "primaryKey": false, + "notNull": false, + "default": 0 + }, + "last_used": { + "name": "last_used", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "deleted_at": { + "name": "deleted_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "mcp_servers_workspace_enabled_idx": { + "name": "mcp_servers_workspace_enabled_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "enabled", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "mcp_servers_workspace_deleted_idx": { + "name": "mcp_servers_workspace_deleted_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "deleted_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "mcp_servers_workspace_id_workspace_id_fk": { + "name": "mcp_servers_workspace_id_workspace_id_fk", + "tableFrom": "mcp_servers", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "mcp_servers_created_by_user_id_fk": { + "name": "mcp_servers_created_by_user_id_fk", + "tableFrom": "mcp_servers", + "tableTo": "user", + "columnsFrom": ["created_by"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.member": { + "name": "member", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "member_user_id_idx": { + "name": "member_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "member_organization_id_idx": { + "name": "member_organization_id_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "member_user_id_user_id_fk": { + "name": "member_user_id_user_id_fk", + "tableFrom": "member", + "tableTo": "user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "member_organization_id_organization_id_fk": { + "name": "member_organization_id_organization_id_fk", + "tableFrom": "member", + "tableTo": "organization", + "columnsFrom": ["organization_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.memory": { + "name": "memory", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "data": { + "name": "data", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "deleted_at": { + "name": "deleted_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "memory_key_idx": { + "name": "memory_key_idx", + "columns": [ + { + "expression": "key", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "memory_workflow_idx": { + "name": "memory_workflow_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "memory_workflow_key_idx": { + "name": "memory_workflow_key_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "key", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "memory_workflow_id_workflow_id_fk": { + "name": "memory_workflow_id_workflow_id_fk", + "tableFrom": "memory", + "tableTo": "workflow", + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.organization": { + "name": "organization", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "slug": { + "name": "slug", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "logo": { + "name": "logo", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "metadata": { + "name": "metadata", + "type": "json", + "primaryKey": false, + "notNull": false + }, + "org_usage_limit": { + "name": "org_usage_limit", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "storage_used_bytes": { + "name": "storage_used_bytes", + "type": "bigint", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "departed_member_usage": { + "name": "departed_member_usage", + "type": "numeric", + "primaryKey": false, + "notNull": true, + "default": "'0'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.paused_executions": { + "name": "paused_executions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "execution_id": { + "name": "execution_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "execution_snapshot": { + "name": "execution_snapshot", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "pause_points": { + "name": "pause_points", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "total_pause_count": { + "name": "total_pause_count", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "resumed_count": { + "name": "resumed_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'paused'" + }, + "metadata": { + "name": "metadata", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'::jsonb" + }, + "paused_at": { + "name": "paused_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "paused_executions_workflow_id_idx": { + "name": "paused_executions_workflow_id_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "paused_executions_status_idx": { + "name": "paused_executions_status_idx", + "columns": [ + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "paused_executions_execution_id_unique": { + "name": "paused_executions_execution_id_unique", + "columns": [ + { + "expression": "execution_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "paused_executions_workflow_id_workflow_id_fk": { + "name": "paused_executions_workflow_id_workflow_id_fk", + "tableFrom": "paused_executions", + "tableTo": "workflow", + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.permissions": { + "name": "permissions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "entity_type": { + "name": "entity_type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "entity_id": { + "name": "entity_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "permission_type": { + "name": "permission_type", + "type": "permission_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "permissions_user_id_idx": { + "name": "permissions_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "permissions_entity_idx": { + "name": "permissions_entity_idx", + "columns": [ + { + "expression": "entity_type", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "entity_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "permissions_user_entity_type_idx": { + "name": "permissions_user_entity_type_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "entity_type", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "permissions_user_entity_permission_idx": { + "name": "permissions_user_entity_permission_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "entity_type", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "permission_type", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "permissions_user_entity_idx": { + "name": "permissions_user_entity_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "entity_type", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "entity_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "permissions_unique_constraint": { + "name": "permissions_unique_constraint", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "entity_type", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "entity_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "permissions_user_id_user_id_fk": { + "name": "permissions_user_id_user_id_fk", + "tableFrom": "permissions", + "tableTo": "user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.resume_queue": { + "name": "resume_queue", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "paused_execution_id": { + "name": "paused_execution_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "parent_execution_id": { + "name": "parent_execution_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "new_execution_id": { + "name": "new_execution_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "context_id": { + "name": "context_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "resume_input": { + "name": "resume_input", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "queued_at": { + "name": "queued_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "claimed_at": { + "name": "claimed_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "completed_at": { + "name": "completed_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "failure_reason": { + "name": "failure_reason", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "resume_queue_parent_status_idx": { + "name": "resume_queue_parent_status_idx", + "columns": [ + { + "expression": "parent_execution_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "queued_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "resume_queue_new_execution_idx": { + "name": "resume_queue_new_execution_idx", + "columns": [ + { + "expression": "new_execution_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "resume_queue_paused_execution_id_paused_executions_id_fk": { + "name": "resume_queue_paused_execution_id_paused_executions_id_fk", + "tableFrom": "resume_queue", + "tableTo": "paused_executions", + "columnsFrom": ["paused_execution_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.session": { + "name": "session", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "token": { + "name": "token", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "ip_address": { + "name": "ip_address", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_agent": { + "name": "user_agent", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "active_organization_id": { + "name": "active_organization_id", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "session_user_id_idx": { + "name": "session_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "session_token_idx": { + "name": "session_token_idx", + "columns": [ + { + "expression": "token", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "session_user_id_user_id_fk": { + "name": "session_user_id_user_id_fk", + "tableFrom": "session", + "tableTo": "user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "session_active_organization_id_organization_id_fk": { + "name": "session_active_organization_id_organization_id_fk", + "tableFrom": "session", + "tableTo": "organization", + "columnsFrom": ["active_organization_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "session_token_unique": { + "name": "session_token_unique", + "nullsNotDistinct": false, + "columns": ["token"] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.settings": { + "name": "settings", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "theme": { + "name": "theme", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'system'" + }, + "auto_connect": { + "name": "auto_connect", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "auto_pan": { + "name": "auto_pan", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "console_expanded_by_default": { + "name": "console_expanded_by_default", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "telemetry_enabled": { + "name": "telemetry_enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "email_preferences": { + "name": "email_preferences", + "type": "json", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "billing_usage_notifications_enabled": { + "name": "billing_usage_notifications_enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "show_floating_controls": { + "name": "show_floating_controls", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "show_training_controls": { + "name": "show_training_controls", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "super_user_mode_enabled": { + "name": "super_user_mode_enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "error_notifications_enabled": { + "name": "error_notifications_enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "copilot_enabled_models": { + "name": "copilot_enabled_models", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "settings_user_id_user_id_fk": { + "name": "settings_user_id_user_id_fk", + "tableFrom": "settings", + "tableTo": "user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "settings_user_id_unique": { + "name": "settings_user_id_unique", + "nullsNotDistinct": false, + "columns": ["user_id"] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.sso_provider": { + "name": "sso_provider", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "issuer": { + "name": "issuer", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "domain": { + "name": "domain", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "oidc_config": { + "name": "oidc_config", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "saml_config": { + "name": "saml_config", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "provider_id": { + "name": "provider_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "sso_provider_provider_id_idx": { + "name": "sso_provider_provider_id_idx", + "columns": [ + { + "expression": "provider_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "sso_provider_domain_idx": { + "name": "sso_provider_domain_idx", + "columns": [ + { + "expression": "domain", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "sso_provider_user_id_idx": { + "name": "sso_provider_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "sso_provider_organization_id_idx": { + "name": "sso_provider_organization_id_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "sso_provider_user_id_user_id_fk": { + "name": "sso_provider_user_id_user_id_fk", + "tableFrom": "sso_provider", + "tableTo": "user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "sso_provider_organization_id_organization_id_fk": { + "name": "sso_provider_organization_id_organization_id_fk", + "tableFrom": "sso_provider", + "tableTo": "organization", + "columnsFrom": ["organization_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.subscription": { + "name": "subscription", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "plan": { + "name": "plan", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "reference_id": { + "name": "reference_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "stripe_customer_id": { + "name": "stripe_customer_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "stripe_subscription_id": { + "name": "stripe_subscription_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "period_start": { + "name": "period_start", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "period_end": { + "name": "period_end", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "cancel_at_period_end": { + "name": "cancel_at_period_end", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "seats": { + "name": "seats", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "trial_start": { + "name": "trial_start", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "trial_end": { + "name": "trial_end", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "metadata": { + "name": "metadata", + "type": "json", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "subscription_reference_status_idx": { + "name": "subscription_reference_status_idx", + "columns": [ + { + "expression": "reference_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "check_enterprise_metadata": { + "name": "check_enterprise_metadata", + "value": "plan != 'enterprise' OR metadata IS NOT NULL" + } + }, + "isRLSEnabled": false + }, + "public.template_creators": { + "name": "template_creators", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "reference_type": { + "name": "reference_type", + "type": "template_creator_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "reference_id": { + "name": "reference_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "profile_image_url": { + "name": "profile_image_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "details": { + "name": "details", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "created_by": { + "name": "created_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "template_creators_reference_idx": { + "name": "template_creators_reference_idx", + "columns": [ + { + "expression": "reference_type", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "reference_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "template_creators_reference_id_idx": { + "name": "template_creators_reference_id_idx", + "columns": [ + { + "expression": "reference_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "template_creators_created_by_idx": { + "name": "template_creators_created_by_idx", + "columns": [ + { + "expression": "created_by", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "template_creators_created_by_user_id_fk": { + "name": "template_creators_created_by_user_id_fk", + "tableFrom": "template_creators", + "tableTo": "user", + "columnsFrom": ["created_by"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.template_stars": { + "name": "template_stars", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "template_id": { + "name": "template_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "starred_at": { + "name": "starred_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "template_stars_user_id_idx": { + "name": "template_stars_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "template_stars_template_id_idx": { + "name": "template_stars_template_id_idx", + "columns": [ + { + "expression": "template_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "template_stars_user_template_idx": { + "name": "template_stars_user_template_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "template_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "template_stars_template_user_idx": { + "name": "template_stars_template_user_idx", + "columns": [ + { + "expression": "template_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "template_stars_starred_at_idx": { + "name": "template_stars_starred_at_idx", + "columns": [ + { + "expression": "starred_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "template_stars_template_starred_at_idx": { + "name": "template_stars_template_starred_at_idx", + "columns": [ + { + "expression": "template_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "starred_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "template_stars_user_template_unique": { + "name": "template_stars_user_template_unique", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "template_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "template_stars_user_id_user_id_fk": { + "name": "template_stars_user_id_user_id_fk", + "tableFrom": "template_stars", + "tableTo": "user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "template_stars_template_id_templates_id_fk": { + "name": "template_stars_template_id_templates_id_fk", + "tableFrom": "template_stars", + "tableTo": "templates", + "columnsFrom": ["template_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.templates": { + "name": "templates", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "details": { + "name": "details", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "creator_id": { + "name": "creator_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "views": { + "name": "views", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "stars": { + "name": "stars", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "status": { + "name": "status", + "type": "template_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "tags": { + "name": "tags", + "type": "text[]", + "primaryKey": false, + "notNull": true, + "default": "'{}'::text[]" + }, + "required_credentials": { + "name": "required_credentials", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'[]'" + }, + "state": { + "name": "state", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "templates_status_idx": { + "name": "templates_status_idx", + "columns": [ + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "templates_creator_id_idx": { + "name": "templates_creator_id_idx", + "columns": [ + { + "expression": "creator_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "templates_views_idx": { + "name": "templates_views_idx", + "columns": [ + { + "expression": "views", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "templates_stars_idx": { + "name": "templates_stars_idx", + "columns": [ + { + "expression": "stars", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "templates_status_views_idx": { + "name": "templates_status_views_idx", + "columns": [ + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "views", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "templates_status_stars_idx": { + "name": "templates_status_stars_idx", + "columns": [ + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "stars", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "templates_created_at_idx": { + "name": "templates_created_at_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "templates_updated_at_idx": { + "name": "templates_updated_at_idx", + "columns": [ + { + "expression": "updated_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "templates_workflow_id_workflow_id_fk": { + "name": "templates_workflow_id_workflow_id_fk", + "tableFrom": "templates", + "tableTo": "workflow", + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + }, + "templates_creator_id_template_creators_id_fk": { + "name": "templates_creator_id_template_creators_id_fk", + "tableFrom": "templates", + "tableTo": "template_creators", + "columnsFrom": ["creator_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.user": { + "name": "user", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "email_verified": { + "name": "email_verified", + "type": "boolean", + "primaryKey": false, + "notNull": true + }, + "image": { + "name": "image", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "stripe_customer_id": { + "name": "stripe_customer_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "is_super_user": { + "name": "is_super_user", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "user_email_unique": { + "name": "user_email_unique", + "nullsNotDistinct": false, + "columns": ["email"] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.user_rate_limits": { + "name": "user_rate_limits", + "schema": "", + "columns": { + "reference_id": { + "name": "reference_id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "sync_api_requests": { + "name": "sync_api_requests", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "async_api_requests": { + "name": "async_api_requests", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "api_endpoint_requests": { + "name": "api_endpoint_requests", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "window_start": { + "name": "window_start", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "last_request_at": { + "name": "last_request_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "is_rate_limited": { + "name": "is_rate_limited", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "rate_limit_reset_at": { + "name": "rate_limit_reset_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.user_stats": { + "name": "user_stats", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "total_manual_executions": { + "name": "total_manual_executions", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "total_api_calls": { + "name": "total_api_calls", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "total_webhook_triggers": { + "name": "total_webhook_triggers", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "total_scheduled_executions": { + "name": "total_scheduled_executions", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "total_chat_executions": { + "name": "total_chat_executions", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "total_tokens_used": { + "name": "total_tokens_used", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "total_cost": { + "name": "total_cost", + "type": "numeric", + "primaryKey": false, + "notNull": true, + "default": "'0'" + }, + "current_usage_limit": { + "name": "current_usage_limit", + "type": "numeric", + "primaryKey": false, + "notNull": false, + "default": "'10'" + }, + "usage_limit_updated_at": { + "name": "usage_limit_updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + }, + "current_period_cost": { + "name": "current_period_cost", + "type": "numeric", + "primaryKey": false, + "notNull": true, + "default": "'0'" + }, + "last_period_cost": { + "name": "last_period_cost", + "type": "numeric", + "primaryKey": false, + "notNull": false, + "default": "'0'" + }, + "billed_overage_this_period": { + "name": "billed_overage_this_period", + "type": "numeric", + "primaryKey": false, + "notNull": true, + "default": "'0'" + }, + "pro_period_cost_snapshot": { + "name": "pro_period_cost_snapshot", + "type": "numeric", + "primaryKey": false, + "notNull": false, + "default": "'0'" + }, + "total_copilot_cost": { + "name": "total_copilot_cost", + "type": "numeric", + "primaryKey": false, + "notNull": true, + "default": "'0'" + }, + "current_period_copilot_cost": { + "name": "current_period_copilot_cost", + "type": "numeric", + "primaryKey": false, + "notNull": true, + "default": "'0'" + }, + "last_period_copilot_cost": { + "name": "last_period_copilot_cost", + "type": "numeric", + "primaryKey": false, + "notNull": false, + "default": "'0'" + }, + "total_copilot_tokens": { + "name": "total_copilot_tokens", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "total_copilot_calls": { + "name": "total_copilot_calls", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "storage_used_bytes": { + "name": "storage_used_bytes", + "type": "bigint", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "last_active": { + "name": "last_active", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "billing_blocked": { + "name": "billing_blocked", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + } + }, + "indexes": {}, + "foreignKeys": { + "user_stats_user_id_user_id_fk": { + "name": "user_stats_user_id_user_id_fk", + "tableFrom": "user_stats", + "tableTo": "user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "user_stats_user_id_unique": { + "name": "user_stats_user_id_unique", + "nullsNotDistinct": false, + "columns": ["user_id"] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.verification": { + "name": "verification", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "identifier": { + "name": "identifier", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "verification_identifier_idx": { + "name": "verification_identifier_idx", + "columns": [ + { + "expression": "identifier", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.waitlist": { + "name": "waitlist", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "waitlist_email_unique": { + "name": "waitlist_email_unique", + "nullsNotDistinct": false, + "columns": ["email"] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.webhook": { + "name": "webhook", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "block_id": { + "name": "block_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "path": { + "name": "path", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "provider": { + "name": "provider", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "provider_config": { + "name": "provider_config", + "type": "json", + "primaryKey": false, + "notNull": false + }, + "is_active": { + "name": "is_active", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "failed_count": { + "name": "failed_count", + "type": "integer", + "primaryKey": false, + "notNull": false, + "default": 0 + }, + "last_failed_at": { + "name": "last_failed_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "path_idx": { + "name": "path_idx", + "columns": [ + { + "expression": "path", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_webhook_on_workflow_id_block_id": { + "name": "idx_webhook_on_workflow_id_block_id", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "block_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "webhook_workflow_id_workflow_id_fk": { + "name": "webhook_workflow_id_workflow_id_fk", + "tableFrom": "webhook", + "tableTo": "workflow", + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "webhook_block_id_workflow_blocks_id_fk": { + "name": "webhook_block_id_workflow_blocks_id_fk", + "tableFrom": "webhook", + "tableTo": "workflow_blocks", + "columnsFrom": ["block_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workflow": { + "name": "workflow", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "folder_id": { + "name": "folder_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "color": { + "name": "color", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'#3972F6'" + }, + "last_synced": { + "name": "last_synced", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "is_deployed": { + "name": "is_deployed", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "deployed_at": { + "name": "deployed_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "run_count": { + "name": "run_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "last_run_at": { + "name": "last_run_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "variables": { + "name": "variables", + "type": "json", + "primaryKey": false, + "notNull": false, + "default": "'{}'" + } + }, + "indexes": { + "workflow_user_id_idx": { + "name": "workflow_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_workspace_id_idx": { + "name": "workflow_workspace_id_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_user_workspace_idx": { + "name": "workflow_user_workspace_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workflow_user_id_user_id_fk": { + "name": "workflow_user_id_user_id_fk", + "tableFrom": "workflow", + "tableTo": "user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workflow_workspace_id_workspace_id_fk": { + "name": "workflow_workspace_id_workspace_id_fk", + "tableFrom": "workflow", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workflow_folder_id_workflow_folder_id_fk": { + "name": "workflow_folder_id_workflow_folder_id_fk", + "tableFrom": "workflow", + "tableTo": "workflow_folder", + "columnsFrom": ["folder_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workflow_blocks": { + "name": "workflow_blocks", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "position_x": { + "name": "position_x", + "type": "numeric", + "primaryKey": false, + "notNull": true + }, + "position_y": { + "name": "position_y", + "type": "numeric", + "primaryKey": false, + "notNull": true + }, + "enabled": { + "name": "enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "horizontal_handles": { + "name": "horizontal_handles", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "is_wide": { + "name": "is_wide", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "advanced_mode": { + "name": "advanced_mode", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "trigger_mode": { + "name": "trigger_mode", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "height": { + "name": "height", + "type": "numeric", + "primaryKey": false, + "notNull": true, + "default": "'0'" + }, + "sub_blocks": { + "name": "sub_blocks", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "outputs": { + "name": "outputs", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "data": { + "name": "data", + "type": "jsonb", + "primaryKey": false, + "notNull": false, + "default": "'{}'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workflow_blocks_workflow_id_idx": { + "name": "workflow_blocks_workflow_id_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workflow_blocks_workflow_id_workflow_id_fk": { + "name": "workflow_blocks_workflow_id_workflow_id_fk", + "tableFrom": "workflow_blocks", + "tableTo": "workflow", + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workflow_checkpoints": { + "name": "workflow_checkpoints", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "chat_id": { + "name": "chat_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "message_id": { + "name": "message_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "workflow_state": { + "name": "workflow_state", + "type": "json", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workflow_checkpoints_user_id_idx": { + "name": "workflow_checkpoints_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_checkpoints_workflow_id_idx": { + "name": "workflow_checkpoints_workflow_id_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_checkpoints_chat_id_idx": { + "name": "workflow_checkpoints_chat_id_idx", + "columns": [ + { + "expression": "chat_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_checkpoints_message_id_idx": { + "name": "workflow_checkpoints_message_id_idx", + "columns": [ + { + "expression": "message_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_checkpoints_user_workflow_idx": { + "name": "workflow_checkpoints_user_workflow_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_checkpoints_workflow_chat_idx": { + "name": "workflow_checkpoints_workflow_chat_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "chat_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_checkpoints_created_at_idx": { + "name": "workflow_checkpoints_created_at_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_checkpoints_chat_created_at_idx": { + "name": "workflow_checkpoints_chat_created_at_idx", + "columns": [ + { + "expression": "chat_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workflow_checkpoints_user_id_user_id_fk": { + "name": "workflow_checkpoints_user_id_user_id_fk", + "tableFrom": "workflow_checkpoints", + "tableTo": "user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workflow_checkpoints_workflow_id_workflow_id_fk": { + "name": "workflow_checkpoints_workflow_id_workflow_id_fk", + "tableFrom": "workflow_checkpoints", + "tableTo": "workflow", + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workflow_checkpoints_chat_id_copilot_chats_id_fk": { + "name": "workflow_checkpoints_chat_id_copilot_chats_id_fk", + "tableFrom": "workflow_checkpoints", + "tableTo": "copilot_chats", + "columnsFrom": ["chat_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workflow_deployment_version": { + "name": "workflow_deployment_version", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "version": { + "name": "version", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "state": { + "name": "state", + "type": "json", + "primaryKey": false, + "notNull": true + }, + "is_active": { + "name": "is_active", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "created_by": { + "name": "created_by", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "workflow_deployment_version_workflow_version_unique": { + "name": "workflow_deployment_version_workflow_version_unique", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "version", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_deployment_version_workflow_active_idx": { + "name": "workflow_deployment_version_workflow_active_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "is_active", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_deployment_version_created_at_idx": { + "name": "workflow_deployment_version_created_at_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workflow_deployment_version_workflow_id_workflow_id_fk": { + "name": "workflow_deployment_version_workflow_id_workflow_id_fk", + "tableFrom": "workflow_deployment_version", + "tableTo": "workflow", + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workflow_edges": { + "name": "workflow_edges", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "source_block_id": { + "name": "source_block_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "target_block_id": { + "name": "target_block_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "source_handle": { + "name": "source_handle", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "target_handle": { + "name": "target_handle", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workflow_edges_workflow_id_idx": { + "name": "workflow_edges_workflow_id_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_edges_workflow_source_idx": { + "name": "workflow_edges_workflow_source_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "source_block_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_edges_workflow_target_idx": { + "name": "workflow_edges_workflow_target_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "target_block_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workflow_edges_workflow_id_workflow_id_fk": { + "name": "workflow_edges_workflow_id_workflow_id_fk", + "tableFrom": "workflow_edges", + "tableTo": "workflow", + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workflow_edges_source_block_id_workflow_blocks_id_fk": { + "name": "workflow_edges_source_block_id_workflow_blocks_id_fk", + "tableFrom": "workflow_edges", + "tableTo": "workflow_blocks", + "columnsFrom": ["source_block_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workflow_edges_target_block_id_workflow_blocks_id_fk": { + "name": "workflow_edges_target_block_id_workflow_blocks_id_fk", + "tableFrom": "workflow_edges", + "tableTo": "workflow_blocks", + "columnsFrom": ["target_block_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workflow_execution_logs": { + "name": "workflow_execution_logs", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "execution_id": { + "name": "execution_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "state_snapshot_id": { + "name": "state_snapshot_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "level": { + "name": "level", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "trigger": { + "name": "trigger", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "started_at": { + "name": "started_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "ended_at": { + "name": "ended_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "total_duration_ms": { + "name": "total_duration_ms", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "execution_data": { + "name": "execution_data", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "cost": { + "name": "cost", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "files": { + "name": "files", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workflow_execution_logs_workflow_id_idx": { + "name": "workflow_execution_logs_workflow_id_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_execution_logs_state_snapshot_id_idx": { + "name": "workflow_execution_logs_state_snapshot_id_idx", + "columns": [ + { + "expression": "state_snapshot_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_execution_logs_trigger_idx": { + "name": "workflow_execution_logs_trigger_idx", + "columns": [ + { + "expression": "trigger", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_execution_logs_level_idx": { + "name": "workflow_execution_logs_level_idx", + "columns": [ + { + "expression": "level", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_execution_logs_started_at_idx": { + "name": "workflow_execution_logs_started_at_idx", + "columns": [ + { + "expression": "started_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_execution_logs_execution_id_unique": { + "name": "workflow_execution_logs_execution_id_unique", + "columns": [ + { + "expression": "execution_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_execution_logs_workflow_started_at_idx": { + "name": "workflow_execution_logs_workflow_started_at_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "started_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workflow_execution_logs_workflow_id_workflow_id_fk": { + "name": "workflow_execution_logs_workflow_id_workflow_id_fk", + "tableFrom": "workflow_execution_logs", + "tableTo": "workflow", + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workflow_execution_logs_state_snapshot_id_workflow_execution_snapshots_id_fk": { + "name": "workflow_execution_logs_state_snapshot_id_workflow_execution_snapshots_id_fk", + "tableFrom": "workflow_execution_logs", + "tableTo": "workflow_execution_snapshots", + "columnsFrom": ["state_snapshot_id"], + "columnsTo": ["id"], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workflow_execution_snapshots": { + "name": "workflow_execution_snapshots", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "state_hash": { + "name": "state_hash", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "state_data": { + "name": "state_data", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workflow_snapshots_workflow_id_idx": { + "name": "workflow_snapshots_workflow_id_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_snapshots_hash_idx": { + "name": "workflow_snapshots_hash_idx", + "columns": [ + { + "expression": "state_hash", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_snapshots_workflow_hash_idx": { + "name": "workflow_snapshots_workflow_hash_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "state_hash", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_snapshots_created_at_idx": { + "name": "workflow_snapshots_created_at_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workflow_execution_snapshots_workflow_id_workflow_id_fk": { + "name": "workflow_execution_snapshots_workflow_id_workflow_id_fk", + "tableFrom": "workflow_execution_snapshots", + "tableTo": "workflow", + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workflow_folder": { + "name": "workflow_folder", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "parent_id": { + "name": "parent_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "color": { + "name": "color", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "'#6B7280'" + }, + "is_expanded": { + "name": "is_expanded", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "sort_order": { + "name": "sort_order", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workflow_folder_user_idx": { + "name": "workflow_folder_user_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_folder_workspace_parent_idx": { + "name": "workflow_folder_workspace_parent_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_folder_parent_sort_idx": { + "name": "workflow_folder_parent_sort_idx", + "columns": [ + { + "expression": "parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "sort_order", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workflow_folder_user_id_user_id_fk": { + "name": "workflow_folder_user_id_user_id_fk", + "tableFrom": "workflow_folder", + "tableTo": "user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workflow_folder_workspace_id_workspace_id_fk": { + "name": "workflow_folder_workspace_id_workspace_id_fk", + "tableFrom": "workflow_folder", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workflow_log_webhook": { + "name": "workflow_log_webhook", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "url": { + "name": "url", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "secret": { + "name": "secret", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "include_final_output": { + "name": "include_final_output", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "include_trace_spans": { + "name": "include_trace_spans", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "include_rate_limits": { + "name": "include_rate_limits", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "include_usage_data": { + "name": "include_usage_data", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "level_filter": { + "name": "level_filter", + "type": "text[]", + "primaryKey": false, + "notNull": true, + "default": "ARRAY['info', 'error']::text[]" + }, + "trigger_filter": { + "name": "trigger_filter", + "type": "text[]", + "primaryKey": false, + "notNull": true, + "default": "ARRAY['api', 'webhook', 'schedule', 'manual', 'chat']::text[]" + }, + "active": { + "name": "active", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workflow_log_webhook_workflow_id_idx": { + "name": "workflow_log_webhook_workflow_id_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_log_webhook_active_idx": { + "name": "workflow_log_webhook_active_idx", + "columns": [ + { + "expression": "active", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workflow_log_webhook_workflow_id_workflow_id_fk": { + "name": "workflow_log_webhook_workflow_id_workflow_id_fk", + "tableFrom": "workflow_log_webhook", + "tableTo": "workflow", + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workflow_log_webhook_delivery": { + "name": "workflow_log_webhook_delivery", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "subscription_id": { + "name": "subscription_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "execution_id": { + "name": "execution_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "webhook_delivery_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "attempts": { + "name": "attempts", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "last_attempt_at": { + "name": "last_attempt_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "next_attempt_at": { + "name": "next_attempt_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "response_status": { + "name": "response_status", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "response_body": { + "name": "response_body", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "error_message": { + "name": "error_message", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workflow_log_webhook_delivery_subscription_id_idx": { + "name": "workflow_log_webhook_delivery_subscription_id_idx", + "columns": [ + { + "expression": "subscription_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_log_webhook_delivery_execution_id_idx": { + "name": "workflow_log_webhook_delivery_execution_id_idx", + "columns": [ + { + "expression": "execution_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_log_webhook_delivery_status_idx": { + "name": "workflow_log_webhook_delivery_status_idx", + "columns": [ + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_log_webhook_delivery_next_attempt_idx": { + "name": "workflow_log_webhook_delivery_next_attempt_idx", + "columns": [ + { + "expression": "next_attempt_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workflow_log_webhook_delivery_subscription_id_workflow_log_webhook_id_fk": { + "name": "workflow_log_webhook_delivery_subscription_id_workflow_log_webhook_id_fk", + "tableFrom": "workflow_log_webhook_delivery", + "tableTo": "workflow_log_webhook", + "columnsFrom": ["subscription_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workflow_log_webhook_delivery_workflow_id_workflow_id_fk": { + "name": "workflow_log_webhook_delivery_workflow_id_workflow_id_fk", + "tableFrom": "workflow_log_webhook_delivery", + "tableTo": "workflow", + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workflow_schedule": { + "name": "workflow_schedule", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "block_id": { + "name": "block_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "cron_expression": { + "name": "cron_expression", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "next_run_at": { + "name": "next_run_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "last_ran_at": { + "name": "last_ran_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "last_queued_at": { + "name": "last_queued_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "trigger_type": { + "name": "trigger_type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "timezone": { + "name": "timezone", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'UTC'" + }, + "failed_count": { + "name": "failed_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'active'" + }, + "last_failed_at": { + "name": "last_failed_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workflow_schedule_workflow_block_unique": { + "name": "workflow_schedule_workflow_block_unique", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "block_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workflow_schedule_workflow_id_workflow_id_fk": { + "name": "workflow_schedule_workflow_id_workflow_id_fk", + "tableFrom": "workflow_schedule", + "tableTo": "workflow", + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workflow_schedule_block_id_workflow_blocks_id_fk": { + "name": "workflow_schedule_block_id_workflow_blocks_id_fk", + "tableFrom": "workflow_schedule", + "tableTo": "workflow_blocks", + "columnsFrom": ["block_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workflow_subflows": { + "name": "workflow_subflows", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "config": { + "name": "config", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workflow_subflows_workflow_id_idx": { + "name": "workflow_subflows_workflow_id_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_subflows_workflow_type_idx": { + "name": "workflow_subflows_workflow_type_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "type", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workflow_subflows_workflow_id_workflow_id_fk": { + "name": "workflow_subflows_workflow_id_workflow_id_fk", + "tableFrom": "workflow_subflows", + "tableTo": "workflow", + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workspace": { + "name": "workspace", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "owner_id": { + "name": "owner_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "billed_account_user_id": { + "name": "billed_account_user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "allow_personal_api_keys": { + "name": "allow_personal_api_keys", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "workspace_owner_id_user_id_fk": { + "name": "workspace_owner_id_user_id_fk", + "tableFrom": "workspace", + "tableTo": "user", + "columnsFrom": ["owner_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workspace_billed_account_user_id_user_id_fk": { + "name": "workspace_billed_account_user_id_user_id_fk", + "tableFrom": "workspace", + "tableTo": "user", + "columnsFrom": ["billed_account_user_id"], + "columnsTo": ["id"], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workspace_environment": { + "name": "workspace_environment", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "variables": { + "name": "variables", + "type": "json", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workspace_environment_workspace_unique": { + "name": "workspace_environment_workspace_unique", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workspace_environment_workspace_id_workspace_id_fk": { + "name": "workspace_environment_workspace_id_workspace_id_fk", + "tableFrom": "workspace_environment", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workspace_file": { + "name": "workspace_file", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "size": { + "name": "size", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "uploaded_by": { + "name": "uploaded_by", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "uploaded_at": { + "name": "uploaded_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workspace_file_workspace_id_idx": { + "name": "workspace_file_workspace_id_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workspace_file_key_idx": { + "name": "workspace_file_key_idx", + "columns": [ + { + "expression": "key", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workspace_file_workspace_id_workspace_id_fk": { + "name": "workspace_file_workspace_id_workspace_id_fk", + "tableFrom": "workspace_file", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workspace_file_uploaded_by_user_id_fk": { + "name": "workspace_file_uploaded_by_user_id_fk", + "tableFrom": "workspace_file", + "tableTo": "user", + "columnsFrom": ["uploaded_by"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "workspace_file_key_unique": { + "name": "workspace_file_key_unique", + "nullsNotDistinct": false, + "columns": ["key"] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workspace_files": { + "name": "workspace_files", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "context": { + "name": "context", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "original_name": { + "name": "original_name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "content_type": { + "name": "content_type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "size": { + "name": "size", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "uploaded_at": { + "name": "uploaded_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workspace_files_key_idx": { + "name": "workspace_files_key_idx", + "columns": [ + { + "expression": "key", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workspace_files_user_id_idx": { + "name": "workspace_files_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workspace_files_workspace_id_idx": { + "name": "workspace_files_workspace_id_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workspace_files_context_idx": { + "name": "workspace_files_context_idx", + "columns": [ + { + "expression": "context", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workspace_files_user_id_user_id_fk": { + "name": "workspace_files_user_id_user_id_fk", + "tableFrom": "workspace_files", + "tableTo": "user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workspace_files_workspace_id_workspace_id_fk": { + "name": "workspace_files_workspace_id_workspace_id_fk", + "tableFrom": "workspace_files", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "workspace_files_key_unique": { + "name": "workspace_files_key_unique", + "nullsNotDistinct": false, + "columns": ["key"] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workspace_invitation": { + "name": "workspace_invitation", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "inviter_id": { + "name": "inviter_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'member'" + }, + "status": { + "name": "status", + "type": "workspace_invitation_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "token": { + "name": "token", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "permissions": { + "name": "permissions", + "type": "permission_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'admin'" + }, + "org_invitation_id": { + "name": "org_invitation_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "workspace_invitation_workspace_id_workspace_id_fk": { + "name": "workspace_invitation_workspace_id_workspace_id_fk", + "tableFrom": "workspace_invitation", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workspace_invitation_inviter_id_user_id_fk": { + "name": "workspace_invitation_inviter_id_user_id_fk", + "tableFrom": "workspace_invitation", + "tableTo": "user", + "columnsFrom": ["inviter_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "workspace_invitation_token_unique": { + "name": "workspace_invitation_token_unique", + "nullsNotDistinct": false, + "columns": ["token"] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + } + }, + "enums": { + "public.permission_type": { + "name": "permission_type", + "schema": "public", + "values": ["admin", "write", "read"] + }, + "public.template_creator_type": { + "name": "template_creator_type", + "schema": "public", + "values": ["user", "organization"] + }, + "public.template_status": { + "name": "template_status", + "schema": "public", + "values": ["pending", "approved", "rejected"] + }, + "public.webhook_delivery_status": { + "name": "webhook_delivery_status", + "schema": "public", + "values": ["pending", "in_progress", "success", "failed"] + }, + "public.workspace_invitation_status": { + "name": "workspace_invitation_status", + "schema": "public", + "values": ["pending", "accepted", "rejected", "cancelled"] + } + }, + "schemas": {}, + "sequences": {}, + "roles": {}, + "policies": {}, + "views": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} diff --git a/packages/db/migrations/meta/_journal.json b/packages/db/migrations/meta/_journal.json index d4c3a7c9ee..43821012ee 100644 --- a/packages/db/migrations/meta/_journal.json +++ b/packages/db/migrations/meta/_journal.json @@ -792,6 +792,13 @@ "when": 1764370369484, "tag": "0113_calm_tiger_shark", "breakpoints": true + }, + { + "idx": 114, + "version": "7", + "when": 1764468360258, + "tag": "0114_wise_sunfire", + "breakpoints": true } ] } diff --git a/packages/db/schema.ts b/packages/db/schema.ts index 81c69cdb51..10bfc43857 100644 --- a/packages/db/schema.ts +++ b/packages/db/schema.ts @@ -745,7 +745,8 @@ export const organization = pgTable('organization', { logo: text('logo'), metadata: json('metadata'), orgUsageLimit: decimal('org_usage_limit'), - storageUsedBytes: bigint('storage_used_bytes', { mode: 'number' }).notNull().default(0), // Storage tracking for team/enterprise + storageUsedBytes: bigint('storage_used_bytes', { mode: 'number' }).notNull().default(0), + departedMemberUsage: decimal('departed_member_usage').notNull().default('0'), createdAt: timestamp('created_at').defaultNow().notNull(), updatedAt: timestamp('updated_at').defaultNow().notNull(), }) From 93309406584d2319e8c4f5fb3f096c2c1d0363da Mon Sep 17 00:00:00 2001 From: Waleed Date: Sat, 29 Nov 2025 20:30:56 -0800 Subject: [PATCH 03/16] feat(i18n): update translations (#2134) Co-authored-by: waleedlatif1 --- apps/docs/content/docs/de/tools/linkedin.mdx | 83 ++++ apps/docs/content/docs/de/tools/mailgun.mdx | 216 ++++++++++ apps/docs/content/docs/de/tools/sendgrid.mdx | 391 ++++++++++++++++++ apps/docs/content/docs/de/tools/smtp.mdx | 73 ++++ apps/docs/content/docs/es/tools/linkedin.mdx | 83 ++++ apps/docs/content/docs/es/tools/mailgun.mdx | 216 ++++++++++ apps/docs/content/docs/es/tools/sendgrid.mdx | 392 +++++++++++++++++++ apps/docs/content/docs/es/tools/smtp.mdx | 73 ++++ apps/docs/content/docs/fr/tools/linkedin.mdx | 83 ++++ apps/docs/content/docs/fr/tools/mailgun.mdx | 216 ++++++++++ apps/docs/content/docs/fr/tools/sendgrid.mdx | 392 +++++++++++++++++++ apps/docs/content/docs/fr/tools/smtp.mdx | 73 ++++ apps/docs/content/docs/ja/tools/linkedin.mdx | 83 ++++ apps/docs/content/docs/ja/tools/mailgun.mdx | 216 ++++++++++ apps/docs/content/docs/ja/tools/sendgrid.mdx | 391 ++++++++++++++++++ apps/docs/content/docs/ja/tools/smtp.mdx | 73 ++++ apps/docs/content/docs/zh/tools/linkedin.mdx | 83 ++++ apps/docs/content/docs/zh/tools/mailgun.mdx | 216 ++++++++++ apps/docs/content/docs/zh/tools/sendgrid.mdx | 391 ++++++++++++++++++ apps/docs/content/docs/zh/tools/smtp.mdx | 73 ++++ apps/docs/i18n.lock | 224 +++++++++++ 21 files changed, 4041 insertions(+) create mode 100644 apps/docs/content/docs/de/tools/linkedin.mdx create mode 100644 apps/docs/content/docs/de/tools/mailgun.mdx create mode 100644 apps/docs/content/docs/de/tools/sendgrid.mdx create mode 100644 apps/docs/content/docs/de/tools/smtp.mdx create mode 100644 apps/docs/content/docs/es/tools/linkedin.mdx create mode 100644 apps/docs/content/docs/es/tools/mailgun.mdx create mode 100644 apps/docs/content/docs/es/tools/sendgrid.mdx create mode 100644 apps/docs/content/docs/es/tools/smtp.mdx create mode 100644 apps/docs/content/docs/fr/tools/linkedin.mdx create mode 100644 apps/docs/content/docs/fr/tools/mailgun.mdx create mode 100644 apps/docs/content/docs/fr/tools/sendgrid.mdx create mode 100644 apps/docs/content/docs/fr/tools/smtp.mdx create mode 100644 apps/docs/content/docs/ja/tools/linkedin.mdx create mode 100644 apps/docs/content/docs/ja/tools/mailgun.mdx create mode 100644 apps/docs/content/docs/ja/tools/sendgrid.mdx create mode 100644 apps/docs/content/docs/ja/tools/smtp.mdx create mode 100644 apps/docs/content/docs/zh/tools/linkedin.mdx create mode 100644 apps/docs/content/docs/zh/tools/mailgun.mdx create mode 100644 apps/docs/content/docs/zh/tools/sendgrid.mdx create mode 100644 apps/docs/content/docs/zh/tools/smtp.mdx diff --git a/apps/docs/content/docs/de/tools/linkedin.mdx b/apps/docs/content/docs/de/tools/linkedin.mdx new file mode 100644 index 0000000000..8860c4d7a5 --- /dev/null +++ b/apps/docs/content/docs/de/tools/linkedin.mdx @@ -0,0 +1,83 @@ +--- +title: LinkedIn +description: Teilen Sie Beiträge und verwalten Sie Ihre LinkedIn-Präsenz +--- + +import { BlockInfoCard } from "@/components/ui/block-info-card" + + + +{/* MANUAL-CONTENT-START:intro */} +[LinkedIn](https://www.linkedin.com) ist die weltweit größte professionelle Netzwerkplattform, die Nutzern ermöglicht, ihre Karriere aufzubauen, sich mit ihrem Netzwerk zu verbinden und berufliche Inhalte zu teilen. LinkedIn wird von Fachleuten aus verschiedenen Branchen für persönliches Branding, Recruiting, Jobsuche und Geschäftsentwicklung genutzt. + +Mit LinkedIn können Sie ganz einfach Beiträge in Ihrem persönlichen Feed teilen, um mit Ihrem Netzwerk in Kontakt zu treten, und auf Informationen über Ihr Profil zugreifen, um Ihre beruflichen Erfolge hervorzuheben. Die automatisierte Integration mit Sim ermöglicht es Ihnen, LinkedIn-Funktionen programmatisch zu nutzen – so können Agenten und Workflows Updates posten, über Ihre berufliche Präsenz berichten und Ihren Feed aktiv halten, ohne dass manuelle Arbeit erforderlich ist. + +Zu den wichtigsten LinkedIn-Funktionen, die über diese Integration verfügbar sind, gehören: + +- **Beiträge teilen:** Veröffentlichen Sie automatisch berufliche Updates, Artikel oder Ankündigungen in Ihrem persönlichen LinkedIn-Feed. +- **Profilinformationen:** Rufen Sie detaillierte Informationen über Ihr LinkedIn-Profil ab, um diese zu überwachen oder in nachgelagerten Aufgaben innerhalb Ihrer Workflows zu verwenden. + +Diese Funktionen machen es einfach, Ihr LinkedIn-Netzwerk zu pflegen und Ihre berufliche Reichweite effizient zu erweitern – als Teil Ihrer KI- oder Workflow-Automatisierungsstrategie. +{/* MANUAL-CONTENT-END */} + +## Nutzungsanleitung + +Integrieren Sie LinkedIn in Workflows. Teilen Sie Beiträge in Ihrem persönlichen Feed und greifen Sie auf Ihre LinkedIn-Profilinformationen zu. + +## Tools + +### `linkedin_share_post` + +Einen Beitrag in Ihrem persönlichen LinkedIn-Feed teilen + +#### Eingabe + +| Parameter | Typ | Erforderlich | Beschreibung | +| --------- | ---- | -------- | ----------- | +| `text` | string | Ja | Der Textinhalt Ihres LinkedIn-Beitrags | +| `visibility` | string | Nein | Wer diesen Beitrag sehen kann: "PUBLIC" oder "CONNECTIONS" \(Standard: "PUBLIC"\) | +| `request` | string | Nein | Keine Beschreibung | +| `output` | string | Nein | Keine Beschreibung | +| `output` | string | Nein | Keine Beschreibung | +| `specificContent` | string | Nein | Keine Beschreibung | +| `shareCommentary` | string | Nein | Keine Beschreibung | +| `visibility` | string | Nein | Keine Beschreibung | +| `headers` | string | Nein | Keine Beschreibung | +| `output` | string | Nein | Keine Beschreibung | +| `output` | string | Nein | Keine Beschreibung | +| `output` | string | Nein | Keine Beschreibung | + +#### Output + +| Parameter | Typ | Beschreibung | +| --------- | ---- | ----------- | +| `success` | boolean | Erfolgsstatus der Operation | +| `postId` | string | Erstellte Beitrags-ID | +| `profile` | json | LinkedIn-Profilinformationen | +| `error` | string | Fehlermeldung bei fehlgeschlagener Operation | + +### `linkedin_get_profile` + +Rufen Sie Ihre LinkedIn-Profilinformationen ab + +#### Input + +| Parameter | Typ | Erforderlich | Beschreibung | +| --------- | ---- | -------- | ----------- | + +#### Output + +| Parameter | Typ | Beschreibung | +| --------- | ---- | ----------- | +| `success` | boolean | Erfolgsstatus der Operation | +| `postId` | string | Erstellte Beitrags-ID | +| `profile` | json | LinkedIn-Profilinformationen | +| `error` | string | Fehlermeldung bei fehlgeschlagener Operation | + +## Hinweise + +- Kategorie: `tools` +- Typ: `linkedin` diff --git a/apps/docs/content/docs/de/tools/mailgun.mdx b/apps/docs/content/docs/de/tools/mailgun.mdx new file mode 100644 index 0000000000..a1981beed4 --- /dev/null +++ b/apps/docs/content/docs/de/tools/mailgun.mdx @@ -0,0 +1,216 @@ +--- +title: Mailgun +description: E-Mails versenden und Mailinglisten mit Mailgun verwalten +--- + +import { BlockInfoCard } from "@/components/ui/block-info-card" + + + +{/* MANUAL-CONTENT-START:intro */} +[Mailgun](https://www.mailgun.com) ist ein leistungsstarker E-Mail-Zustelldienst, der für Entwickler und Unternehmen konzipiert wurde, um E-Mails mühelos zu versenden, zu empfangen und zu verfolgen. Mailgun ermöglicht es Ihnen, robuste APIs für zuverlässige Transaktions- und Marketing-E-Mails, flexible Mailinglisten-Verwaltung und fortschrittliches Event-Tracking zu nutzen. + +Mit Mailguns umfassendem Funktionsumfang können Sie wichtige E-Mail-Operationen automatisieren und die Zustellbarkeit sowie das Engagement der Empfänger genau überwachen. Dies macht es zu einer idealen Lösung für Workflow-Automatisierung, bei der Kommunikation, Benachrichtigungen und Kampagnen-Mails zentrale Bestandteile Ihrer Prozesse sind. + +Zu den wichtigsten Funktionen von Mailgun gehören: + +- **Versand von Transaktions-E-Mails:** Zustellung von E-Mails mit hohem Volumen wie Kontobenachrichtigungen, Quittungen, Warnmeldungen und Passwort-Zurücksetzungen. +- **Reichhaltige E-Mail-Inhalte:** Versenden Sie sowohl Nur-Text- als auch HTML-E-Mails und verwenden Sie Tags zur Kategorisierung und Verfolgung Ihrer Nachrichten. +- **Mailinglisten-Verwaltung:** Erstellen, aktualisieren und verwalten Sie Mailinglisten und Mitglieder, um Gruppenkommunikation effizient zu versenden. +- **Domain-Informationen:** Rufen Sie Details zu Ihren Sende-Domains ab, um Konfiguration und Zustand zu überwachen. +- **Event-Tracking:** Analysieren Sie die Zustellbarkeit von E-Mails und das Engagement mit detaillierten Ereignisdaten zu gesendeten Nachrichten. +- **Nachrichtenabruf:** Greifen Sie auf gespeicherte Nachrichten für Compliance-, Analyse- oder Fehlerbehebungszwecke zu. + +Durch die Integration von Mailgun in Sim können Ihre Agenten programmatisch E-Mails versenden, E-Mail-Listen verwalten, auf Domain-Informationen zugreifen und Ereignisse in Echtzeit überwachen – als Teil automatisierter Workflows. Dies ermöglicht eine intelligente, datengesteuerte Interaktion mit Ihren Nutzern direkt aus Ihren KI-gestützten Prozessen heraus. +{/* MANUAL-CONTENT-END */} + +## Nutzungsanleitung + +Integrieren Sie Mailgun in Ihren Workflow. Senden Sie Transaktions-E-Mails, verwalten Sie Mailinglisten und Mitglieder, sehen Sie Domain-Informationen ein und verfolgen Sie E-Mail-Ereignisse. Unterstützt Text- und HTML-E-Mails, Tags für Tracking und umfassende Listenverwaltung. + +## Tools + +### `mailgun_send_message` + +E-Mail über die Mailgun API versenden + +#### Eingabe + +| Parameter | Typ | Erforderlich | Beschreibung | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Ja | Mailgun API-Schlüssel | +| `domain` | string | Ja | Mailgun-Domain \(z.B. mg.example.com\) | +| `from` | string | Ja | E-Mail-Adresse des Absenders | +| `to` | string | Ja | E-Mail-Adresse des Empfängers \(durch Komma getrennt für mehrere\) | +| `subject` | string | Ja | Betreff der E-Mail | +| `text` | string | Nein | Nur-Text-Inhalt der E-Mail | +| `html` | string | Nein | HTML-Inhalt der E-Mail | +| `cc` | string | Nein | CC-E-Mail-Adresse \(durch Komma getrennt für mehrere\) | +| `bcc` | string | Nein | BCC-E-Mail-Adresse \(durch Komma getrennt für mehrere\) | +| `tags` | string | Nein | Tags für die E-Mail \(durch Komma getrennt\) | + +#### Ausgabe + +| Parameter | Typ | Beschreibung | +| --------- | ---- | ----------- | +| `success` | boolean | Ob die Nachricht erfolgreich gesendet wurde | +| `id` | string | Nachrichten-ID | +| `message` | string | Antwortnachricht von Mailgun | + +### `mailgun_get_message` + +Eine gespeicherte Nachricht anhand ihres Schlüssels abrufen + +#### Eingabe + +| Parameter | Typ | Erforderlich | Beschreibung | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Ja | Mailgun API-Schlüssel | +| `domain` | string | Ja | Mailgun-Domain | +| `messageKey` | string | Ja | Speicherschlüssel der Nachricht | + +#### Output + +| Parameter | Type | Beschreibung | +| --------- | ---- | ----------- | +| `success` | boolean | Ob die Anfrage erfolgreich war | +| `recipients` | string | Nachrichtenempfänger | +| `from` | string | Absender-E-Mail | +| `subject` | string | Nachrichtenbetreff | +| `bodyPlain` | string | Nur-Text-Inhalt | +| `strippedText` | string | Bereinigter Text | +| `strippedSignature` | string | Bereinigte Signatur | +| `bodyHtml` | string | HTML-Inhalt | +| `strippedHtml` | string | Bereinigtes HTML | +| `attachmentCount` | number | Anzahl der Anhänge | +| `timestamp` | number | Nachrichtenzeitstempel | +| `messageHeaders` | json | Nachrichtenheader | +| `contentIdMap` | json | Content-ID-Zuordnung | + +### `mailgun_list_messages` + +Ereignisse (Logs) für über Mailgun gesendete Nachrichten auflisten + +#### Input + +| Parameter | Type | Required | Beschreibung | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Ja | Mailgun API-Schlüssel | +| `domain` | string | Ja | Mailgun-Domain | +| `event` | string | Nein | Nach Ereignistyp filtern \(accepted, delivered, failed, opened, clicked, usw.\) | +| `limit` | number | Nein | Maximale Anzahl der zurückzugebenden Ereignisse \(Standard: 100\) | + +#### Output + +| Parameter | Type | Beschreibung | +| --------- | ---- | ----------- | +| `success` | boolean | Ob die Anfrage erfolgreich war | +| `items` | json | Array von Ereigniselementen | +| `paging` | json | Paginierungsinformationen | + +### `mailgun_create_mailing_list` + +Eine neue Mailingliste erstellen + +#### Eingabe + +| Parameter | Typ | Erforderlich | Beschreibung | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Ja | Mailgun API-Schlüssel | +| `address` | string | Ja | Mailinglisten-Adresse \(z.B. liste@beispiel.com\) | +| `name` | string | Nein | Name der Mailingliste | +| `description` | string | Nein | Beschreibung der Mailingliste | +| `accessLevel` | string | Nein | Zugriffsebene: readonly, members oder everyone | + +#### Ausgabe + +| Parameter | Typ | Beschreibung | +| --------- | ---- | ----------- | +| `success` | boolean | Ob die Liste erfolgreich erstellt wurde | +| `message` | string | Antwortnachricht | +| `list` | json | Details der erstellten Mailingliste | + +### `mailgun_get_mailing_list` + +Details einer Mailingliste abrufen + +#### Eingabe + +| Parameter | Typ | Erforderlich | Beschreibung | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Ja | Mailgun API-Schlüssel | +| `address` | string | Ja | Mailinglisten-Adresse | + +#### Ausgabe + +| Parameter | Typ | Beschreibung | +| --------- | ---- | ----------- | +| `success` | boolean | Ob die Anfrage erfolgreich war | +| `list` | json | Details der Mailingliste | + +### `mailgun_add_list_member` + +Ein Mitglied zu einer Mailingliste hinzufügen + +#### Eingabe + +| Parameter | Typ | Erforderlich | Beschreibung | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Ja | Mailgun API-Schlüssel | +| `listAddress` | string | Ja | Mailinglisten-Adresse | +| `address` | string | Ja | E-Mail-Adresse des Mitglieds | +| `name` | string | Nein | Name des Mitglieds | +| `vars` | string | Nein | JSON-String mit benutzerdefinierten Variablen | +| `subscribed` | boolean | Nein | Ob das Mitglied abonniert ist | + +#### Ausgabe + +| Parameter | Typ | Beschreibung | +| --------- | ---- | ----------- | +| `success` | boolean | Ob das Mitglied erfolgreich hinzugefügt wurde | +| `message` | string | Antwortnachricht | +| `member` | json | Details des hinzugefügten Mitglieds | + +### `mailgun_list_domains` + +Alle Domains für Ihr Mailgun-Konto auflisten + +#### Eingabe + +| Parameter | Typ | Erforderlich | Beschreibung | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Ja | Mailgun API-Schlüssel | + +#### Ausgabe + +| Parameter | Typ | Beschreibung | +| --------- | ---- | ----------- | +| `success` | boolean | Ob die Anfrage erfolgreich war | +| `totalCount` | number | Gesamtanzahl der Domains | +| `items` | json | Array von Domain-Objekten | + +### `mailgun_get_domain` + +Details einer bestimmten Domain abrufen + +#### Eingabe + +| Parameter | Typ | Erforderlich | Beschreibung | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Ja | Mailgun API-Schlüssel | +| `domain` | string | Ja | Domainname | + +#### Ausgabe + +| Parameter | Typ | Beschreibung | +| --------- | ---- | ----------- | +| `success` | boolean | Ob die Anfrage erfolgreich war | +| `domain` | json | Domain-Details | + +## Hinweise + +- Kategorie: `tools` +- Typ: `mailgun` diff --git a/apps/docs/content/docs/de/tools/sendgrid.mdx b/apps/docs/content/docs/de/tools/sendgrid.mdx new file mode 100644 index 0000000000..8360d67811 --- /dev/null +++ b/apps/docs/content/docs/de/tools/sendgrid.mdx @@ -0,0 +1,391 @@ +--- +title: SendGrid +description: Senden Sie E-Mails und verwalten Sie Kontakte, Listen und Vorlagen mit SendGrid +--- + +import { BlockInfoCard } from "@/components/ui/block-info-card" + + + +{/* MANUAL-CONTENT-START:intro */} +[SendGrid](https://sendgrid.com) ist eine führende cloudbasierte E-Mail-Zustellplattform, der Entwickler und Unternehmen vertrauen, um zuverlässige Transaktions- und Marketing-E-Mails in großem Umfang zu versenden. Mit seinen robusten APIs und leistungsstarken Tools ermöglicht SendGrid die Verwaltung aller Aspekte Ihrer E-Mail-Kommunikation, vom Versenden von Benachrichtigungen und Quittungen bis hin zur Verwaltung komplexer Marketingkampagnen. + +SendGrid bietet Benutzern eine vollständige Suite von E-Mail-Funktionen, mit denen Sie kritische E-Mail-Workflows automatisieren und Kontaktlisten, Vorlagen und Empfängerengagement genau verwalten können. Die nahtlose Integration mit Sim ermöglicht es Agenten und Workflows, gezielte Nachrichten zu versenden, dynamische Kontakt- und Empfängerlisten zu pflegen, personalisierte E-Mails über Vorlagen auszulösen und die Ergebnisse in Echtzeit zu verfolgen. + +Zu den wichtigsten Funktionen von SendGrid gehören: + +- **Transaktions-E-Mails:** Versenden Sie automatisierte und umfangreiche Transaktions-E-Mails (wie Benachrichtigungen, Quittungen und Passwort-Zurücksetzungen). +- **Dynamische Vorlagen:** Verwenden Sie umfangreiche HTML- oder Textvorlagen mit dynamischen Daten für hochpersonalisierte Kommunikation im großen Maßstab. +- **Kontaktverwaltung:** Fügen Sie Marketing-Kontakte hinzu und aktualisieren Sie diese, verwalten Sie Empfängerlisten und Zielsegmente für Kampagnen. +- **Unterstützung für Anhänge:** Fügen Sie Ihren E-Mails einen oder mehrere Dateianhänge hinzu. +- **Umfassende API-Abdeckung:** Verwalten Sie E-Mails, Kontakte, Listen, Vorlagen, Unterdrückungsgruppen und mehr programmatisch. + +Durch die Verbindung von SendGrid mit Sim können Ihre Agenten: + +- Sowohl einfache als auch fortgeschrittene (vorlagenbasierte oder an mehrere Empfänger gerichtete) E-Mails als Teil eines beliebigen Workflows versenden. +- Kontakte und Listen automatisch verwalten und segmentieren. +- Vorlagen für Konsistenz und dynamische Personalisierung nutzen. +- E-Mail-Engagement innerhalb Ihrer automatisierten Prozesse verfolgen und darauf reagieren. + +Diese Integration ermöglicht es Ihnen, alle kritischen Kommunikationsabläufe zu automatisieren, sicherzustellen, dass Nachrichten die richtige Zielgruppe erreichen, und die Kontrolle über die E-Mail-Strategie Ihrer Organisation direkt aus Sim-Workflows zu behalten. +{/* MANUAL-CONTENT-END */} + +## Nutzungsanleitung + +Integrieren Sie SendGrid in Ihren Workflow. Senden Sie transaktionale E-Mails, verwalten Sie Marketing-Kontakte und -Listen und arbeiten Sie mit E-Mail-Vorlagen. Unterstützt dynamische Vorlagen, Anhänge und umfassendes Kontaktmanagement. + +## Tools + +### `sendgrid_send_mail` + +Eine E-Mail über die SendGrid API senden + +#### Eingabe + +| Parameter | Typ | Erforderlich | Beschreibung | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Ja | SendGrid API-Schlüssel | +| `from` | string | Ja | E-Mail-Adresse des Absenders \(muss in SendGrid verifiziert sein\) | +| `fromName` | string | Nein | Name des Absenders | +| `to` | string | Ja | E-Mail-Adresse des Empfängers | +| `toName` | string | Nein | Name des Empfängers | +| `subject` | string | Nein | E-Mail-Betreff \(erforderlich, es sei denn, es wird eine Vorlage mit vordefiniertem Betreff verwendet\) | +| `content` | string | Nein | E-Mail-Inhalt \(erforderlich, es sei denn, es wird eine Vorlage mit vordefiniertem Inhalt verwendet\) | +| `contentType` | string | Nein | Inhaltstyp \(text/plain oder text/html\) | +| `cc` | string | Nein | CC E-Mail-Adresse | +| `bcc` | string | Nein | BCC E-Mail-Adresse | +| `replyTo` | string | Nein | Antwort-an E-Mail-Adresse | +| `replyToName` | string | Nein | Antwort-an Name | +| `attachments` | file[] | Nein | Dateien, die der E-Mail angehängt werden sollen | +| `templateId` | string | Nein | Zu verwendende SendGrid-Vorlagen-ID | +| `dynamicTemplateData` | json | Nein | JSON-Objekt mit dynamischen Vorlagendaten | + +#### Ausgabe + +| Parameter | Typ | Beschreibung | +| --------- | ---- | ----------- | +| `success` | boolean | Ob die E-Mail erfolgreich gesendet wurde | +| `messageId` | string | SendGrid-Nachrichten-ID | +| `to` | string | E-Mail-Adresse des Empfängers | +| `subject` | string | E-Mail-Betreff | + +### `sendgrid_add_contact` + +Einen neuen Kontakt zu SendGrid hinzufügen + +#### Eingabe + +| Parameter | Typ | Erforderlich | Beschreibung | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Ja | SendGrid API-Schlüssel | +| `email` | string | Ja | E-Mail-Adresse des Kontakts | +| `firstName` | string | Nein | Vorname des Kontakts | +| `lastName` | string | Nein | Nachname des Kontakts | +| `customFields` | json | Nein | JSON-Objekt mit benutzerdefinierten Feld-Schlüssel-Wert-Paaren \(verwende Feld-IDs wie e1_T, e2_N, e3_D, nicht Feldnamen\) | +| `listIds` | string | Nein | Kommagetrennte Listen-IDs, zu denen der Kontakt hinzugefügt werden soll | + +#### Ausgabe + +| Parameter | Typ | Beschreibung | +| --------- | ---- | ----------- | +| `jobId` | string | Job-ID zur Verfolgung der asynchronen Kontakterstellung | +| `email` | string | E-Mail-Adresse des Kontakts | +| `firstName` | string | Vorname des Kontakts | +| `lastName` | string | Nachname des Kontakts | +| `message` | string | Statusmeldung | + +### `sendgrid_get_contact` + +Einen bestimmten Kontakt anhand der ID von SendGrid abrufen + +#### Eingabe + +| Parameter | Typ | Erforderlich | Beschreibung | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Ja | SendGrid API-Schlüssel | +| `contactId` | string | Ja | Kontakt-ID | + +#### Output + +| Parameter | Typ | Beschreibung | +| --------- | ---- | ----------- | +| `id` | string | Kontakt-ID | +| `email` | string | E-Mail-Adresse des Kontakts | +| `firstName` | string | Vorname des Kontakts | +| `lastName` | string | Nachname des Kontakts | +| `createdAt` | string | Erstellungszeitstempel | +| `updatedAt` | string | Zeitstempel der letzten Aktualisierung | +| `listIds` | json | Array von Listen-IDs, zu denen der Kontakt gehört | +| `customFields` | json | Benutzerdefinierte Feldwerte | + +### `sendgrid_search_contacts` + +Suche nach Kontakten in SendGrid mit einer Abfrage + +#### Input + +| Parameter | Typ | Erforderlich | Beschreibung | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Ja | SendGrid API-Schlüssel | +| `query` | string | Ja | Suchabfrage (z.B. "email LIKE '%example.com%' AND CONTAINS(list_ids, 'list-id')") | + +#### Output + +| Parameter | Typ | Beschreibung | +| --------- | ---- | ----------- | +| `contacts` | json | Array übereinstimmender Kontakte | +| `contactCount` | number | Gesamtzahl der gefundenen Kontakte | + +### `sendgrid_delete_contacts` + +Einen oder mehrere Kontakte aus SendGrid löschen + +#### Input + +| Parameter | Typ | Erforderlich | Beschreibung | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Ja | SendGrid API-Schlüssel | +| `contactIds` | string | Ja | Kommagetrennte Kontakt-IDs zum Löschen | + +#### Output + +| Parameter | Typ | Beschreibung | +| --------- | ---- | ----------- | +| `jobId` | string | Job-ID für die Löschanfrage | + +### `sendgrid_create_list` + +Erstellen einer neuen Kontaktliste in SendGrid + +#### Eingabe + +| Parameter | Typ | Erforderlich | Beschreibung | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Ja | SendGrid API-Schlüssel | +| `name` | string | Ja | Listenname | + +#### Ausgabe + +| Parameter | Typ | Beschreibung | +| --------- | ---- | ----------- | +| `id` | string | Listen-ID | +| `name` | string | Listenname | +| `contactCount` | number | Anzahl der Kontakte in der Liste | + +### `sendgrid_get_list` + +Eine bestimmte Liste anhand der ID von SendGrid abrufen + +#### Eingabe + +| Parameter | Typ | Erforderlich | Beschreibung | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Ja | SendGrid API-Schlüssel | +| `listId` | string | Ja | Listen-ID | + +#### Ausgabe + +| Parameter | Typ | Beschreibung | +| --------- | ---- | ----------- | +| `id` | string | Listen-ID | +| `name` | string | Listenname | +| `contactCount` | number | Anzahl der Kontakte in der Liste | + +### `sendgrid_list_all_lists` + +Alle Kontaktlisten von SendGrid abrufen + +#### Eingabe + +| Parameter | Typ | Erforderlich | Beschreibung | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Ja | SendGrid API-Schlüssel | +| `pageSize` | number | Nein | Anzahl der Listen, die pro Seite zurückgegeben werden sollen (Standard: 100) | + +#### Ausgabe + +| Parameter | Typ | Beschreibung | +| --------- | ---- | ----------- | +| `lists` | json | Array von Listen | + +### `sendgrid_delete_list` + +Eine Kontaktliste von SendGrid löschen + +#### Eingabe + +| Parameter | Typ | Erforderlich | Beschreibung | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Ja | SendGrid API-Schlüssel | +| `listId` | string | Ja | Listen-ID zum Löschen | + +#### Ausgabe + +| Parameter | Typ | Beschreibung | +| --------- | ---- | ----------- | +| `message` | string | Erfolgsmeldung | + +### `sendgrid_add_contacts_to_list` + +Kontakte hinzufügen oder aktualisieren und einer Liste in SendGrid zuweisen (verwendet PUT /v3/marketing/contacts) + +#### Eingabe + +| Parameter | Typ | Erforderlich | Beschreibung | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Ja | SendGrid API-Schlüssel | +| `listId` | string | Ja | Listen-ID, zu der Kontakte hinzugefügt werden sollen | +| `contacts` | json | Ja | JSON-Array von Kontaktobjekten. Jeder Kontakt muss mindestens Folgendes enthalten: E-Mail \(oder phone_number_id/external_id/anonymous_id\). Beispiel: \[\{"email": "user@example.com", "first_name": "John"\}\] | + +#### Ausgabe + +| Parameter | Typ | Beschreibung | +| --------- | ---- | ----------- | +| `jobId` | string | Job-ID zur Verfolgung des asynchronen Vorgangs | +| `message` | string | Statusmeldung | + +### `sendgrid_remove_contacts_from_list` + +Kontakte aus einer bestimmten Liste in SendGrid entfernen + +#### Eingabe + +| Parameter | Typ | Erforderlich | Beschreibung | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Ja | SendGrid API-Schlüssel | +| `listId` | string | Ja | Listen-ID | +| `contactIds` | string | Ja | Kommagetrennte Kontakt-IDs, die aus der Liste entfernt werden sollen | + +#### Ausgabe + +| Parameter | Typ | Beschreibung | +| --------- | ---- | ----------- | +| `jobId` | string | Job-ID für die Anfrage | + +### `sendgrid_create_template` + +Eine neue E-Mail-Vorlage in SendGrid erstellen + +#### Eingabe + +| Parameter | Typ | Erforderlich | Beschreibung | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Ja | SendGrid API-Schlüssel | +| `name` | string | Ja | Vorlagenname | +| `generation` | string | Nein | Vorlagenerstellungstyp \(legacy oder dynamic, standard: dynamic\) | + +#### Ausgabe + +| Parameter | Typ | Beschreibung | +| --------- | ---- | ----------- | +| `id` | string | Vorlagen-ID | +| `name` | string | Vorlagenname | +| `generation` | string | Vorlagenerstellung | +| `updatedAt` | string | Zeitstempel der letzten Aktualisierung | +| `versions` | json | Array von Vorlagenversionen | + +### `sendgrid_get_template` + +Eine bestimmte Vorlage anhand der ID von SendGrid abrufen + +#### Eingabe + +| Parameter | Typ | Erforderlich | Beschreibung | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Ja | SendGrid API-Schlüssel | +| `templateId` | string | Ja | Vorlagen-ID | + +#### Ausgabe + +| Parameter | Typ | Beschreibung | +| --------- | ---- | ----------- | +| `id` | string | Vorlagen-ID | +| `name` | string | Vorlagenname | +| `generation` | string | Vorlagenerstellung | +| `updatedAt` | string | Zeitstempel der letzten Aktualisierung | +| `versions` | json | Array von Vorlagenversionen | + +### `sendgrid_list_templates` + +Alle E-Mail-Vorlagen von SendGrid abrufen + +#### Eingabe + +| Parameter | Typ | Erforderlich | Beschreibung | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Ja | SendGrid API-Schlüssel | +| `generations` | string | Nein | Nach Generation filtern (legacy, dynamic oder beides) | +| `pageSize` | number | Nein | Anzahl der Vorlagen pro Seite (Standard: 20) | + +#### Ausgabe + +| Parameter | Typ | Beschreibung | +| --------- | ---- | ----------- | +| `templates` | json | Array von Vorlagen | + +### `sendgrid_delete_template` + +Eine E-Mail-Vorlage von SendGrid löschen + +#### Eingabe + +| Parameter | Typ | Erforderlich | Beschreibung | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Ja | SendGrid API-Schlüssel | +| `templateId` | string | Ja | Zu löschende Vorlagen-ID | + +#### Ausgabe + +| Parameter | Typ | Beschreibung | +| --------- | ---- | ----------- | +| `success` | boolean | Erfolgsstatus der Operation | +| `messageId` | string | E-Mail-Nachrichten-ID (send_mail) | +| `id` | string | Ressourcen-ID | +| `jobId` | string | Job-ID für asynchrone Operationen | +| `email` | string | E-Mail-Adresse | +| `firstName` | string | Vorname | +| `lastName` | string | Nachname | +| `contacts` | json | Array von Kontakten | +| `contactCount` | number | Anzahl der Kontakte | +| `lists` | json | Array von Listen | +| `templates` | json | Array von Vorlagen | +| `message` | string | Status- oder Erfolgsmeldung | +| `name` | string | Ressourcenname | +| `generation` | string | Vorlagengeneration | + +### `sendgrid_create_template_version` + +Eine neue Version einer E-Mail-Vorlage in SendGrid erstellen + +#### Eingabe + +| Parameter | Typ | Erforderlich | Beschreibung | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Ja | SendGrid API-Schlüssel | +| `templateId` | string | Ja | Vorlagen-ID | +| `name` | string | Ja | Versionsname | +| `subject` | string | Ja | E-Mail-Betreffzeile | +| `htmlContent` | string | Nein | HTML-Inhalt der Vorlage | +| `plainContent` | string | Nein | Nur-Text-Inhalt der Vorlage | +| `active` | boolean | Nein | Ob diese Version aktiv ist \(Standard: true\) | + +#### Ausgabe + +| Parameter | Typ | Beschreibung | +| --------- | ---- | ----------- | +| `id` | string | Versions-ID | +| `templateId` | string | Vorlagen-ID | +| `name` | string | Versionsname | +| `subject` | string | E-Mail-Betreff | +| `active` | boolean | Ob diese Version aktiv ist | +| `htmlContent` | string | HTML-Inhalt | +| `plainContent` | string | Nur-Text-Inhalt | +| `updatedAt` | string | Zeitstempel der letzten Aktualisierung | + +## Hinweise + +- Kategorie: `tools` +- Typ: `sendgrid` diff --git a/apps/docs/content/docs/de/tools/smtp.mdx b/apps/docs/content/docs/de/tools/smtp.mdx new file mode 100644 index 0000000000..b8ade7db9c --- /dev/null +++ b/apps/docs/content/docs/de/tools/smtp.mdx @@ -0,0 +1,73 @@ +--- +title: SMTP +description: E-Mails über jeden SMTP-Mailserver versenden +--- + +import { BlockInfoCard } from "@/components/ui/block-info-card" + + + +{/* MANUAL-CONTENT-START:intro */} +[SMTP (Simple Mail Transfer Protocol)](https://en.wikipedia.org/wiki/Simple_Mail_Transfer_Protocol) ist der grundlegende Standard für die E-Mail-Übertragung im Internet. Durch die Verbindung mit einem SMTP-kompatiblen Server – wie Gmail, Outlook oder der eigenen Mail-Infrastruktur Ihrer Organisation – können Sie E-Mails programmatisch versenden und Ihre ausgehende Kommunikation automatisieren. + +Die SMTP-Integration ermöglicht es Ihnen, den E-Mail-Versand durch direkte Serververbindung vollständig anzupassen und unterstützt sowohl einfache als auch fortgeschrittene E-Mail-Anwendungsfälle. Mit SMTP können Sie jeden Aspekt der Nachrichtenzustellung, des Empfängermanagements und der Inhaltsformatierung kontrollieren, was es ideal für transaktionale Benachrichtigungen, Massenmailings und jeden automatisierten Workflow macht, der eine robuste ausgehende E-Mail-Zustellung erfordert. + +**Zu den wichtigsten Funktionen der SMTP-Integration gehören:** + +- **Universeller E-Mail-Versand:** Senden Sie E-Mails über jeden SMTP-Server durch Konfiguration standardmäßiger Serververbindungsparameter. +- **Anpassbare Absender und Empfänger:** Legen Sie Absenderadresse, Anzeigename, Hauptempfänger sowie CC- und BCC-Felder fest. +- **Unterstützung für umfangreiche Inhalte:** Senden Sie Nur-Text- oder reich formatierte HTML-E-Mails entsprechend Ihren Anforderungen. +- **Anhänge:** Fügen Sie ausgehenden E-Mails mehrere Dateien als Anhänge hinzu. +- **Flexible Sicherheit:** Verbinden Sie sich über TLS, SSL oder Standardprotokolle (unverschlüsselt), je nach Unterstützung Ihres SMTP-Anbieters. +- **Erweiterte Header:** Setzen Sie Antwort-an-Header und andere erweiterte E-Mail-Optionen, um komplexe Mailflows und Benutzerinteraktionen zu ermöglichen. + +Durch die Integration von SMTP mit Sim können Agenten und Workflows programmatisch E-Mails als Teil jedes automatisierten Prozesses versenden – von Benachrichtigungen und Bestätigungen bis hin zur Automatisierung externer Kommunikation, Berichterstattung und Dokumentenzustellung. Dies bietet einen hochflexiblen, anbieterunabhängigen Ansatz zur Verwaltung von E-Mails direkt innerhalb Ihrer KI-gesteuerten Prozesse. +{/* MANUAL-CONTENT-END */} + +## Gebrauchsanweisung + +Senden Sie E-Mails über jeden SMTP-Server (Gmail, Outlook, benutzerdefinierte Server usw.). Konfigurieren Sie SMTP-Verbindungseinstellungen und senden Sie E-Mails mit voller Kontrolle über Inhalt, Empfänger und Anhänge. + +## Tools + +### `smtp_send_mail` + +E-Mails über SMTP-Server senden + +#### Eingabe + +| Parameter | Typ | Erforderlich | Beschreibung | +| --------- | ---- | -------- | ----------- | +| `smtpHost` | string | Ja | SMTP-Server-Hostname \(z.B. smtp.gmail.com\) | +| `smtpPort` | number | Ja | SMTP-Server-Port \(587 für TLS, 465 für SSL\) | +| `smtpUsername` | string | Ja | SMTP-Authentifizierungsbenutzername | +| `smtpPassword` | string | Ja | SMTP-Authentifizierungspasswort | +| `smtpSecure` | string | Ja | Sicherheitsprotokoll \(TLS, SSL oder None\) | +| `from` | string | Ja | Absender-E-Mail-Adresse | +| `to` | string | Ja | Empfänger-E-Mail-Adresse | +| `subject` | string | Ja | E-Mail-Betreff | +| `body` | string | Ja | E-Mail-Inhalt | +| `contentType` | string | Nein | Inhaltstyp \(text oder html\) | +| `fromName` | string | Nein | Anzeigename für Absender | +| `cc` | string | Nein | CC-Empfänger \(durch Komma getrennt\) | +| `bcc` | string | Nein | BCC-Empfänger \(durch Komma getrennt\) | +| `replyTo` | string | Nein | Antwort-an E-Mail-Adresse | +| `attachments` | file[] | Nein | Dateien, die der E-Mail angehängt werden sollen | + +#### Ausgabe + +| Parameter | Typ | Beschreibung | +| --------- | ---- | ----------- | +| `success` | boolean | Ob die E-Mail erfolgreich gesendet wurde | +| `messageId` | string | Nachrichten-ID vom SMTP-Server | +| `to` | string | Empfänger-E-Mail-Adresse | +| `subject` | string | E-Mail-Betreff | +| `error` | string | Fehlermeldung, wenn das Senden fehlgeschlagen ist | + +## Notizen + +- Kategorie: `tools` +- Typ: `smtp` diff --git a/apps/docs/content/docs/es/tools/linkedin.mdx b/apps/docs/content/docs/es/tools/linkedin.mdx new file mode 100644 index 0000000000..29f31acb68 --- /dev/null +++ b/apps/docs/content/docs/es/tools/linkedin.mdx @@ -0,0 +1,83 @@ +--- +title: LinkedIn +description: Comparte publicaciones y gestiona tu presencia en LinkedIn +--- + +import { BlockInfoCard } from "@/components/ui/block-info-card" + + + +{/* MANUAL-CONTENT-START:intro */} +[LinkedIn](https://www.linkedin.com) es la plataforma de redes profesionales más grande del mundo, que permite a los usuarios desarrollar sus carreras, conectarse con su red y compartir contenido profesional. LinkedIn es ampliamente utilizado por profesionales de diversas industrias para branding personal, reclutamiento, búsqueda de empleo y desarrollo de negocios. + +Con LinkedIn, puedes compartir fácilmente publicaciones en tu feed personal para interactuar con tu red y acceder a información sobre tu perfil para destacar tus logros profesionales. La integración automatizada con Sim te permite aprovechar la funcionalidad de LinkedIn de forma programática, permitiendo que agentes y flujos de trabajo publiquen actualizaciones, informen sobre tu presencia profesional y mantengan tu feed activo sin esfuerzo manual. + +Las características clave de LinkedIn disponibles a través de esta integración incluyen: + +- **Compartir publicaciones:** Publica automáticamente actualizaciones profesionales, artículos o anuncios en tu feed personal de LinkedIn. +- **Información del perfil:** Obtén información detallada sobre tu perfil de LinkedIn para monitorear o usar en tareas posteriores dentro de tus flujos de trabajo. + +Estas capacidades facilitan mantener tu red de LinkedIn comprometida y extender tu alcance profesional de manera eficiente como parte de tu estrategia de automatización de IA o flujo de trabajo. +{/* MANUAL-CONTENT-END */} + +## Instrucciones de uso + +Integra LinkedIn en flujos de trabajo. Comparte publicaciones en tu feed personal y accede a la información de tu perfil de LinkedIn. + +## Herramientas + +### `linkedin_share_post` + +Comparte una publicación en tu feed personal de LinkedIn + +#### Entrada + +| Parámetro | Tipo | Obligatorio | Descripción | +| --------- | ---- | -------- | ----------- | +| `text` | string | Sí | El contenido de texto de tu publicación en LinkedIn | +| `visibility` | string | No | Quién puede ver esta publicación: "PUBLIC" o "CONNECTIONS" \(predeterminado: "PUBLIC"\) | +| `request` | string | No | Sin descripción | +| `output` | string | No | Sin descripción | +| `output` | string | No | Sin descripción | +| `specificContent` | string | No | Sin descripción | +| `shareCommentary` | string | No | Sin descripción | +| `visibility` | string | No | Sin descripción | +| `headers` | string | No | Sin descripción | +| `output` | string | No | Sin descripción | +| `output` | string | No | Sin descripción | +| `output` | string | No | Sin descripción | + +#### Salida + +| Parámetro | Tipo | Descripción | +| --------- | ---- | ----------- | +| `success` | boolean | Estado de éxito de la operación | +| `postId` | string | ID de la publicación creada | +| `profile` | json | Información del perfil de LinkedIn | +| `error` | string | Mensaje de error si la operación falló | + +### `linkedin_get_profile` + +Recuperar la información de tu perfil de LinkedIn + +#### Entrada + +| Parámetro | Tipo | Requerido | Descripción | +| --------- | ---- | -------- | ----------- | + +#### Salida + +| Parámetro | Tipo | Descripción | +| --------- | ---- | ----------- | +| `success` | boolean | Estado de éxito de la operación | +| `postId` | string | ID de la publicación creada | +| `profile` | json | Información del perfil de LinkedIn | +| `error` | string | Mensaje de error si la operación falló | + +## Notas + +- Categoría: `tools` +- Tipo: `linkedin` diff --git a/apps/docs/content/docs/es/tools/mailgun.mdx b/apps/docs/content/docs/es/tools/mailgun.mdx new file mode 100644 index 0000000000..f1e5e5704a --- /dev/null +++ b/apps/docs/content/docs/es/tools/mailgun.mdx @@ -0,0 +1,216 @@ +--- +title: Mailgun +description: Envía correos electrónicos y gestiona listas de correo con Mailgun +--- + +import { BlockInfoCard } from "@/components/ui/block-info-card" + + + +{/* MANUAL-CONTENT-START:intro */} +[Mailgun](https://www.mailgun.com) es un potente servicio de envío de correos electrónicos diseñado para desarrolladores y empresas que permite enviar, recibir y rastrear correos electrónicos sin esfuerzo. Mailgun te permite aprovechar APIs robustas para correos electrónicos transaccionales y de marketing confiables, gestión flexible de listas de correo y seguimiento avanzado de eventos. + +Con el conjunto completo de funciones de Mailgun, puedes automatizar operaciones clave de correo electrónico y monitorear de cerca la entregabilidad y el compromiso de los destinatarios. Esto lo convierte en una solución ideal para la automatización de flujos de trabajo donde las comunicaciones, notificaciones y correos de campaña son partes fundamentales de tus procesos. + +Las características principales de Mailgun incluyen: + +- **Envío de correos electrónicos transaccionales:** Entrega correos electrónicos de alto volumen como notificaciones de cuenta, recibos, alertas y restablecimientos de contraseña. +- **Contenido de correo electrónico enriquecido:** Envía correos electrónicos tanto en texto plano como en HTML, y utiliza etiquetas para categorizar y rastrear tus mensajes. +- **Gestión de listas de correo:** Crea, actualiza y gestiona listas de correo y miembros para enviar comunicaciones grupales de manera eficiente. +- **Información de dominio:** Obtén detalles sobre tus dominios de envío para monitorear la configuración y el estado. +- **Seguimiento de eventos:** Analiza la entregabilidad y el compromiso del correo electrónico con datos detallados de eventos en los mensajes enviados. +- **Recuperación de mensajes:** Accede a mensajes almacenados para necesidades de cumplimiento, análisis o solución de problemas. + +Al integrar Mailgun en Sim, tus agentes pueden enviar correos electrónicos programáticamente, gestionar listas de correo, acceder a información de dominio y monitorear eventos en tiempo real como parte de flujos de trabajo automatizados. Esto permite una participación inteligente y basada en datos con tus usuarios directamente desde tus procesos impulsados por IA. +{/* MANUAL-CONTENT-END */} + +## Instrucciones de uso + +Integra Mailgun en tu flujo de trabajo. Envía correos electrónicos transaccionales, gestiona listas de correo y miembros, visualiza información de dominio y realiza seguimiento de eventos de correo electrónico. Compatible con correos electrónicos de texto y HTML, etiquetas para seguimiento y gestión integral de listas. + +## Herramientas + +### `mailgun_send_message` + +Enviar un correo electrónico usando la API de Mailgun + +#### Entrada + +| Parámetro | Tipo | Obligatorio | Descripción | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Sí | Clave API de Mailgun | +| `domain` | string | Sí | Dominio de Mailgun \(ej., mg.example.com\) | +| `from` | string | Sí | Dirección de correo del remitente | +| `to` | string | Sí | Dirección de correo del destinatario \(separados por comas para múltiples\) | +| `subject` | string | Sí | Asunto del correo electrónico | +| `text` | string | No | Cuerpo de texto plano del correo electrónico | +| `html` | string | No | Cuerpo HTML del correo electrónico | +| `cc` | string | No | Dirección de correo CC \(separados por comas para múltiples\) | +| `bcc` | string | No | Dirección de correo BCC \(separados por comas para múltiples\) | +| `tags` | string | No | Etiquetas para el correo electrónico \(separadas por comas\) | + +#### Salida + +| Parámetro | Tipo | Descripción | +| --------- | ---- | ----------- | +| `success` | boolean | Si el mensaje fue enviado con éxito | +| `id` | string | ID del mensaje | +| `message` | string | Mensaje de respuesta de Mailgun | + +### `mailgun_get_message` + +Recuperar un mensaje almacenado por su clave + +#### Entrada + +| Parámetro | Tipo | Obligatorio | Descripción | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Sí | Clave API de Mailgun | +| `domain` | string | Sí | Dominio de Mailgun | +| `messageKey` | string | Sí | Clave de almacenamiento del mensaje | + +#### Salida + +| Parámetro | Tipo | Descripción | +| --------- | ---- | ----------- | +| `success` | boolean | Si la solicitud fue exitosa | +| `recipients` | string | Destinatarios del mensaje | +| `from` | string | Correo electrónico del remitente | +| `subject` | string | Asunto del mensaje | +| `bodyPlain` | string | Cuerpo en texto plano | +| `strippedText` | string | Texto simplificado | +| `strippedSignature` | string | Firma simplificada | +| `bodyHtml` | string | Cuerpo HTML | +| `strippedHtml` | string | HTML simplificado | +| `attachmentCount` | number | Número de archivos adjuntos | +| `timestamp` | number | Marca de tiempo del mensaje | +| `messageHeaders` | json | Encabezados del mensaje | +| `contentIdMap` | json | Mapa de ID de contenido | + +### `mailgun_list_messages` + +Listar eventos (registros) para mensajes enviados a través de Mailgun + +#### Entrada + +| Parámetro | Tipo | Obligatorio | Descripción | +| --------- | ---- | ----------- | ----------- | +| `apiKey` | string | Sí | Clave API de Mailgun | +| `domain` | string | Sí | Dominio de Mailgun | +| `event` | string | No | Filtrar por tipo de evento \(accepted, delivered, failed, opened, clicked, etc.\) | +| `limit` | number | No | Número máximo de eventos a devolver \(predeterminado: 100\) | + +#### Salida + +| Parámetro | Tipo | Descripción | +| --------- | ---- | ----------- | +| `success` | boolean | Si la solicitud fue exitosa | +| `items` | json | Array de elementos de eventos | +| `paging` | json | Información de paginación | + +### `mailgun_create_mailing_list` + +Crear una nueva lista de correo + +#### Entrada + +| Parámetro | Tipo | Obligatorio | Descripción | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Sí | Clave API de Mailgun | +| `address` | string | Sí | Dirección de la lista de correo \(ej., lista@ejemplo.com\) | +| `name` | string | No | Nombre de la lista de correo | +| `description` | string | No | Descripción de la lista de correo | +| `accessLevel` | string | No | Nivel de acceso: readonly, members, o everyone | + +#### Salida + +| Parámetro | Tipo | Descripción | +| --------- | ---- | ----------- | +| `success` | boolean | Si la lista fue creada con éxito | +| `message` | string | Mensaje de respuesta | +| `list` | json | Detalles de la lista de correo creada | + +### `mailgun_get_mailing_list` + +Obtener detalles de una lista de correo + +#### Entrada + +| Parámetro | Tipo | Obligatorio | Descripción | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Sí | Clave API de Mailgun | +| `address` | string | Sí | Dirección de la lista de correo | + +#### Salida + +| Parámetro | Tipo | Descripción | +| --------- | ---- | ----------- | +| `success` | boolean | Si la solicitud fue exitosa | +| `list` | json | Detalles de la lista de correo | + +### `mailgun_add_list_member` + +Añadir un miembro a una lista de correo + +#### Entrada + +| Parámetro | Tipo | Obligatorio | Descripción | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Sí | Clave API de Mailgun | +| `listAddress` | string | Sí | Dirección de la lista de correo | +| `address` | string | Sí | Dirección de correo electrónico del miembro | +| `name` | string | No | Nombre del miembro | +| `vars` | string | No | Cadena JSON de variables personalizadas | +| `subscribed` | boolean | No | Si el miembro está suscrito | + +#### Salida + +| Parámetro | Tipo | Descripción | +| --------- | ---- | ----------- | +| `success` | boolean | Si el miembro fue añadido con éxito | +| `message` | string | Mensaje de respuesta | +| `member` | json | Detalles del miembro añadido | + +### `mailgun_list_domains` + +Listar todos los dominios para tu cuenta de Mailgun + +#### Entrada + +| Parámetro | Tipo | Obligatorio | Descripción | +| --------- | ---- | ----------- | ----------- | +| `apiKey` | string | Sí | Clave API de Mailgun | + +#### Salida + +| Parámetro | Tipo | Descripción | +| --------- | ---- | ----------- | +| `success` | boolean | Si la solicitud fue exitosa | +| `totalCount` | number | Número total de dominios | +| `items` | json | Array de objetos de dominio | + +### `mailgun_get_domain` + +Obtener detalles de un dominio específico + +#### Entrada + +| Parámetro | Tipo | Obligatorio | Descripción | +| --------- | ---- | ----------- | ----------- | +| `apiKey` | string | Sí | Clave API de Mailgun | +| `domain` | string | Sí | Nombre de dominio | + +#### Salida + +| Parámetro | Tipo | Descripción | +| --------- | ---- | ----------- | +| `success` | boolean | Si la solicitud fue exitosa | +| `domain` | json | Detalles del dominio | + +## Notas + +- Categoría: `tools` +- Tipo: `mailgun` diff --git a/apps/docs/content/docs/es/tools/sendgrid.mdx b/apps/docs/content/docs/es/tools/sendgrid.mdx new file mode 100644 index 0000000000..439f89e704 --- /dev/null +++ b/apps/docs/content/docs/es/tools/sendgrid.mdx @@ -0,0 +1,392 @@ +--- +title: SendGrid +description: Envía correos electrónicos y gestiona contactos, listas y + plantillas con SendGrid +--- + +import { BlockInfoCard } from "@/components/ui/block-info-card" + + + +{/* MANUAL-CONTENT-START:intro */} +[SendGrid](https://sendgrid.com) es una plataforma líder de envío de correos electrónicos en la nube en la que confían desarrolladores y empresas para enviar correos electrónicos transaccionales y de marketing fiables a gran escala. Con sus sólidas APIs y potentes herramientas, SendGrid te permite gestionar todos los aspectos de tu comunicación por correo electrónico, desde el envío de notificaciones y recibos hasta la gestión de complejas campañas de marketing. + +SendGrid ofrece a los usuarios un conjunto completo de operaciones de correo electrónico, permitiéndote automatizar flujos de trabajo críticos de correo electrónico y gestionar de cerca listas de contactos, plantillas y la participación de los destinatarios. Su integración perfecta con Sim permite a los agentes y flujos de trabajo entregar mensajes específicos, mantener listas dinámicas de contactos y destinatarios, activar correos electrónicos personalizados a través de plantillas y seguir los resultados en tiempo real. + +Las características principales de SendGrid incluyen: + +- **Correo electrónico transaccional:** Envía correos electrónicos transaccionales automatizados y de alto volumen (como notificaciones, recibos y restablecimientos de contraseña). +- **Plantillas dinámicas:** Utiliza plantillas de texto o HTML enriquecido con datos dinámicos para una comunicación altamente personalizada a gran escala. +- **Gestión de contactos:** Añade y actualiza contactos de marketing, gestiona listas de destinatarios y segmentos objetivo para campañas. +- **Soporte para archivos adjuntos:** Incluye uno o más archivos adjuntos en tus correos electrónicos. +- **Cobertura integral de API:** Gestiona programáticamente correos electrónicos, contactos, listas, plantillas, grupos de supresión y más. + +Al conectar SendGrid con Sim, tus agentes pueden: + +- Enviar correos electrónicos tanto simples como avanzados (con plantillas o múltiples destinatarios) como parte de cualquier flujo de trabajo. +- Gestionar y segmentar contactos y listas automáticamente. +- Aprovechar las plantillas para mantener consistencia y personalización dinámica. +- Realizar seguimiento y responder a la interacción con los correos electrónicos dentro de tus procesos automatizados. + +Esta integración te permite automatizar todos los flujos de comunicación críticos, asegurar que los mensajes lleguen a la audiencia correcta y mantener el control sobre la estrategia de correo electrónico de tu organización, directamente desde los flujos de trabajo de Sim. +{/* MANUAL-CONTENT-END */} + +## Instrucciones de uso + +Integra SendGrid en tu flujo de trabajo. Envía correos electrónicos transaccionales, gestiona contactos y listas de marketing, y trabaja con plantillas de correo electrónico. Compatible con plantillas dinámicas, archivos adjuntos y gestión integral de contactos. + +## Herramientas + +### `sendgrid_send_mail` + +Enviar un correo electrónico usando la API de SendGrid + +#### Entrada + +| Parámetro | Tipo | Obligatorio | Descripción | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Sí | Clave API de SendGrid | +| `from` | string | Sí | Dirección de correo electrónico del remitente \(debe estar verificada en SendGrid\) | +| `fromName` | string | No | Nombre del remitente | +| `to` | string | Sí | Dirección de correo electrónico del destinatario | +| `toName` | string | No | Nombre del destinatario | +| `subject` | string | No | Asunto del correo electrónico \(obligatorio a menos que se use una plantilla con asunto predefinido\) | +| `content` | string | No | Contenido del cuerpo del correo electrónico \(obligatorio a menos que se use una plantilla con contenido predefinido\) | +| `contentType` | string | No | Tipo de contenido \(text/plain o text/html\) | +| `cc` | string | No | Dirección de correo electrónico CC | +| `bcc` | string | No | Dirección de correo electrónico BCC | +| `replyTo` | string | No | Dirección de correo electrónico de respuesta | +| `replyToName` | string | No | Nombre de respuesta | +| `attachments` | file[] | No | Archivos para adjuntar al correo electrónico | +| `templateId` | string | No | ID de plantilla de SendGrid a utilizar | +| `dynamicTemplateData` | json | No | Objeto JSON de datos de plantilla dinámica | + +#### Salida + +| Parámetro | Tipo | Descripción | +| --------- | ---- | ----------- | +| `success` | boolean | Si el correo electrónico se envió correctamente | +| `messageId` | string | ID del mensaje de SendGrid | +| `to` | string | Dirección de correo electrónico del destinatario | +| `subject` | string | Asunto del correo electrónico | + +### `sendgrid_add_contact` + +Añadir un nuevo contacto a SendGrid + +#### Entrada + +| Parámetro | Tipo | Obligatorio | Descripción | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Sí | Clave API de SendGrid | +| `email` | string | Sí | Dirección de correo electrónico del contacto | +| `firstName` | string | No | Nombre del contacto | +| `lastName` | string | No | Apellido del contacto | +| `customFields` | json | No | Objeto JSON de pares clave-valor de campos personalizados \(use IDs de campo como e1_T, e2_N, e3_D, no nombres de campo\) | +| `listIds` | string | No | Lista separada por comas de IDs a los que añadir el contacto | + +#### Salida + +| Parámetro | Tipo | Descripción | +| --------- | ---- | ----------- | +| `jobId` | string | ID de trabajo para seguimiento de la creación asíncrona de contactos | +| `email` | string | Dirección de correo electrónico del contacto | +| `firstName` | string | Nombre del contacto | +| `lastName` | string | Apellido del contacto | +| `message` | string | Mensaje de estado | + +### `sendgrid_get_contact` + +Obtener un contacto específico por ID desde SendGrid + +#### Entrada + +| Parámetro | Tipo | Obligatorio | Descripción | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Sí | Clave API de SendGrid | +| `contactId` | string | Sí | ID del contacto | + +#### Salida + +| Parámetro | Tipo | Descripción | +| --------- | ---- | ----------- | +| `id` | string | ID del contacto | +| `email` | string | Dirección de correo electrónico del contacto | +| `firstName` | string | Nombre del contacto | +| `lastName` | string | Apellido del contacto | +| `createdAt` | string | Marca de tiempo de creación | +| `updatedAt` | string | Marca de tiempo de última actualización | +| `listIds` | json | Array de IDs de listas a las que pertenece el contacto | +| `customFields` | json | Valores de campos personalizados | + +### `sendgrid_search_contacts` + +Buscar contactos en SendGrid usando una consulta + +#### Entrada + +| Parámetro | Tipo | Obligatorio | Descripción | +| --------- | ---- | ----------- | ----------- | +| `apiKey` | string | Sí | Clave API de SendGrid | +| `query` | string | Sí | Consulta de búsqueda (p. ej., "email LIKE '%example.com%' AND CONTAINS(list_ids, 'list-id')") | + +#### Salida + +| Parámetro | Tipo | Descripción | +| --------- | ---- | ----------- | +| `contacts` | json | Array de contactos coincidentes | +| `contactCount` | number | Número total de contactos encontrados | + +### `sendgrid_delete_contacts` + +Eliminar uno o más contactos de SendGrid + +#### Entrada + +| Parámetro | Tipo | Obligatorio | Descripción | +| --------- | ---- | ----------- | ----------- | +| `apiKey` | string | Sí | Clave API de SendGrid | +| `contactIds` | string | Sí | IDs de contactos separados por comas para eliminar | + +#### Salida + +| Parámetro | Tipo | Descripción | +| --------- | ---- | ----------- | +| `jobId` | string | ID de trabajo para la solicitud de eliminación | + +### `sendgrid_create_list` + +Crear una nueva lista de contactos en SendGrid + +#### Entrada + +| Parámetro | Tipo | Obligatorio | Descripción | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Sí | Clave API de SendGrid | +| `name` | string | Sí | Nombre de la lista | + +#### Salida + +| Parámetro | Tipo | Descripción | +| --------- | ---- | ----------- | +| `id` | string | ID de la lista | +| `name` | string | Nombre de la lista | +| `contactCount` | number | Número de contactos en la lista | + +### `sendgrid_get_list` + +Obtener una lista específica por ID desde SendGrid + +#### Entrada + +| Parámetro | Tipo | Obligatorio | Descripción | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Sí | Clave API de SendGrid | +| `listId` | string | Sí | ID de la lista | + +#### Salida + +| Parámetro | Tipo | Descripción | +| --------- | ---- | ----------- | +| `id` | string | ID de la lista | +| `name` | string | Nombre de la lista | +| `contactCount` | number | Número de contactos en la lista | + +### `sendgrid_list_all_lists` + +Obtener todas las listas de contactos desde SendGrid + +#### Entrada + +| Parámetro | Tipo | Obligatorio | Descripción | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Sí | Clave API de SendGrid | +| `pageSize` | number | No | Número de listas a devolver por página \(predeterminado: 100\) | + +#### Salida + +| Parámetro | Tipo | Descripción | +| --------- | ---- | ----------- | +| `lists` | json | Array de listas | + +### `sendgrid_delete_list` + +Eliminar una lista de contactos de SendGrid + +#### Entrada + +| Parámetro | Tipo | Obligatorio | Descripción | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Sí | Clave API de SendGrid | +| `listId` | string | Sí | ID de la lista a eliminar | + +#### Salida + +| Parámetro | Tipo | Descripción | +| --------- | ---- | ----------- | +| `message` | string | Mensaje de éxito | + +### `sendgrid_add_contacts_to_list` + +Añadir o actualizar contactos y asignarlos a una lista en SendGrid (usa PUT /v3/marketing/contacts) + +#### Entrada + +| Parámetro | Tipo | Obligatorio | Descripción | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Sí | Clave API de SendGrid | +| `listId` | string | Sí | ID de la lista a la que añadir contactos | +| `contacts` | json | Sí | Array JSON de objetos de contacto. Cada contacto debe tener al menos: email \(o phone_number_id/external_id/anonymous_id\). Ejemplo: \[\{"email": "user@example.com", "first_name": "John"\}\] | + +#### Salida + +| Parámetro | Tipo | Descripción | +| --------- | ---- | ----------- | +| `jobId` | string | ID del trabajo para seguimiento de la operación asíncrona | +| `message` | string | Mensaje de estado | + +### `sendgrid_remove_contacts_from_list` + +Eliminar contactos de una lista específica en SendGrid + +#### Entrada + +| Parámetro | Tipo | Obligatorio | Descripción | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Sí | Clave API de SendGrid | +| `listId` | string | Sí | ID de la lista | +| `contactIds` | string | Sí | IDs de contactos separados por comas para eliminar de la lista | + +#### Salida + +| Parámetro | Tipo | Descripción | +| --------- | ---- | ----------- | +| `jobId` | string | ID del trabajo para la solicitud | + +### `sendgrid_create_template` + +Crear una nueva plantilla de correo electrónico en SendGrid + +#### Entrada + +| Parámetro | Tipo | Obligatorio | Descripción | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Sí | Clave API de SendGrid | +| `name` | string | Sí | Nombre de la plantilla | +| `generation` | string | No | Tipo de generación de plantilla \(legacy o dynamic, predeterminado: dynamic\) | + +#### Salida + +| Parámetro | Tipo | Descripción | +| --------- | ---- | ----------- | +| `id` | string | ID de la plantilla | +| `name` | string | Nombre de la plantilla | +| `generation` | string | Generación de la plantilla | +| `updatedAt` | string | Marca de tiempo de la última actualización | +| `versions` | json | Array de versiones de la plantilla | + +### `sendgrid_get_template` + +Obtener una plantilla específica por ID desde SendGrid + +#### Entrada + +| Parámetro | Tipo | Obligatorio | Descripción | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Sí | Clave API de SendGrid | +| `templateId` | string | Sí | ID de la plantilla | + +#### Salida + +| Parámetro | Tipo | Descripción | +| --------- | ---- | ----------- | +| `id` | string | ID de la plantilla | +| `name` | string | Nombre de la plantilla | +| `generation` | string | Generación de la plantilla | +| `updatedAt` | string | Marca de tiempo de la última actualización | +| `versions` | json | Array de versiones de la plantilla | + +### `sendgrid_list_templates` + +Obtener todas las plantillas de correo electrónico de SendGrid + +#### Entrada + +| Parámetro | Tipo | Obligatorio | Descripción | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Sí | Clave API de SendGrid | +| `generations` | string | No | Filtrar por generación \(legacy, dynamic, o ambas\) | +| `pageSize` | number | No | Número de plantillas a devolver por página \(predeterminado: 20\) | + +#### Salida + +| Parámetro | Tipo | Descripción | +| --------- | ---- | ----------- | +| `templates` | json | Array de plantillas | + +### `sendgrid_delete_template` + +Eliminar una plantilla de correo electrónico de SendGrid + +#### Entrada + +| Parámetro | Tipo | Obligatorio | Descripción | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Sí | Clave API de SendGrid | +| `templateId` | string | Sí | ID de la plantilla a eliminar | + +#### Salida + +| Parámetro | Tipo | Descripción | +| --------- | ---- | ----------- | +| `success` | boolean | Estado de éxito de la operación | +| `messageId` | string | ID del mensaje de correo electrónico \(send_mail\) | +| `id` | string | ID del recurso | +| `jobId` | string | ID del trabajo para operaciones asíncronas | +| `email` | string | Dirección de correo electrónico | +| `firstName` | string | Nombre | +| `lastName` | string | Apellido | +| `contacts` | json | Array de contactos | +| `contactCount` | number | Número de contactos | +| `lists` | json | Array de listas | +| `templates` | json | Array de plantillas | +| `message` | string | Estado o mensaje de éxito | +| `name` | string | Nombre del recurso | +| `generation` | string | Generación de plantilla | + +### `sendgrid_create_template_version` + +Crear una nueva versión de una plantilla de correo electrónico en SendGrid + +#### Entrada + +| Parámetro | Tipo | Obligatorio | Descripción | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Sí | Clave API de SendGrid | +| `templateId` | string | Sí | ID de la plantilla | +| `name` | string | Sí | Nombre de la versión | +| `subject` | string | Sí | Línea de asunto del correo electrónico | +| `htmlContent` | string | No | Contenido HTML de la plantilla | +| `plainContent` | string | No | Contenido de texto plano de la plantilla | +| `active` | boolean | No | Si esta versión está activa \(predeterminado: true\) | + +#### Salida + +| Parámetro | Tipo | Descripción | +| --------- | ---- | ----------- | +| `id` | string | ID de la versión | +| `templateId` | string | ID de la plantilla | +| `name` | string | Nombre de la versión | +| `subject` | string | Asunto del correo electrónico | +| `active` | boolean | Si esta versión está activa | +| `htmlContent` | string | Contenido HTML | +| `plainContent` | string | Contenido de texto plano | +| `updatedAt` | string | Marca de tiempo de la última actualización | + +## Notas + +- Categoría: `tools` +- Tipo: `sendgrid` diff --git a/apps/docs/content/docs/es/tools/smtp.mdx b/apps/docs/content/docs/es/tools/smtp.mdx new file mode 100644 index 0000000000..0596eb2a41 --- /dev/null +++ b/apps/docs/content/docs/es/tools/smtp.mdx @@ -0,0 +1,73 @@ +--- +title: SMTP +description: Envía correos electrónicos a través de cualquier servidor de correo SMTP +--- + +import { BlockInfoCard } from "@/components/ui/block-info-card" + + + +{/* MANUAL-CONTENT-START:intro */} +[SMTP (Simple Mail Transfer Protocol)](https://en.wikipedia.org/wiki/Simple_Mail_Transfer_Protocol) es el estándar fundamental para la transmisión de correos electrónicos a través de Internet. Al conectarte a cualquier servidor compatible con SMTP—como Gmail, Outlook, o la infraestructura de correo de tu organización—puedes enviar correos electrónicos de forma programática y automatizar tus comunicaciones salientes. + +La integración SMTP te permite personalizar completamente el envío de correos electrónicos mediante conectividad directa con el servidor, admitiendo casos de uso de correo electrónico tanto básicos como avanzados. Con SMTP, puedes controlar todos los aspectos de la entrega de mensajes, la gestión de destinatarios y el formato del contenido, lo que lo hace adecuado para notificaciones transaccionales, envíos masivos y cualquier flujo de trabajo automatizado que requiera una entrega robusta de correos electrónicos salientes. + +**Las características clave disponibles a través de la integración SMTP incluyen:** + +- **Entrega universal de correos electrónicos:** Envía correos electrónicos utilizando cualquier servidor SMTP configurando parámetros estándar de conexión al servidor. +- **Remitente y destinatarios personalizables:** Especifica la dirección del remitente, el nombre para mostrar, los destinatarios principales, así como los campos CC y CCO. +- **Soporte para contenido enriquecido:** Envía correos electrónicos de texto plano o con formato HTML enriquecido según tus requisitos. +- **Archivos adjuntos:** Incluye múltiples archivos como adjuntos en los correos electrónicos salientes. +- **Seguridad flexible:** Conéctate usando protocolos TLS, SSL o estándar (sin cifrar) según lo admita tu proveedor SMTP. +- **Encabezados avanzados:** Configura encabezados de respuesta y otras opciones avanzadas de correo electrónico para atender flujos de correo complejos e interacciones de usuario. + +Al integrar SMTP con Sim, los agentes y flujos de trabajo pueden enviar correos electrónicos de forma programática como parte de cualquier proceso automatizado—desde el envío de notificaciones y confirmaciones, hasta la automatización de comunicaciones externas, informes y entrega de documentos. Esto ofrece un enfoque altamente flexible e independiente del proveedor para gestionar el correo electrónico directamente dentro de tus procesos impulsados por IA. +{/* MANUAL-CONTENT-END */} + +## Instrucciones de uso + +Envía correos electrónicos utilizando cualquier servidor SMTP (Gmail, Outlook, servidores personalizados, etc.). Configura los ajustes de conexión SMTP y envía correos electrónicos con control total sobre el contenido, destinatarios y archivos adjuntos. + +## Herramientas + +### `smtp_send_mail` + +Enviar correos electrónicos a través del servidor SMTP + +#### Entrada + +| Parámetro | Tipo | Obligatorio | Descripción | +| --------- | ---- | -------- | ----------- | +| `smtpHost` | string | Sí | Nombre del host del servidor SMTP \(p. ej., smtp.gmail.com\) | +| `smtpPort` | number | Sí | Puerto del servidor SMTP \(587 para TLS, 465 para SSL\) | +| `smtpUsername` | string | Sí | Nombre de usuario para autenticación SMTP | +| `smtpPassword` | string | Sí | Contraseña para autenticación SMTP | +| `smtpSecure` | string | Sí | Protocolo de seguridad \(TLS, SSL o Ninguno\) | +| `from` | string | Sí | Dirección de correo electrónico del remitente | +| `to` | string | Sí | Dirección de correo electrónico del destinatario | +| `subject` | string | Sí | Asunto del correo electrónico | +| `body` | string | Sí | Contenido del cuerpo del correo electrónico | +| `contentType` | string | No | Tipo de contenido \(texto o html\) | +| `fromName` | string | No | Nombre para mostrar del remitente | +| `cc` | string | No | Destinatarios en CC \(separados por comas\) | +| `bcc` | string | No | Destinatarios en CCO \(separados por comas\) | +| `replyTo` | string | No | Dirección de correo electrónico de respuesta | +| `attachments` | file[] | No | Archivos para adjuntar al correo electrónico | + +#### Salida + +| Parámetro | Tipo | Descripción | +| --------- | ---- | ----------- | +| `success` | boolean | Si el correo electrónico se envió correctamente | +| `messageId` | string | ID del mensaje del servidor SMTP | +| `to` | string | Dirección de correo electrónico del destinatario | +| `subject` | string | Asunto del correo electrónico | +| `error` | string | Mensaje de error si el envío falló | + +## Notas + +- Categoría: `tools` +- Tipo: `smtp` diff --git a/apps/docs/content/docs/fr/tools/linkedin.mdx b/apps/docs/content/docs/fr/tools/linkedin.mdx new file mode 100644 index 0000000000..9c8395bab2 --- /dev/null +++ b/apps/docs/content/docs/fr/tools/linkedin.mdx @@ -0,0 +1,83 @@ +--- +title: LinkedIn +description: Partagez des publications et gérez votre présence LinkedIn +--- + +import { BlockInfoCard } from "@/components/ui/block-info-card" + + + +{/* MANUAL-CONTENT-START:intro */} +[LinkedIn](https://www.linkedin.com) est la plus grande plateforme de réseautage professionnel au monde, permettant aux utilisateurs de développer leur carrière, de se connecter avec leur réseau et de partager du contenu professionnel. LinkedIn est largement utilisé par des professionnels de tous secteurs pour le développement de leur marque personnelle, le recrutement, la recherche d'emploi et le développement commercial. + +Avec LinkedIn, vous pouvez facilement partager des publications sur votre fil personnel pour interagir avec votre réseau et accéder aux informations de votre profil pour mettre en valeur vos réalisations professionnelles. L'intégration automatisée avec Sim vous permet d'exploiter les fonctionnalités de LinkedIn de manière programmatique, permettant aux agents et aux flux de travail de publier des mises à jour, de générer des rapports sur votre présence professionnelle et de maintenir votre fil d'actualité actif sans effort manuel. + +Les principales fonctionnalités de LinkedIn disponibles via cette intégration comprennent : + +- **Partage de publications :** Publiez automatiquement des mises à jour professionnelles, des articles ou des annonces sur votre fil personnel LinkedIn. +- **Informations de profil :** Récupérez des informations détaillées sur votre profil LinkedIn pour les surveiller ou les utiliser dans des tâches en aval au sein de vos flux de travail. + +Ces capacités facilitent l'engagement de votre réseau LinkedIn et l'extension efficace de votre portée professionnelle dans le cadre de votre stratégie d'automatisation IA ou de flux de travail. +{/* MANUAL-CONTENT-END */} + +## Instructions d'utilisation + +Intégrez LinkedIn dans vos flux de travail. Partagez des publications sur votre fil personnel et accédez aux informations de votre profil LinkedIn. + +## Outils + +### `linkedin_share_post` + +Partager une publication sur votre fil personnel LinkedIn + +#### Entrée + +| Paramètre | Type | Obligatoire | Description | +| --------- | ---- | ---------- | ----------- | +| `text` | string | Oui | Le contenu textuel de votre publication LinkedIn | +| `visibility` | string | Non | Qui peut voir cette publication : "PUBLIC" ou "CONNECTIONS" \(par défaut : "PUBLIC"\) | +| `request` | string | Non | Pas de description | +| `output` | string | Non | Pas de description | +| `output` | string | Non | Pas de description | +| `specificContent` | string | Non | Pas de description | +| `shareCommentary` | string | Non | Pas de description | +| `visibility` | string | Non | Pas de description | +| `headers` | string | Non | Pas de description | +| `output` | string | Non | Pas de description | +| `output` | string | Non | Pas de description | +| `output` | string | Non | Pas de description | + +#### Sortie + +| Paramètre | Type | Description | +| --------- | ---- | ----------- | +| `success` | boolean | Statut de réussite de l'opération | +| `postId` | string | ID du post créé | +| `profile` | json | Informations du profil LinkedIn | +| `error` | string | Message d'erreur si l'opération a échoué | + +### `linkedin_get_profile` + +Récupérer les informations de votre profil LinkedIn + +#### Entrée + +| Paramètre | Type | Obligatoire | Description | +| --------- | ---- | ----------- | ----------- | + +#### Sortie + +| Paramètre | Type | Description | +| --------- | ---- | ----------- | +| `success` | boolean | Statut de réussite de l'opération | +| `postId` | string | ID du post créé | +| `profile` | json | Informations du profil LinkedIn | +| `error` | string | Message d'erreur si l'opération a échoué | + +## Notes + +- Catégorie : `tools` +- Type : `linkedin` diff --git a/apps/docs/content/docs/fr/tools/mailgun.mdx b/apps/docs/content/docs/fr/tools/mailgun.mdx new file mode 100644 index 0000000000..39d0bc982b --- /dev/null +++ b/apps/docs/content/docs/fr/tools/mailgun.mdx @@ -0,0 +1,216 @@ +--- +title: Mailgun +description: Envoyez des e-mails et gérez des listes de diffusion avec Mailgun +--- + +import { BlockInfoCard } from "@/components/ui/block-info-card" + + + +{/* MANUAL-CONTENT-START:intro */} +[Mailgun](https://www.mailgun.com) est un service puissant d'envoi d'e-mails conçu pour les développeurs et les entreprises afin d'envoyer, recevoir et suivre des e-mails sans effort. Mailgun vous permet d'exploiter des API robustes pour des e-mails transactionnels et marketing fiables, une gestion flexible des listes de diffusion et un suivi avancé des événements. + +Avec l'ensemble complet de fonctionnalités de Mailgun, vous pouvez automatiser les opérations clés liées aux e-mails et surveiller étroitement la délivrabilité et l'engagement des destinataires. Cela en fait une solution idéale pour l'automatisation des flux de travail où les communications, les notifications et les campagnes d'e-mails sont des éléments essentiels de vos processus. + +Les fonctionnalités clés de Mailgun comprennent : + +- **Envoi d'e-mails transactionnels :** Livrez des e-mails à haut volume tels que des notifications de compte, des reçus, des alertes et des réinitialisations de mot de passe. +- **Contenu d'e-mail enrichi :** Envoyez des e-mails en texte brut et en HTML, et utilisez des balises pour catégoriser et suivre vos messages. +- **Gestion des listes de diffusion :** Créez, mettez à jour et gérez des listes de diffusion et des membres pour envoyer efficacement des communications groupées. +- **Informations sur les domaines :** Récupérez des détails sur vos domaines d'envoi pour surveiller la configuration et la santé. +- **Suivi des événements :** Analysez la délivrabilité des e-mails et l'engagement avec des données détaillées sur les messages envoyés. +- **Récupération des messages :** Accédez aux messages stockés pour des besoins de conformité, d'analyse ou de dépannage. + +En intégrant Mailgun à Sim, vos agents sont habilités à envoyer des e-mails par programmation, gérer des listes d'e-mails, accéder aux informations de domaine et surveiller les événements en temps réel dans le cadre de flux de travail automatisés. Cela permet un engagement intelligent et basé sur les données avec vos utilisateurs directement à partir de vos processus alimentés par l'IA. +{/* MANUAL-CONTENT-END */} + +## Instructions d'utilisation + +Intégrez Mailgun dans votre flux de travail. Envoyez des e-mails transactionnels, gérez des listes de diffusion et leurs membres, consultez les informations de domaine et suivez les événements liés aux e-mails. Prend en charge les e-mails texte et HTML, les balises pour le suivi et une gestion complète des listes. + +## Outils + +### `mailgun_send_message` + +Envoyer un e-mail en utilisant l'API Mailgun + +#### Entrée + +| Paramètre | Type | Obligatoire | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | chaîne | Oui | Clé API Mailgun | +| `domain` | chaîne | Oui | Domaine Mailgun \(ex. : mg.example.com\) | +| `from` | chaîne | Oui | Adresse e-mail de l'expéditeur | +| `to` | chaîne | Oui | Adresse e-mail du destinataire \(séparées par des virgules pour plusieurs\) | +| `subject` | chaîne | Oui | Objet de l'e-mail | +| `text` | chaîne | Non | Corps de l'e-mail en texte brut | +| `html` | chaîne | Non | Corps de l'e-mail en HTML | +| `cc` | chaîne | Non | Adresse e-mail en CC \(séparées par des virgules pour plusieurs\) | +| `bcc` | chaîne | Non | Adresse e-mail en BCC \(séparées par des virgules pour plusieurs\) | +| `tags` | chaîne | Non | Tags pour l'e-mail \(séparés par des virgules\) | + +#### Sortie + +| Paramètre | Type | Description | +| --------- | ---- | ----------- | +| `success` | booléen | Indique si le message a été envoyé avec succès | +| `id` | chaîne | ID du message | +| `message` | chaîne | Message de réponse de Mailgun | + +### `mailgun_get_message` + +Récupérer un message stocké par sa clé + +#### Entrée + +| Paramètre | Type | Obligatoire | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | chaîne | Oui | Clé API Mailgun | +| `domain` | chaîne | Oui | Domaine Mailgun | +| `messageKey` | chaîne | Oui | Clé de stockage du message | + +#### Sortie + +| Paramètre | Type | Description | +| --------- | ---- | ----------- | +| `success` | boolean | Indique si la requête a réussi | +| `recipients` | string | Destinataires du message | +| `from` | string | Email de l'expéditeur | +| `subject` | string | Objet du message | +| `bodyPlain` | string | Corps du texte brut | +| `strippedText` | string | Texte épuré | +| `strippedSignature` | string | Signature épurée | +| `bodyHtml` | string | Corps HTML | +| `strippedHtml` | string | HTML épuré | +| `attachmentCount` | number | Nombre de pièces jointes | +| `timestamp` | number | Horodatage du message | +| `messageHeaders` | json | En-têtes du message | +| `contentIdMap` | json | Carte des ID de contenu | + +### `mailgun_list_messages` + +Liste des événements (journaux) pour les messages envoyés via Mailgun + +#### Entrée + +| Paramètre | Type | Obligatoire | Description | +| --------- | ---- | ----------- | ----------- | +| `apiKey` | string | Oui | Clé API Mailgun | +| `domain` | string | Oui | Domaine Mailgun | +| `event` | string | Non | Filtrer par type d'événement \(accepted, delivered, failed, opened, clicked, etc.\) | +| `limit` | number | Non | Nombre maximum d'événements à retourner \(par défaut : 100\) | + +#### Sortie + +| Paramètre | Type | Description | +| --------- | ---- | ----------- | +| `success` | boolean | Indique si la requête a réussi | +| `items` | json | Tableau d'éléments d'événements | +| `paging` | json | Informations de pagination | + +### `mailgun_create_mailing_list` + +Créer une nouvelle liste de diffusion + +#### Entrée + +| Paramètre | Type | Obligatoire | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | chaîne | Oui | Clé API Mailgun | +| `address` | chaîne | Oui | Adresse de la liste de diffusion \(ex., liste@exemple.com\) | +| `name` | chaîne | Non | Nom de la liste de diffusion | +| `description` | chaîne | Non | Description de la liste de diffusion | +| `accessLevel` | chaîne | Non | Niveau d'accès : readonly, members, ou everyone | + +#### Sortie + +| Paramètre | Type | Description | +| --------- | ---- | ----------- | +| `success` | booléen | Indique si la liste a été créée avec succès | +| `message` | chaîne | Message de réponse | +| `list` | json | Détails de la liste de diffusion créée | + +### `mailgun_get_mailing_list` + +Obtenir les détails d'une liste de diffusion + +#### Entrée + +| Paramètre | Type | Obligatoire | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | chaîne | Oui | Clé API Mailgun | +| `address` | chaîne | Oui | Adresse de la liste de diffusion | + +#### Sortie + +| Paramètre | Type | Description | +| --------- | ---- | ----------- | +| `success` | booléen | Indique si la requête a réussi | +| `list` | json | Détails de la liste de diffusion | + +### `mailgun_add_list_member` + +Ajouter un membre à une liste de diffusion + +#### Entrée + +| Paramètre | Type | Obligatoire | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | chaîne | Oui | Clé API Mailgun | +| `listAddress` | chaîne | Oui | Adresse de la liste de diffusion | +| `address` | chaîne | Oui | Adresse e-mail du membre | +| `name` | chaîne | Non | Nom du membre | +| `vars` | chaîne | Non | Chaîne JSON des variables personnalisées | +| `subscribed` | booléen | Non | Indique si le membre est abonné | + +#### Sortie + +| Paramètre | Type | Description | +| --------- | ---- | ----------- | +| `success` | boolean | Indique si le membre a été ajouté avec succès | +| `message` | string | Message de réponse | +| `member` | json | Détails du membre ajouté | + +### `mailgun_list_domains` + +Lister tous les domaines de votre compte Mailgun + +#### Entrée + +| Paramètre | Type | Obligatoire | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Oui | Clé API Mailgun | + +#### Sortie + +| Paramètre | Type | Description | +| --------- | ---- | ----------- | +| `success` | boolean | Indique si la requête a réussi | +| `totalCount` | number | Nombre total de domaines | +| `items` | json | Tableau d'objets de domaine | + +### `mailgun_get_domain` + +Obtenir les détails d'un domaine spécifique + +#### Entrée + +| Paramètre | Type | Obligatoire | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Oui | Clé API Mailgun | +| `domain` | string | Oui | Nom de domaine | + +#### Sortie + +| Paramètre | Type | Description | +| --------- | ---- | ----------- | +| `success` | boolean | Indique si la requête a réussi | +| `domain` | json | Détails du domaine | + +## Notes + +- Catégorie : `tools` +- Type : `mailgun` diff --git a/apps/docs/content/docs/fr/tools/sendgrid.mdx b/apps/docs/content/docs/fr/tools/sendgrid.mdx new file mode 100644 index 0000000000..d4496a3bb3 --- /dev/null +++ b/apps/docs/content/docs/fr/tools/sendgrid.mdx @@ -0,0 +1,392 @@ +--- +title: SendGrid +description: Envoyez des emails et gérez des contacts, des listes et des modèles + avec SendGrid +--- + +import { BlockInfoCard } from "@/components/ui/block-info-card" + + + +{/* MANUAL-CONTENT-START:intro */} +[SendGrid](https://sendgrid.com) est une plateforme d'envoi d'emails cloud de premier plan, reconnue par les développeurs et les entreprises pour l'envoi fiable d'emails transactionnels et marketing à grande échelle. Grâce à ses API robustes et ses outils puissants, SendGrid vous permet de gérer tous les aspects de votre communication par email, de l'envoi de notifications et de reçus à la gestion de campagnes marketing complexes. + +SendGrid offre aux utilisateurs une suite complète d'opérations email, permettant d'automatiser les flux de travail email critiques et de gérer étroitement les listes de contacts, les modèles et l'engagement des destinataires. Son intégration transparente avec Sim permet aux agents et aux workflows de délivrer des messages ciblés, de maintenir des listes dynamiques de contacts et de destinataires, de déclencher des emails personnalisés via des modèles et de suivre les résultats en temps réel. + +Les fonctionnalités clés de SendGrid comprennent : + +- **Email transactionnel :** envoi automatisé d'emails transactionnels à haut volume (comme des notifications, reçus et réinitialisations de mot de passe). +- **Modèles dynamiques :** utilisation de modèles HTML riches ou textuels avec des données dynamiques pour une communication hautement personnalisée à grande échelle. +- **Gestion des contacts :** ajout et mise à jour de contacts marketing, gestion des listes de destinataires et ciblage de segments pour les campagnes. +- **Prise en charge des pièces jointes :** inclusion d'une ou plusieurs pièces jointes dans vos emails. +- **Couverture API complète :** gestion programmatique des emails, contacts, listes, modèles, groupes de suppression, et plus encore. + +En connectant SendGrid avec Sim, vos agents peuvent : + +- Envoyer des emails simples et avancés (avec modèles ou multi-destinataires) dans le cadre de n'importe quel workflow. +- Gérer et segmenter automatiquement les contacts et les listes. +- Exploiter des modèles pour assurer cohérence et personnalisation dynamique. +- Suivre et répondre à l'engagement des emails au sein de vos processus automatisés. + +Cette intégration vous permet d'automatiser tous les flux de communication critiques, de garantir que les messages atteignent le bon public et de maintenir le contrôle sur la stratégie de messagerie de votre organisation, directement à partir des flux de travail Sim. +{/* MANUAL-CONTENT-END */} + +## Instructions d'utilisation + +Intégrez SendGrid dans votre flux de travail. Envoyez des e-mails transactionnels, gérez les contacts et les listes marketing, et travaillez avec des modèles d'e-mail. Prend en charge les modèles dynamiques, les pièces jointes et la gestion complète des contacts. + +## Outils + +### `sendgrid_send_mail` + +Envoyer un e-mail en utilisant l'API SendGrid + +#### Entrée + +| Paramètre | Type | Obligatoire | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Oui | Clé API SendGrid | +| `from` | string | Oui | Adresse e-mail de l'expéditeur \(doit être vérifiée dans SendGrid\) | +| `fromName` | string | Non | Nom de l'expéditeur | +| `to` | string | Oui | Adresse e-mail du destinataire | +| `toName` | string | Non | Nom du destinataire | +| `subject` | string | Non | Objet de l'e-mail \(obligatoire sauf si vous utilisez un modèle avec un objet prédéfini\) | +| `content` | string | Non | Contenu du corps de l'e-mail \(obligatoire sauf si vous utilisez un modèle avec un contenu prédéfini\) | +| `contentType` | string | Non | Type de contenu \(text/plain ou text/html\) | +| `cc` | string | Non | Adresse e-mail en CC | +| `bcc` | string | Non | Adresse e-mail en BCC | +| `replyTo` | string | Non | Adresse e-mail de réponse | +| `replyToName` | string | Non | Nom de réponse | +| `attachments` | file[] | Non | Fichiers à joindre à l'e-mail | +| `templateId` | string | Non | ID du modèle SendGrid à utiliser | +| `dynamicTemplateData` | json | Non | Objet JSON de données de modèle dynamique | + +#### Sortie + +| Paramètre | Type | Description | +| --------- | ---- | ----------- | +| `success` | boolean | Indique si l'e-mail a été envoyé avec succès | +| `messageId` | string | ID du message SendGrid | +| `to` | string | Adresse e-mail du destinataire | +| `subject` | string | Objet de l'e-mail | + +### `sendgrid_add_contact` + +Ajouter un nouveau contact à SendGrid + +#### Entrée + +| Paramètre | Type | Obligatoire | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Oui | Clé API SendGrid | +| `email` | string | Oui | Adresse e-mail du contact | +| `firstName` | string | Non | Prénom du contact | +| `lastName` | string | Non | Nom de famille du contact | +| `customFields` | json | Non | Objet JSON de paires clé-valeur de champs personnalisés (utilisez les ID de champ comme e1_T, e2_N, e3_D, pas les noms de champ) | +| `listIds` | string | Non | Liste d'ID séparés par des virgules pour ajouter le contact | + +#### Sortie + +| Paramètre | Type | Description | +| --------- | ---- | ----------- | +| `jobId` | string | ID de tâche pour suivre la création asynchrone du contact | +| `email` | string | Adresse e-mail du contact | +| `firstName` | string | Prénom du contact | +| `lastName` | string | Nom de famille du contact | +| `message` | string | Message d'état | + +### `sendgrid_get_contact` + +Obtenir un contact spécifique par ID depuis SendGrid + +#### Entrée + +| Paramètre | Type | Obligatoire | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Oui | Clé API SendGrid | +| `contactId` | string | Oui | ID du contact | + +#### Sortie + +| Paramètre | Type | Description | +| --------- | ---- | ----------- | +| `id` | string | ID du contact | +| `email` | string | Adresse e-mail du contact | +| `firstName` | string | Prénom du contact | +| `lastName` | string | Nom de famille du contact | +| `createdAt` | string | Horodatage de création | +| `updatedAt` | string | Horodatage de dernière mise à jour | +| `listIds` | json | Tableau des ID de listes auxquelles le contact appartient | +| `customFields` | json | Valeurs des champs personnalisés | + +### `sendgrid_search_contacts` + +Rechercher des contacts dans SendGrid à l'aide d'une requête + +#### Entrée + +| Paramètre | Type | Obligatoire | Description | +| --------- | ---- | ---------- | ----------- | +| `apiKey` | string | Oui | Clé API SendGrid | +| `query` | string | Oui | Requête de recherche (par ex., "email LIKE '%example.com%' AND CONTAINS(list_ids, 'list-id')") | + +#### Sortie + +| Paramètre | Type | Description | +| --------- | ---- | ----------- | +| `contacts` | json | Tableau des contacts correspondants | +| `contactCount` | number | Nombre total de contacts trouvés | + +### `sendgrid_delete_contacts` + +Supprimer un ou plusieurs contacts de SendGrid + +#### Entrée + +| Paramètre | Type | Obligatoire | Description | +| --------- | ---- | ---------- | ----------- | +| `apiKey` | string | Oui | Clé API SendGrid | +| `contactIds` | string | Oui | ID de contacts séparés par des virgules à supprimer | + +#### Sortie + +| Paramètre | Type | Description | +| --------- | ---- | ----------- | +| `jobId` | string | ID de tâche pour la demande de suppression | + +### `sendgrid_create_list` + +Créer une nouvelle liste de contacts dans SendGrid + +#### Entrée + +| Paramètre | Type | Obligatoire | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | chaîne | Oui | Clé API SendGrid | +| `name` | chaîne | Oui | Nom de la liste | + +#### Sortie + +| Paramètre | Type | Description | +| --------- | ---- | ----------- | +| `id` | chaîne | ID de la liste | +| `name` | chaîne | Nom de la liste | +| `contactCount` | nombre | Nombre de contacts dans la liste | + +### `sendgrid_get_list` + +Obtenir une liste spécifique par ID depuis SendGrid + +#### Entrée + +| Paramètre | Type | Obligatoire | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | chaîne | Oui | Clé API SendGrid | +| `listId` | chaîne | Oui | ID de la liste | + +#### Sortie + +| Paramètre | Type | Description | +| --------- | ---- | ----------- | +| `id` | chaîne | ID de la liste | +| `name` | chaîne | Nom de la liste | +| `contactCount` | nombre | Nombre de contacts dans la liste | + +### `sendgrid_list_all_lists` + +Obtenir toutes les listes de contacts depuis SendGrid + +#### Entrée + +| Paramètre | Type | Obligatoire | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | chaîne | Oui | Clé API SendGrid | +| `pageSize` | nombre | Non | Nombre de listes à renvoyer par page \(par défaut : 100\) | + +#### Sortie + +| Paramètre | Type | Description | +| --------- | ---- | ----------- | +| `lists` | json | Tableau de listes | + +### `sendgrid_delete_list` + +Supprimer une liste de contacts de SendGrid + +#### Entrée + +| Paramètre | Type | Obligatoire | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | chaîne | Oui | Clé API SendGrid | +| `listId` | chaîne | Oui | ID de la liste à supprimer | + +#### Sortie + +| Paramètre | Type | Description | +| --------- | ---- | ----------- | +| `message` | chaîne | Message de succès | + +### `sendgrid_add_contacts_to_list` + +Ajouter ou mettre à jour des contacts et les assigner à une liste dans SendGrid (utilise PUT /v3/marketing/contacts) + +#### Entrée + +| Paramètre | Type | Obligatoire | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | chaîne | Oui | Clé API SendGrid | +| `listId` | chaîne | Oui | ID de la liste à laquelle ajouter les contacts | +| `contacts` | json | Oui | Tableau JSON d'objets contact. Chaque contact doit avoir au minimum : email \(ou phone_number_id/external_id/anonymous_id\). Exemple : \[\{"email": "user@example.com", "first_name": "John"\}\] | + +#### Sortie + +| Paramètre | Type | Description | +| --------- | ---- | ----------- | +| `jobId` | chaîne | ID de tâche pour suivre l'opération asynchrone | +| `message` | chaîne | Message de statut | + +### `sendgrid_remove_contacts_from_list` + +Supprimer des contacts d'une liste spécifique dans SendGrid + +#### Entrée + +| Paramètre | Type | Obligatoire | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | chaîne | Oui | Clé API SendGrid | +| `listId` | chaîne | Oui | ID de la liste | +| `contactIds` | chaîne | Oui | IDs de contacts séparés par des virgules à supprimer de la liste | + +#### Sortie + +| Paramètre | Type | Description | +| --------- | ---- | ----------- | +| `jobId` | string | ID de tâche pour la requête | + +### `sendgrid_create_template` + +Créer un nouveau modèle d'e-mail dans SendGrid + +#### Entrée + +| Paramètre | Type | Obligatoire | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Oui | Clé API SendGrid | +| `name` | string | Oui | Nom du modèle | +| `generation` | string | Non | Type de génération de modèle \(legacy ou dynamic, par défaut : dynamic\) | + +#### Sortie + +| Paramètre | Type | Description | +| --------- | ---- | ----------- | +| `id` | string | ID du modèle | +| `name` | string | Nom du modèle | +| `generation` | string | Génération du modèle | +| `updatedAt` | string | Horodatage de la dernière mise à jour | +| `versions` | json | Tableau des versions du modèle | + +### `sendgrid_get_template` + +Obtenir un modèle spécifique par ID depuis SendGrid + +#### Entrée + +| Paramètre | Type | Obligatoire | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Oui | Clé API SendGrid | +| `templateId` | string | Oui | ID du modèle | + +#### Sortie + +| Paramètre | Type | Description | +| --------- | ---- | ----------- | +| `id` | string | ID du modèle | +| `name` | string | Nom du modèle | +| `generation` | string | Génération du modèle | +| `updatedAt` | string | Horodatage de la dernière mise à jour | +| `versions` | json | Tableau des versions du modèle | + +### `sendgrid_list_templates` + +Obtenir tous les modèles d'e-mail de SendGrid + +#### Entrée + +| Paramètre | Type | Obligatoire | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | chaîne | Oui | Clé API SendGrid | +| `generations` | chaîne | Non | Filtrer par génération \(legacy, dynamic, ou les deux\) | +| `pageSize` | nombre | Non | Nombre de modèles à renvoyer par page \(par défaut : 20\) | + +#### Sortie + +| Paramètre | Type | Description | +| --------- | ---- | ----------- | +| `templates` | json | Tableau de modèles | + +### `sendgrid_delete_template` + +Supprimer un modèle d'e-mail de SendGrid + +#### Entrée + +| Paramètre | Type | Obligatoire | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | chaîne | Oui | Clé API SendGrid | +| `templateId` | chaîne | Oui | ID du modèle à supprimer | + +#### Sortie + +| Paramètre | Type | Description | +| --------- | ---- | ----------- | +| `success` | booléen | Statut de réussite de l'opération | +| `messageId` | chaîne | ID du message e-mail \(send_mail\) | +| `id` | chaîne | ID de la ressource | +| `jobId` | chaîne | ID de tâche pour les opérations asynchrones | +| `email` | chaîne | Adresse e-mail | +| `firstName` | chaîne | Prénom | +| `lastName` | chaîne | Nom de famille | +| `contacts` | json | Tableau de contacts | +| `contactCount` | nombre | Nombre de contacts | +| `lists` | json | Tableau de listes | +| `templates` | json | Tableau de modèles | +| `message` | chaîne | Statut ou message de réussite | +| `name` | chaîne | Nom de la ressource | +| `generation` | chaîne | Génération du modèle | + +### `sendgrid_create_template_version` + +Créer une nouvelle version d'un modèle d'e-mail dans SendGrid + +#### Entrée + +| Paramètre | Type | Obligatoire | Description | +| --------- | ---- | ---------- | ----------- | +| `apiKey` | chaîne | Oui | Clé API SendGrid | +| `templateId` | chaîne | Oui | ID du modèle | +| `name` | chaîne | Oui | Nom de la version | +| `subject` | chaîne | Oui | Objet de l'e-mail | +| `htmlContent` | chaîne | Non | Contenu HTML du modèle | +| `plainContent` | chaîne | Non | Contenu texte brut du modèle | +| `active` | booléen | Non | Si cette version est active \(par défaut : true\) | + +#### Sortie + +| Paramètre | Type | Description | +| --------- | ---- | ----------- | +| `id` | chaîne | ID de la version | +| `templateId` | chaîne | ID du modèle | +| `name` | chaîne | Nom de la version | +| `subject` | chaîne | Objet de l'e-mail | +| `active` | booléen | Si cette version est active | +| `htmlContent` | chaîne | Contenu HTML | +| `plainContent` | chaîne | Contenu texte brut | +| `updatedAt` | chaîne | Horodatage de la dernière mise à jour | + +## Notes + +- Catégorie : `tools` +- Type : `sendgrid` diff --git a/apps/docs/content/docs/fr/tools/smtp.mdx b/apps/docs/content/docs/fr/tools/smtp.mdx new file mode 100644 index 0000000000..d8205cdd64 --- /dev/null +++ b/apps/docs/content/docs/fr/tools/smtp.mdx @@ -0,0 +1,73 @@ +--- +title: SMTP +description: Envoyez des emails via n'importe quel serveur de messagerie SMTP +--- + +import { BlockInfoCard } from "@/components/ui/block-info-card" + + + +{/* MANUAL-CONTENT-START:intro */} +[SMTP (Simple Mail Transfer Protocol)](https://en.wikipedia.org/wiki/Simple_Mail_Transfer_Protocol) est la norme fondamentale pour la transmission d'emails sur Internet. En vous connectant à n'importe quel serveur compatible SMTP—comme Gmail, Outlook, ou l'infrastructure de messagerie de votre organisation—vous pouvez envoyer des emails de manière programmatique et automatiser vos communications sortantes. + +L'intégration SMTP vous permet de personnaliser entièrement l'envoi d'emails grâce à une connectivité directe au serveur, prenant en charge les cas d'utilisation d'email basiques et avancés. Avec SMTP, vous pouvez contrôler tous les aspects de la livraison des messages, de la gestion des destinataires et du formatage du contenu, ce qui le rend adapté aux notifications transactionnelles, aux envois en masse et à tout flux de travail automatisé nécessitant une livraison robuste d'emails sortants. + +**Les fonctionnalités clés disponibles via l'intégration SMTP incluent :** + +- **Livraison universelle d'emails :** Envoyez des emails en utilisant n'importe quel serveur SMTP en configurant les paramètres de connexion standard. +- **Expéditeur et destinataires personnalisables :** Spécifiez l'adresse de l'expéditeur, le nom d'affichage, les destinataires principaux, ainsi que les champs CC et BCC. +- **Prise en charge de contenu enrichi :** Envoyez des emails en texte brut ou au format HTML richement formaté selon vos besoins. +- **Pièces jointes :** Incluez plusieurs fichiers en pièces jointes dans les emails sortants. +- **Sécurité flexible :** Connectez-vous en utilisant les protocoles TLS, SSL ou standard (non chiffré) selon ce que prend en charge votre fournisseur SMTP. +- **En-têtes avancés :** Définissez les en-têtes de réponse et d'autres options d'email avancées pour répondre aux flux de messagerie complexes et aux interactions utilisateur. + +En intégrant SMTP avec Sim, les agents et les flux de travail peuvent envoyer des emails de manière programmatique dans le cadre de tout processus automatisé—allant de l'envoi de notifications et de confirmations à l'automatisation des communications externes, des rapports et de la livraison de documents. Cela offre une approche hautement flexible et indépendante du fournisseur pour gérer les emails directement au sein de vos processus pilotés par l'IA. +{/* MANUAL-CONTENT-END */} + +## Instructions d'utilisation + +Envoyez des emails en utilisant n'importe quel serveur SMTP (Gmail, Outlook, serveurs personnalisés, etc.). Configurez les paramètres de connexion SMTP et envoyez des emails avec un contrôle total sur le contenu, les destinataires et les pièces jointes. + +## Outils + +### `smtp_send_mail` + +Envoyer des emails via un serveur SMTP + +#### Entrée + +| Paramètre | Type | Obligatoire | Description | +| --------- | ---- | ----------- | ----------- | +| `smtpHost` | string | Oui | Nom d'hôte du serveur SMTP \(ex., smtp.gmail.com\) | +| `smtpPort` | number | Oui | Port du serveur SMTP \(587 pour TLS, 465 pour SSL\) | +| `smtpUsername` | string | Oui | Nom d'utilisateur pour l'authentification SMTP | +| `smtpPassword` | string | Oui | Mot de passe pour l'authentification SMTP | +| `smtpSecure` | string | Oui | Protocole de sécurité \(TLS, SSL ou Aucun\) | +| `from` | string | Oui | Adresse email de l'expéditeur | +| `to` | string | Oui | Adresse email du destinataire | +| `subject` | string | Oui | Objet de l'email | +| `body` | string | Oui | Contenu du corps de l'email | +| `contentType` | string | Non | Type de contenu \(texte ou html\) | +| `fromName` | string | Non | Nom d'affichage de l'expéditeur | +| `cc` | string | Non | Destinataires en copie \(séparés par des virgules\) | +| `bcc` | string | Non | Destinataires en copie cachée \(séparés par des virgules\) | +| `replyTo` | string | Non | Adresse email de réponse | +| `attachments` | file[] | Non | Fichiers à joindre à l'email | + +#### Sortie + +| Paramètre | Type | Description | +| --------- | ---- | ----------- | +| `success` | boolean | Indique si l'email a été envoyé avec succès | +| `messageId` | string | ID du message du serveur SMTP | +| `to` | string | Adresse email du destinataire | +| `subject` | string | Objet de l'email | +| `error` | string | Message d'erreur si l'envoi a échoué | + +## Notes + +- Catégorie : `tools` +- Type : `smtp` diff --git a/apps/docs/content/docs/ja/tools/linkedin.mdx b/apps/docs/content/docs/ja/tools/linkedin.mdx new file mode 100644 index 0000000000..ec541b4c2e --- /dev/null +++ b/apps/docs/content/docs/ja/tools/linkedin.mdx @@ -0,0 +1,83 @@ +--- +title: LinkedIn +description: 投稿を共有し、LinkedInのプレゼンスを管理する +--- + +import { BlockInfoCard } from "@/components/ui/block-info-card" + + + +{/* MANUAL-CONTENT-START:intro */} +[LinkedIn](https://www.linkedin.com)は世界最大のプロフェッショナルネットワーキングプラットフォームで、ユーザーがキャリアを構築し、ネットワークとつながり、専門的なコンテンツを共有することを可能にします。LinkedInは、個人ブランディング、採用活動、求職活動、ビジネス開発など、様々な業界のプロフェッショナルに広く利用されています。 + +LinkedInを使用すると、個人フィードに投稿を簡単に共有してネットワークとエンゲージメントを取ったり、プロフェッショナルな実績を強調するためにプロフィール情報にアクセスしたりできます。Simとの自動統合により、LinkedInの機能をプログラムで活用できるようになり、エージェントやワークフローが更新を投稿したり、プロフェッショナルなプレゼンスについてレポートしたり、手動の作業なしにフィードをアクティブに保つことが可能になります。 + +この統合を通じて利用可能な主なLinkedIn機能には以下が含まれます: + +- **投稿の共有:** プロフェッショナルな更新、記事、またはお知らせをLinkedInの個人フィードに自動的に公開します。 +- **プロフィール情報:** LinkedInプロフィールに関する詳細情報を取得し、ワークフロー内での監視や下流タスクでの使用が可能です。 + +これらの機能により、AIやワークフロー自動化戦略の一部として、LinkedInネットワークとのエンゲージメントを維持し、プロフェッショナルなリーチを効率的に拡大することが容易になります。 +{/* MANUAL-CONTENT-END */} + +## 使用方法 + +LinkedInをワークフローに統合します。個人フィードに投稿を共有し、LinkedInプロフィール情報にアクセスします。 + +## ツール + +### `linkedin_share_post` + +LinkedInの個人フィードに投稿を共有する + +#### 入力 + +| パラメータ | 型 | 必須 | 説明 | +| --------- | ---- | -------- | ----------- | +| `text` | string | はい | LinkedInの投稿のテキスト内容 | +| `visibility` | string | いいえ | この投稿を見ることができる人:「PUBLIC」または「CONNECTIONS」\(デフォルト:「PUBLIC」\) | +| `request` | string | いいえ | 説明なし | +| `output` | string | いいえ | 説明なし | +| `output` | string | いいえ | 説明なし | +| `specificContent` | string | いいえ | 説明なし | +| `shareCommentary` | string | いいえ | 説明なし | +| `visibility` | string | いいえ | 説明なし | +| `headers` | string | いいえ | 説明なし | +| `output` | string | いいえ | 説明なし | +| `output` | string | いいえ | 説明なし | +| `output` | string | いいえ | 説明なし | + +#### 出力 + +| パラメータ | 型 | 説明 | +| --------- | ---- | ----------- | +| `success` | boolean | 操作成功ステータス | +| `postId` | string | 作成された投稿ID | +| `profile` | json | LinkedInプロフィール情報 | +| `error` | string | 操作が失敗した場合のエラーメッセージ | + +### `linkedin_get_profile` + +LinkedInプロフィール情報を取得する + +#### 入力 + +| パラメータ | 型 | 必須 | 説明 | +| --------- | ---- | -------- | ----------- | + +#### 出力 + +| パラメータ | 型 | 説明 | +| --------- | ---- | ----------- | +| `success` | boolean | 操作成功ステータス | +| `postId` | string | 作成された投稿ID | +| `profile` | json | LinkedInプロフィール情報 | +| `error` | string | 操作が失敗した場合のエラーメッセージ | + +## 注意事項 + +- カテゴリー: `tools` +- タイプ: `linkedin` diff --git a/apps/docs/content/docs/ja/tools/mailgun.mdx b/apps/docs/content/docs/ja/tools/mailgun.mdx new file mode 100644 index 0000000000..82083e2e47 --- /dev/null +++ b/apps/docs/content/docs/ja/tools/mailgun.mdx @@ -0,0 +1,216 @@ +--- +title: Mailgun +description: Mailgunでメールを送信し、メーリングリストを管理する +--- + +import { BlockInfoCard } from "@/components/ui/block-info-card" + + + +{/* MANUAL-CONTENT-START:intro */} +[Mailgun](https://www.mailgun.com)は、開発者やビジネス向けに設計された強力なメール配信サービスで、メールの送受信やトラッキングを簡単に行うことができます。Mailgunを使用すると、信頼性の高いトランザクションメールやマーケティングメール、柔軟なメーリングリスト管理、高度なイベントトラッキングのための堅牢なAPIを活用できます。 + +Mailgunの包括的な機能セットにより、主要なメール操作を自動化し、配信可能性や受信者のエンゲージメントを緊密に監視することができます。これにより、コミュニケーション、通知、キャンペーンメールがワークフローの中核となるプロセスの理想的なソリューションとなります。 + +Mailgunの主な機能には以下が含まれます: + +- **トランザクションメール送信:** アカウント通知、領収書、アラート、パスワードリセットなどの大量メールを配信。 +- **リッチメールコンテンツ:** プレーンテキストとHTMLの両方のメールを送信し、タグを使用してメッセージを分類・追跡。 +- **メーリングリスト管理:** メーリングリストとメンバーを作成、更新、管理して、グループコミュニケーションを効率的に送信。 +- **ドメイン情報:** 送信ドメインに関する詳細を取得して、構成と健全性を監視。 +- **イベントトラッキング:** 送信メッセージに関する詳細なイベントデータで、メールの配信可能性とエンゲージメントを分析。 +- **メッセージ取得:** コンプライアンス、分析、またはトラブルシューティングのニーズのために保存されたメッセージにアクセス。 + +MailgunをSimに統合することで、エージェントはプログラムによるメール送信、メーリングリスト管理、ドメイン情報へのアクセス、自動化されたワークフローの一部としてリアルタイムイベントの監視を行うことができます。これにより、AIを活用したプロセスから直接ユーザーとインテリジェントでデータ駆動型のエンゲージメントが可能になります。 +{/* MANUAL-CONTENT-END */} + +## 使用手順 + +Mailgunをワークフローに統合します。トランザクションメールの送信、メーリングリストとメンバーの管理、ドメイン情報の表示、メールイベントの追跡が可能です。テキストメールとHTMLメール、追跡用のタグ、包括的なリスト管理をサポートしています。 + +## ツール + +### `mailgun_send_message` + +Mailgun APIを使用してメールを送信する + +#### 入力 + +| パラメータ | 型 | 必須 | 説明 | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | はい | Mailgun APIキー | +| `domain` | string | はい | Mailgunドメイン(例:mg.example.com) | +| `from` | string | はい | 送信者のメールアドレス | +| `to` | string | はい | 受信者のメールアドレス(複数の場合はカンマ区切り) | +| `subject` | string | はい | メールの件名 | +| `text` | string | いいえ | メールのプレーンテキスト本文 | +| `html` | string | いいえ | メールのHTML本文 | +| `cc` | string | いいえ | CCメールアドレス(複数の場合はカンマ区切り) | +| `bcc` | string | いいえ | BCCメールアドレス(複数の場合はカンマ区切り) | +| `tags` | string | いいえ | メールのタグ(カンマ区切り) | + +#### 出力 + +| パラメータ | 型 | 説明 | +| --------- | ---- | ----------- | +| `success` | boolean | メッセージが正常に送信されたかどうか | +| `id` | string | メッセージID | +| `message` | string | Mailgunからのレスポンスメッセージ | + +### `mailgun_get_message` + +キーによって保存されたメッセージを取得する + +#### 入力 + +| パラメータ | 型 | 必須 | 説明 | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | はい | Mailgun APIキー | +| `domain` | string | はい | Mailgunドメイン | +| `messageKey` | string | はい | メッセージストレージキー | + +#### 出力 + +| パラメータ | 型 | 説明 | +| --------- | ---- | ----------- | +| `success` | boolean | リクエストが成功したかどうか | +| `recipients` | string | メッセージの受信者 | +| `from` | string | 送信者のメールアドレス | +| `subject` | string | メッセージの件名 | +| `bodyPlain` | string | プレーンテキスト本文 | +| `strippedText` | string | 整形されたテキスト | +| `strippedSignature` | string | 整形された署名 | +| `bodyHtml` | string | HTML本文 | +| `strippedHtml` | string | 整形されたHTML | +| `attachmentCount` | number | 添付ファイルの数 | +| `timestamp` | number | メッセージのタイムスタンプ | +| `messageHeaders` | json | メッセージヘッダー | +| `contentIdMap` | json | コンテンツIDマップ | + +### `mailgun_list_messages` + +Mailgunを通じて送信されたメッセージのイベント(ログ)を一覧表示する + +#### 入力 + +| パラメータ | 型 | 必須 | 説明 | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | はい | Mailgun APIキー | +| `domain` | string | はい | Mailgunドメイン | +| `event` | string | いいえ | イベントタイプでフィルタリング(accepted、delivered、failed、opened、clickedなど) | +| `limit` | number | いいえ | 返すイベントの最大数(デフォルト:100) | + +#### 出力 + +| パラメータ | 型 | 説明 | +| --------- | ---- | ----------- | +| `success` | boolean | リクエストが成功したかどうか | +| `items` | json | イベント項目の配列 | +| `paging` | json | ページング情報 | + +### `mailgun_create_mailing_list` + +新しいメーリングリストを作成する + +#### 入力 + +| パラメータ | 型 | 必須 | 説明 | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | はい | Mailgun APIキー | +| `address` | string | はい | メーリングリストアドレス(例:list@example.com) | +| `name` | string | いいえ | メーリングリスト名 | +| `description` | string | いいえ | メーリングリストの説明 | +| `accessLevel` | string | いいえ | アクセスレベル:readonly、members、またはeveryone | + +#### 出力 + +| パラメータ | 型 | 説明 | +| --------- | ---- | ----------- | +| `success` | boolean | リストが正常に作成されたかどうか | +| `message` | string | レスポンスメッセージ | +| `list` | json | 作成されたメーリングリストの詳細 | + +### `mailgun_get_mailing_list` + +メーリングリストの詳細を取得する + +#### 入力 + +| パラメータ | 型 | 必須 | 説明 | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | はい | Mailgun APIキー | +| `address` | string | はい | メーリングリストアドレス | + +#### 出力 + +| パラメータ | 型 | 説明 | +| --------- | ---- | ----------- | +| `success` | boolean | リクエストが成功したかどうか | +| `list` | json | メーリングリストの詳細 | + +### `mailgun_add_list_member` + +メーリングリストにメンバーを追加する + +#### 入力 + +| パラメータ | 型 | 必須 | 説明 | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | はい | Mailgun APIキー | +| `listAddress` | string | はい | メーリングリストアドレス | +| `address` | string | はい | メンバーのメールアドレス | +| `name` | string | いいえ | メンバー名 | +| `vars` | string | いいえ | カスタム変数のJSON文字列 | +| `subscribed` | boolean | いいえ | メンバーが購読しているかどうか | + +#### 出力 + +| パラメータ | 型 | 説明 | +| --------- | ---- | ----------- | +| `success` | boolean | メンバーが正常に追加されたかどうか | +| `message` | string | レスポンスメッセージ | +| `member` | json | 追加されたメンバーの詳細 | + +### `mailgun_list_domains` + +Mailgunアカウントのすべてのドメインを一覧表示する + +#### 入力 + +| パラメータ | 型 | 必須 | 説明 | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | はい | Mailgun APIキー | + +#### 出力 + +| パラメータ | 型 | 説明 | +| --------- | ---- | ----------- | +| `success` | boolean | リクエストが成功したかどうか | +| `totalCount` | number | ドメインの総数 | +| `items` | json | ドメインオブジェクトの配列 | + +### `mailgun_get_domain` + +特定のドメインの詳細を取得する + +#### 入力 + +| パラメータ | 型 | 必須 | 説明 | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | はい | Mailgun APIキー | +| `domain` | string | はい | ドメイン名 | + +#### 出力 + +| パラメータ | 型 | 説明 | +| --------- | ---- | ----------- | +| `success` | boolean | リクエストが成功したかどうか | +| `domain` | json | ドメインの詳細 | + +## 注意事項 + +- カテゴリー: `tools` +- タイプ: `mailgun` diff --git a/apps/docs/content/docs/ja/tools/sendgrid.mdx b/apps/docs/content/docs/ja/tools/sendgrid.mdx new file mode 100644 index 0000000000..4a5e555075 --- /dev/null +++ b/apps/docs/content/docs/ja/tools/sendgrid.mdx @@ -0,0 +1,391 @@ +--- +title: SendGrid +description: SendGridでメールの送信、連絡先、リスト、テンプレートの管理を行う +--- + +import { BlockInfoCard } from "@/components/ui/block-info-card" + + + +{/* MANUAL-CONTENT-START:intro */} +[SendGrid](https://sendgrid.com)は、開発者や企業が信頼する、スケーラブルなトランザクションメールやマーケティングメールを確実に配信するクラウドベースのメール配信プラットフォームです。強力なAPIとツールを備え、SendGridは通知や領収書の送信から複雑なマーケティングキャンペーンの管理まで、あらゆるメールコミュニケーションを管理できます。 + +SendGridは、重要なメールワークフローの自動化や連絡先リスト、テンプレート、受信者のエンゲージメントの緻密な管理など、メール運用の完全なスイートを提供します。Simとのシームレスな統合により、エージェントやワークフローはターゲットを絞ったメッセージの配信、動的な連絡先やリストの維持、テンプレートを通じたパーソナライズされたメールの送信、そしてリアルタイムでの結果追跡が可能になります。 + +SendGridの主な機能には以下が含まれます: + +- **トランザクションメール:** 自動化された大量のトランザクションメール(通知、領収書、パスワードリセットなど)を送信。 +- **動的テンプレート:** リッチHTMLまたはテキストテンプレートに動的データを使用して、高度にパーソナライズされた大規模なコミュニケーションを実現。 +- **連絡先管理:** マーケティング連絡先の追加と更新、受信者リストの管理、キャンペーン向けのセグメントのターゲティング。 +- **添付ファイルのサポート:** メールに1つまたは複数のファイル添付が可能。 +- **包括的なAPIカバレッジ:** メール、連絡先、リスト、テンプレート、抑制グループなどをプログラムで管理。 + +SendGridとSimを連携させることで、エージェントは以下のことが可能になります: + +- ワークフローの一部として、シンプルなメールと高度な(テンプレート化または複数の受信者向けの)メールの両方を送信。 +- 連絡先とリストを自動的に管理・セグメント化。 +- 一貫性と動的なパーソナライゼーションのためにテンプレートを活用。 +- 自動化されたプロセス内でメールのエンゲージメントを追跡し対応。 + +この連携により、重要なコミュニケーションフローをすべて自動化し、メッセージが適切な対象者に届くようにし、Simワークフローから直接組織のメール戦略を管理することができます。 +{/* MANUAL-CONTENT-END */} + +## 使用方法 + +SendGridをワークフローに統合します。トランザクションメールの送信、マーケティング連絡先とリストの管理、メールテンプレートの操作が可能です。動的テンプレート、添付ファイル、包括的な連絡先管理をサポートしています。 + +## ツール + +### `sendgrid_send_mail` + +SendGrid APIを使用してメールを送信する + +#### 入力 + +| パラメータ | 種類 | 必須 | 説明 | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | はい | SendGrid APIキー | +| `from` | string | はい | 送信者のメールアドレス(SendGridで検証済みである必要があります) | +| `fromName` | string | いいえ | 送信者名 | +| `to` | string | はい | 受信者のメールアドレス | +| `toName` | string | いいえ | 受信者名 | +| `subject` | string | いいえ | メールの件名(事前定義された件名を持つテンプレートを使用しない限り必須) | +| `content` | string | いいえ | メール本文のコンテンツ(事前定義されたコンテンツを持つテンプレートを使用しない限り必須) | +| `contentType` | string | いいえ | コンテンツタイプ(text/plainまたはtext/html) | +| `cc` | string | いいえ | CCメールアドレス | +| `bcc` | string | いいえ | BCCメールアドレス | +| `replyTo` | string | いいえ | 返信先メールアドレス | +| `replyToName` | string | いいえ | 返信先名 | +| `attachments` | file[] | いいえ | メールに添付するファイル | +| `templateId` | string | いいえ | 使用するSendGridテンプレートID | +| `dynamicTemplateData` | json | いいえ | 動的テンプレートデータのJSONオブジェクト | + +#### 出力 + +| パラメータ | 型 | 説明 | +| --------- | ---- | ----------- | +| `success` | boolean | メールが正常に送信されたかどうか | +| `messageId` | string | SendGridメッセージID | +| `to` | string | 受信者のメールアドレス | +| `subject` | string | メールの件名 | + +### `sendgrid_add_contact` + +SendGridに新しい連絡先を追加する + +#### 入力 + +| パラメータ | 型 | 必須 | 説明 | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | はい | SendGrid APIキー | +| `email` | string | はい | 連絡先のメールアドレス | +| `firstName` | string | いいえ | 連絡先の名 | +| `lastName` | string | いいえ | 連絡先の姓 | +| `customFields` | json | いいえ | カスタムフィールドのキーと値のペアのJSONオブジェクト(フィールド名ではなく、e1_T、e2_N、e3_DなどのフィールドIDを使用) | +| `listIds` | string | いいえ | 連絡先を追加するリストIDのカンマ区切りリスト | + +#### 出力 + +| パラメータ | 型 | 説明 | +| --------- | ---- | ----------- | +| `jobId` | string | 非同期連絡先作成を追跡するためのジョブID | +| `email` | string | 連絡先のメールアドレス | +| `firstName` | string | 連絡先の名 | +| `lastName` | string | 連絡先の姓 | +| `message` | string | ステータスメッセージ | + +### `sendgrid_get_contact` + +SendGridから特定の連絡先をIDで取得する + +#### 入力 + +| パラメータ | 型 | 必須 | 説明 | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | はい | SendGrid APIキー | +| `contactId` | string | はい | 連絡先ID | + +#### 出力 + +| パラメータ | 型 | 説明 | +| --------- | ---- | ----------- | +| `id` | string | 連絡先ID | +| `email` | string | 連絡先のメールアドレス | +| `firstName` | string | 連絡先の名 | +| `lastName` | string | 連絡先の姓 | +| `createdAt` | string | 作成タイムスタンプ | +| `updatedAt` | string | 最終更新タイムスタンプ | +| `listIds` | json | 連絡先が所属するリストIDの配列 | +| `customFields` | json | カスタムフィールドの値 | + +### `sendgrid_search_contacts` + +クエリを使用してSendGrid内の連絡先を検索する + +#### 入力 + +| パラメータ | 型 | 必須 | 説明 | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | はい | SendGrid APIキー | +| `query` | string | はい | 検索クエリ(例:"email LIKE '%example.com%' AND CONTAINS(list_ids, 'list-id')") | + +#### 出力 + +| パラメータ | 型 | 説明 | +| --------- | ---- | ----------- | +| `contacts` | json | 一致する連絡先の配列 | +| `contactCount` | number | 見つかった連絡先の総数 | + +### `sendgrid_delete_contacts` + +SendGridから1つ以上の連絡先を削除する + +#### 入力 + +| パラメータ | 型 | 必須 | 説明 | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | はい | SendGrid APIキー | +| `contactIds` | string | はい | 削除する連絡先IDのカンマ区切りリスト | + +#### 出力 + +| パラメータ | 型 | 説明 | +| --------- | ---- | ----------- | +| `jobId` | string | 削除リクエストのジョブID | + +### `sendgrid_create_list` + +SendGridで新しいコンタクトリストを作成する + +#### 入力 + +| パラメータ | 型 | 必須 | 説明 | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | はい | SendGrid APIキー | +| `name` | string | はい | リスト名 | + +#### 出力 + +| パラメータ | 型 | 説明 | +| --------- | ---- | ----------- | +| `id` | string | リストID | +| `name` | string | リスト名 | +| `contactCount` | number | リスト内のコンタクト数 | + +### `sendgrid_get_list` + +SendGridから特定のリストをIDで取得する + +#### 入力 + +| パラメータ | 型 | 必須 | 説明 | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | はい | SendGrid APIキー | +| `listId` | string | はい | リストID | + +#### 出力 + +| パラメータ | 型 | 説明 | +| --------- | ---- | ----------- | +| `id` | string | リストID | +| `name` | string | リスト名 | +| `contactCount` | number | リスト内のコンタクト数 | + +### `sendgrid_list_all_lists` + +SendGridからすべてのコンタクトリストを取得する + +#### 入力 + +| パラメータ | 型 | 必須 | 説明 | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | はい | SendGrid APIキー | +| `pageSize` | number | いいえ | ページごとに返すリスト数(デフォルト:100) | + +#### 出力 + +| パラメータ | 型 | 説明 | +| --------- | ---- | ----------- | +| `lists` | json | リストの配列 | + +### `sendgrid_delete_list` + +SendGridからコンタクトリストを削除する + +#### 入力 + +| パラメータ | 型 | 必須 | 説明 | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | はい | SendGrid APIキー | +| `listId` | string | はい | 削除するリストID | + +#### 出力 + +| パラメータ | 型 | 説明 | +| --------- | ---- | ----------- | +| `message` | string | 成功メッセージ | + +### `sendgrid_add_contacts_to_list` + +SendGridでコンタクトを追加または更新し、リストに割り当てる(PUT /v3/marketing/contactsを使用) + +#### 入力 + +| パラメータ | 型 | 必須 | 説明 | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | はい | SendGrid APIキー | +| `listId` | string | はい | コンタクトを追加するリストID | +| `contacts` | json | はい | コンタクトオブジェクトのJSON配列。各コンタクトには少なくとも:email(またはphone_number_id/external_id/anonymous_id)が必要。例:\[\{"email": "user@example.com", "first_name": "John"\}\] | + +#### 出力 + +| パラメータ | 型 | 説明 | +| --------- | ---- | ----------- | +| `jobId` | string | 非同期操作を追跡するためのジョブID | +| `message` | string | ステータスメッセージ | + +### `sendgrid_remove_contacts_from_list` + +SendGridの特定のリストからコンタクトを削除する + +#### 入力 + +| パラメータ | 型 | 必須 | 説明 | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | はい | SendGrid APIキー | +| `listId` | string | はい | リストID | +| `contactIds` | string | はい | リストから削除するコンタクトIDのカンマ区切りリスト | + +#### 出力 + +| パラメータ | 型 | 説明 | +| --------- | ---- | ----------- | +| `jobId` | string | リクエストのジョブID | + +### `sendgrid_create_template` + +SendGridで新しいメールテンプレートを作成する + +#### 入力 + +| パラメータ | 型 | 必須 | 説明 | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | はい | SendGrid APIキー | +| `name` | string | はい | テンプレート名 | +| `generation` | string | いいえ | テンプレート生成タイプ(レガシーまたはダイナミック、デフォルト:ダイナミック) | + +#### 出力 + +| パラメータ | 型 | 説明 | +| --------- | ---- | ----------- | +| `id` | string | テンプレートID | +| `name` | string | テンプレート名 | +| `generation` | string | テンプレート生成 | +| `updatedAt` | string | 最終更新タイムスタンプ | +| `versions` | json | テンプレートバージョンの配列 | + +### `sendgrid_get_template` + +SendGridから特定のテンプレートをIDで取得する + +#### 入力 + +| パラメータ | 型 | 必須 | 説明 | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | はい | SendGrid APIキー | +| `templateId` | string | はい | テンプレートID | + +#### 出力 + +| パラメータ | 型 | 説明 | +| --------- | ---- | ----------- | +| `id` | string | テンプレートID | +| `name` | string | テンプレート名 | +| `generation` | string | テンプレート生成 | +| `updatedAt` | string | 最終更新タイムスタンプ | +| `versions` | json | テンプレートバージョンの配列 | + +### `sendgrid_list_templates` + +SendGridからすべてのメールテンプレートを取得する + +#### 入力 + +| パラメータ | 型 | 必須 | 説明 | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | はい | SendGrid APIキー | +| `generations` | string | いいえ | 生成方法でフィルタリング(legacy、dynamic、または両方) | +| `pageSize` | number | いいえ | ページごとに返すテンプレートの数(デフォルト:20) | + +#### 出力 + +| パラメータ | 型 | 説明 | +| --------- | ---- | ----------- | +| `templates` | json | テンプレートの配列 | + +### `sendgrid_delete_template` + +SendGridからメールテンプレートを削除する + +#### 入力 + +| パラメータ | 型 | 必須 | 説明 | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | はい | SendGrid APIキー | +| `templateId` | string | はい | 削除するテンプレートID | + +#### 出力 + +| パラメータ | 型 | 説明 | +| --------- | ---- | ----------- | +| `success` | boolean | 操作成功ステータス | +| `messageId` | string | メールメッセージID(send_mail) | +| `id` | string | リソースID | +| `jobId` | string | 非同期操作のジョブID | +| `email` | string | メールアドレス | +| `firstName` | string | 名 | +| `lastName` | string | 姓 | +| `contacts` | json | 連絡先の配列 | +| `contactCount` | number | 連絡先の数 | +| `lists` | json | リストの配列 | +| `templates` | json | テンプレートの配列 | +| `message` | string | ステータスまたは成功メッセージ | +| `name` | string | リソース名 | +| `generation` | string | テンプレート生成方法 | + +### `sendgrid_create_template_version` + +SendGridでメールテンプレートの新しいバージョンを作成する + +#### 入力 + +| パラメータ | 型 | 必須 | 説明 | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | はい | SendGrid APIキー | +| `templateId` | string | はい | テンプレートID | +| `name` | string | はい | バージョン名 | +| `subject` | string | はい | メールの件名 | +| `htmlContent` | string | いいえ | テンプレートのHTML内容 | +| `plainContent` | string | いいえ | テンプレートのプレーンテキスト内容 | +| `active` | boolean | いいえ | このバージョンがアクティブかどうか(デフォルト:true) | + +#### 出力 + +| パラメータ | 型 | 説明 | +| --------- | ---- | ----------- | +| `id` | string | バージョンID | +| `templateId` | string | テンプレートID | +| `name` | string | バージョン名 | +| `subject` | string | メールの件名 | +| `active` | boolean | このバージョンがアクティブかどうか | +| `htmlContent` | string | HTML内容 | +| `plainContent` | string | プレーンテキスト内容 | +| `updatedAt` | string | 最終更新タイムスタンプ | + +## 注意事項 + +- カテゴリー: `tools` +- タイプ: `sendgrid` diff --git a/apps/docs/content/docs/ja/tools/smtp.mdx b/apps/docs/content/docs/ja/tools/smtp.mdx new file mode 100644 index 0000000000..39ef4ae103 --- /dev/null +++ b/apps/docs/content/docs/ja/tools/smtp.mdx @@ -0,0 +1,73 @@ +--- +title: SMTP +description: 任意のSMTPメールサーバーを介してメールを送信 +--- + +import { BlockInfoCard } from "@/components/ui/block-info-card" + + + +{/* MANUAL-CONTENT-START:intro */} +[SMTP(Simple Mail Transfer Protocol)](https://en.wikipedia.org/wiki/Simple_Mail_Transfer_Protocol)は、インターネット上でのメール送信の基本的な標準規格です。Gmail、Outlook、または組織独自のメールインフラなど、SMTP互換サーバーに接続することで、プログラムによるメール送信や送信コミュニケーションの自動化が可能になります。 + +SMTP統合により、サーバーへの直接接続を通じてメール送信を完全にカスタマイズでき、基本的なものから高度なメールユースケースまでサポートします。SMTPを使用すると、メッセージ配信、受信者管理、コンテンツフォーマットなどあらゆる側面を制御できるため、トランザクションメール通知、一括メール送信、堅牢な送信メール配信を必要とするあらゆる自動化ワークフローに適しています。 + +**SMTP統合で利用可能な主な機能:** + +- **ユニバーサルなメール配信:** 標準的なサーバー接続パラメータを設定することで、任意のSMTPサーバーを使用してメールを送信できます。 +- **カスタマイズ可能な送信者と受信者:** 送信者アドレス、表示名、主要受信者、CCおよびBCCフィールドを指定できます。 +- **リッチコンテンツのサポート:** 要件に応じて、プレーンテキストまたはリッチフォーマットのHTMLメールを送信できます。 +- **添付ファイル:** 送信メールに複数のファイルを添付ファイルとして含めることができます。 +- **柔軟なセキュリティ:** SMTPプロバイダーがサポートするTLS、SSL、または標準(非暗号化)プロトコルを使用して接続できます。 +- **高度なヘッダー:** 返信先ヘッダーやその他の高度なメールオプションを設定して、複雑なメールフローやユーザーインタラクションに対応できます。 + +SMTPをSimと統合することで、エージェントやワークフローは、通知や確認メールの送信から、外部コミュニケーション、レポート作成、文書配信の自動化まで、あらゆる自動化プロセスの一部としてプログラムによるメール送信が可能になります。これにより、AI駆動プロセス内で直接メールを管理するための、非常に柔軟でプロバイダーに依存しないアプローチが提供されます。 +{/* MANUAL-CONTENT-END */} + +## 使用方法 + +任意のSMTPサーバー(Gmail、Outlook、カスタムサーバーなど)を使用してメールを送信します。SMTP接続設定を構成し、コンテンツ、受信者、添付ファイルを完全に制御してメールを送信できます。 + +## ツール + +### `smtp_send_mail` + +SMTPサーバー経由でメールを送信 + +#### 入力 + +| パラメータ | 型 | 必須 | 説明 | +| --------- | ---- | -------- | ----------- | +| `smtpHost` | string | はい | SMTPサーバーのホスト名(例:smtp.gmail.com) | +| `smtpPort` | number | はい | SMTPサーバーのポート(TLSの場合は587、SSLの場合は465) | +| `smtpUsername` | string | はい | SMTP認証のユーザー名 | +| `smtpPassword` | string | はい | SMTP認証のパスワード | +| `smtpSecure` | string | はい | セキュリティプロトコル(TLS、SSL、またはNone) | +| `from` | string | はい | 送信者のメールアドレス | +| `to` | string | はい | 受信者のメールアドレス | +| `subject` | string | はい | メールの件名 | +| `body` | string | はい | メール本文の内容 | +| `contentType` | string | いいえ | コンテンツタイプ(textまたはhtml) | +| `fromName` | string | いいえ | 送信者の表示名 | +| `cc` | string | いいえ | CC受信者(カンマ区切り) | +| `bcc` | string | いいえ | BCC受信者(カンマ区切り) | +| `replyTo` | string | いいえ | 返信先メールアドレス | +| `attachments` | file[] | いいえ | メールに添付するファイル | + +#### 出力 + +| パラメータ | 型 | 説明 | +| --------- | ---- | ----------- | +| `success` | boolean | メールが正常に送信されたかどうか | +| `messageId` | string | SMTPサーバーからのメッセージID | +| `to` | string | 受信者のメールアドレス | +| `subject` | string | メールの件名 | +| `error` | string | 送信に失敗した場合のエラーメッセージ | + +## メモ + +- カテゴリー: `tools` +- タイプ: `smtp` diff --git a/apps/docs/content/docs/zh/tools/linkedin.mdx b/apps/docs/content/docs/zh/tools/linkedin.mdx new file mode 100644 index 0000000000..30f019c3a3 --- /dev/null +++ b/apps/docs/content/docs/zh/tools/linkedin.mdx @@ -0,0 +1,83 @@ +--- +title: LinkedIn +description: 分享帖子并管理您的 LinkedIn 存在 +--- + +import { BlockInfoCard } from "@/components/ui/block-info-card" + + + +{/* MANUAL-CONTENT-START:intro */} +[LinkedIn](https://www.linkedin.com) 是全球最大的职业社交平台,帮助用户建立职业生涯,与人脉建立联系,并分享专业内容。LinkedIn 被各行业的专业人士广泛用于个人品牌建设、招聘、求职和业务发展。 + +通过 LinkedIn,您可以轻松地在个人动态中分享帖子,与您的网络互动,并访问您的个人资料信息以突出您的职业成就。与 Sim 的自动集成使您能够以编程方式利用 LinkedIn 的功能——让代理和工作流发布更新、报告您的职业存在,并在无需手动操作的情况下保持动态活跃。 + +通过此集成可用的 LinkedIn 关键功能包括: + +- **分享帖子:** 自动将专业更新、文章或公告发布到您的 LinkedIn 个人动态。 +- **个人资料信息:** 检索有关您 LinkedIn 个人资料的详细信息,以便在工作流中进行监控或用于后续任务。 + +这些功能使您能够轻松地保持 LinkedIn 网络的互动,并作为您的 AI 或工作流自动化策略的一部分,高效地扩展您的职业影响力。 +{/* MANUAL-CONTENT-END */} + +## 使用说明 + +将 LinkedIn 集成到工作流中。在个人动态中分享帖子并访问您的 LinkedIn 个人资料信息。 + +## 工具 + +### `linkedin_share_post` + +将帖子分享到您的个人 LinkedIn 动态 + +#### 输入 + +| 参数 | 类型 | 必需 | 描述 | +| --------- | ---- | -------- | ----------- | +| `text` | string | 是 | 您的 LinkedIn 帖子的文本内容 | +| `visibility` | string | 否 | 谁可以看到此帖子:“PUBLIC” 或 “CONNECTIONS” \(默认值:“PUBLIC”\) | +| `request` | string | 否 | 无描述 | +| `output` | string | 否 | 无描述 | +| `output` | string | 否 | 无描述 | +| `specificContent` | string | 否 | 无描述 | +| `shareCommentary` | string | 否 | 无描述 | +| `visibility` | string | 否 | 无描述 | +| `headers` | string | 否 | 无描述 | +| `output` | string | 否 | 无描述 | +| `output` | string | 否 | 无描述 | +| `output` | string | 否 | 无描述 | + +#### 输出 + +| 参数 | 类型 | 描述 | +| --------- | ---- | ----------- | +| `success` | boolean | 操作成功状态 | +| `postId` | string | 创建的帖子 ID | +| `profile` | json | LinkedIn 个人资料信息 | +| `error` | string | 如果操作失败的错误信息 | + +### `linkedin_get_profile` + +检索您的 LinkedIn 个人资料信息 + +#### 输入 + +| 参数 | 类型 | 必需 | 描述 | +| --------- | ---- | -------- | ----------- | + +#### 输出 + +| 参数 | 类型 | 描述 | +| --------- | ---- | ----------- | +| `success` | boolean | 操作成功状态 | +| `postId` | string | 创建的帖子 ID | +| `profile` | json | LinkedIn 个人资料信息 | +| `error` | string | 如果操作失败的错误信息 | + +## 注意事项 + +- 类别: `tools` +- 类型: `linkedin` diff --git a/apps/docs/content/docs/zh/tools/mailgun.mdx b/apps/docs/content/docs/zh/tools/mailgun.mdx new file mode 100644 index 0000000000..8d2e2c4ae6 --- /dev/null +++ b/apps/docs/content/docs/zh/tools/mailgun.mdx @@ -0,0 +1,216 @@ +--- +title: Mailgun +description: 使用 Mailgun 发送电子邮件并管理邮件列表 +--- + +import { BlockInfoCard } from "@/components/ui/block-info-card" + + + +{/* MANUAL-CONTENT-START:intro */} +[Mailgun](https://www.mailgun.com) 是一款功能强大的电子邮件发送服务,专为开发者和企业设计,能够轻松发送、接收和跟踪电子邮件。Mailgun 提供强大的 API,支持可靠的事务性和营销电子邮件、灵活的邮件列表管理以及高级事件跟踪。 + +通过 Mailgun 的全面功能集,您可以自动化关键的电子邮件操作,并密切监控投递率和收件人参与度。这使其成为在通信、通知和活动邮件是核心流程的工作流自动化中的理想解决方案。 + +Mailgun 的主要功能包括: + +- **事务性电子邮件发送:** 发送大量电子邮件,例如账户通知、收据、警报和密码重置。 +- **丰富的电子邮件内容:** 发送纯文本和 HTML 格式的电子邮件,并使用标签对消息进行分类和跟踪。 +- **邮件列表管理:** 创建、更新和管理邮件列表及成员,以高效发送分组通信。 +- **域信息:** 检索发送域的详细信息,以监控配置和健康状况。 +- **事件跟踪:** 通过详细的事件数据分析电子邮件的投递率和参与度。 +- **消息检索:** 访问存储的消息以满足合规性、分析或故障排除需求。 + +通过将 Mailgun 集成到 Sim 中,您的代理可以以编程方式发送电子邮件、管理邮件列表、访问域信息并监控实时事件,作为自动化工作流的一部分。这使您能够直接从 AI 驱动的流程中实现智能、数据驱动的用户互动。 +{/* MANUAL-CONTENT-END */} + +## 使用说明 + +将 Mailgun 集成到您的工作流中。发送事务性电子邮件,管理邮件列表及成员,查看域信息并跟踪电子邮件事件。支持文本和 HTML 格式的电子邮件、用于跟踪的标签以及全面的列表管理功能。 + +## 工具 + +### `mailgun_send_message` + +使用 Mailgun API 发送电子邮件 + +#### 输入 + +| 参数 | 类型 | 必需 | 描述 | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | 是 | Mailgun API 密钥 | +| `domain` | string | 是 | Mailgun 域名 \(例如:mg.example.com\) | +| `from` | string | 是 | 发件人电子邮件地址 | +| `to` | string | 是 | 收件人电子邮件地址 \(多个地址用逗号分隔\) | +| `subject` | string | 是 | 电子邮件主题 | +| `text` | string | 否 | 电子邮件的纯文本正文 | +| `html` | string | 否 | 电子邮件的 HTML 正文 | +| `cc` | string | 否 | 抄送电子邮件地址 \(多个地址用逗号分隔\) | +| `bcc` | string | 否 | 密送电子邮件地址 \(多个地址用逗号分隔\) | +| `tags` | string | 否 | 电子邮件标签 \(用逗号分隔\) | + +#### 输出 + +| 参数 | 类型 | 描述 | +| --------- | ---- | ----------- | +| `success` | boolean | 消息是否成功发送 | +| `id` | string | 消息 ID | +| `message` | string | 来自 Mailgun 的响应消息 | + +### `mailgun_get_message` + +通过其密钥检索存储的消息 + +#### 输入 + +| 参数 | 类型 | 必需 | 描述 | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | 是 | Mailgun API 密钥 | +| `domain` | string | 是 | Mailgun 域名 | +| `messageKey` | string | 是 | 消息存储密钥 | + +#### 输出 + +| 参数 | 类型 | 描述 | +| --------- | ---- | ----------- | +| `success` | boolean | 请求是否成功 | +| `recipients` | string | 消息接收者 | +| `from` | string | 发件人邮箱 | +| `subject` | string | 消息主题 | +| `bodyPlain` | string | 纯文本正文 | +| `strippedText` | string | 去除格式的文本 | +| `strippedSignature` | string | 去除格式的签名 | +| `bodyHtml` | string | HTML 正文 | +| `strippedHtml` | string | 去除格式的 HTML | +| `attachmentCount` | number | 附件数量 | +| `timestamp` | number | 消息时间戳 | +| `messageHeaders` | json | 消息头信息 | +| `contentIdMap` | json | 内容 ID 映射 | + +### `mailgun_list_messages` + +列出通过 Mailgun 发送的消息的事件(日志) + +#### 输入 + +| 参数 | 类型 | 必需 | 描述 | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | 是 | Mailgun API 密钥 | +| `domain` | string | 是 | Mailgun 域名 | +| `event` | string | 否 | 按事件类型过滤 \(accepted, delivered, failed, opened, clicked, etc.\) | +| `limit` | number | 否 | 返回的最大事件数 \(默认值: 100\) | + +#### 输出 + +| 参数 | 类型 | 描述 | +| --------- | ---- | ----------- | +| `success` | boolean | 请求是否成功 | +| `items` | json | 事件项数组 | +| `paging` | json | 分页信息 | + +### `mailgun_create_mailing_list` + +创建一个新的邮件列表 + +#### 输入 + +| 参数 | 类型 | 必需 | 描述 | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | 是 | Mailgun API 密钥 | +| `address` | string | 是 | 邮件列表地址 \(例如:list@example.com\) | +| `name` | string | 否 | 邮件列表名称 | +| `description` | string | 否 | 邮件列表描述 | +| `accessLevel` | string | 否 | 访问级别:readonly、members 或 everyone | + +#### 输出 + +| 参数 | 类型 | 描述 | +| --------- | ---- | ----------- | +| `success` | boolean | 是否成功创建了列表 | +| `message` | string | 响应消息 | +| `list` | json | 创建的邮件列表详情 | + +### `mailgun_get_mailing_list` + +获取邮件列表的详细信息 + +#### 输入 + +| 参数 | 类型 | 必需 | 描述 | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | 是 | Mailgun API 密钥 | +| `address` | string | 是 | 邮件列表地址 | + +#### 输出 + +| 参数 | 类型 | 描述 | +| --------- | ---- | ----------- | +| `success` | boolean | 请求是否成功 | +| `list` | json | 邮件列表详情 | + +### `mailgun_add_list_member` + +向邮件列表添加成员 + +#### 输入 + +| 参数 | 类型 | 必需 | 描述 | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | 是 | Mailgun API 密钥 | +| `listAddress` | string | 是 | 邮件列表地址 | +| `address` | string | 是 | 成员邮箱地址 | +| `name` | string | 否 | 成员名称 | +| `vars` | string | 否 | 自定义变量的 JSON 字符串 | +| `subscribed` | boolean | 否 | 成员是否已订阅 | + +#### 输出 + +| 参数 | 类型 | 描述 | +| --------- | ---- | ----------- | +| `success` | boolean | 成员是否成功添加 | +| `message` | string | 响应消息 | +| `member` | json | 添加的成员详情 | + +### `mailgun_list_domains` + +列出您的 Mailgun 帐户的所有域名 + +#### 输入 + +| 参数 | 类型 | 必需 | 描述 | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | 是 | Mailgun API 密钥 | + +#### 输出 + +| 参数 | 类型 | 描述 | +| --------- | ---- | ----------- | +| `success` | boolean | 请求是否成功 | +| `totalCount` | number | 域名总数 | +| `items` | json | 域名对象数组 | + +### `mailgun_get_domain` + +获取特定域名的详细信息 + +#### 输入 + +| 参数 | 类型 | 必需 | 描述 | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | 是 | Mailgun API 密钥 | +| `domain` | string | 是 | 域名 | + +#### 输出 + +| 参数 | 类型 | 描述 | +| --------- | ---- | ----------- | +| `success` | boolean | 请求是否成功 | +| `domain` | json | 域名详情 | + +## 注意事项 + +- 类别: `tools` +- 类型: `mailgun` diff --git a/apps/docs/content/docs/zh/tools/sendgrid.mdx b/apps/docs/content/docs/zh/tools/sendgrid.mdx new file mode 100644 index 0000000000..4e3d0d9acc --- /dev/null +++ b/apps/docs/content/docs/zh/tools/sendgrid.mdx @@ -0,0 +1,391 @@ +--- +title: SendGrid +description: 使用 SendGrid 发送电子邮件并管理联系人、列表和模板 +--- + +import { BlockInfoCard } from "@/components/ui/block-info-card" + + + +{/* MANUAL-CONTENT-START:intro */} +[SendGrid](https://sendgrid.com) 是一个领先的基于云的电子邮件发送平台,受到开发者和企业的信赖,可大规模发送可靠的事务性和营销电子邮件。通过其强大的 API 和工具,SendGrid 使您能够管理电子邮件通信的各个方面,从发送通知和收据到管理复杂的营销活动。 + +SendGrid 为用户提供了一整套电子邮件操作功能,使您能够自动化关键的电子邮件工作流,并密切管理联系人列表、模板和收件人参与度。它与 Sim 的无缝集成使代理和工作流能够发送目标消息,维护动态联系人和收件人列表,通过模板触发个性化电子邮件,并实时跟踪结果。 + +SendGrid 的主要功能包括: + +- **事务性电子邮件:** 发送自动化和大批量的事务性电子邮件(如通知、收据和密码重置)。 +- **动态模板:** 使用丰富的 HTML 或文本模板和动态数据,实现大规模高度个性化的通信。 +- **联系人管理:** 添加和更新营销联系人,管理收件人列表,并针对活动目标群体进行细分。 +- **附件支持:** 在电子邮件中包含一个或多个文件附件。 +- **全面的 API 覆盖:** 以编程方式管理电子邮件、联系人、列表、模板、抑制组等。 + +通过将 SendGrid 与 Sim 连接,您的代理可以: + +- 在任何工作流中发送简单或高级(模板化或多收件人)的电子邮件。 +- 自动管理和细分联系人和列表。 +- 利用模板实现一致性和动态个性化。 +- 在自动化流程中跟踪和响应电子邮件参与情况。 + +此集成允许您自动化所有关键的通信流程,确保消息到达正确的受众,并直接从 Sim 工作流中维护对您组织电子邮件策略的控制。 +{/* MANUAL-CONTENT-END */} + +## 使用说明 + +将 SendGrid 集成到您的工作流中。发送事务性电子邮件,管理营销联系人和列表,并使用电子邮件模板。支持动态模板、附件和全面的联系人管理。 + +## 工具 + +### `sendgrid_send_mail` + +使用 SendGrid API 发送电子邮件 + +#### 输入 + +| 参数 | 类型 | 必需 | 描述 | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | 是 | SendGrid API 密钥 | +| `from` | string | 是 | 发件人电子邮件地址 \(必须在 SendGrid 中验证\) | +| `fromName` | string | 否 | 发件人名称 | +| `to` | string | 是 | 收件人电子邮件地址 | +| `toName` | string | 否 | 收件人名称 | +| `subject` | string | 否 | 电子邮件主题 \(除非使用具有预定义主题的模板,否则必需\) | +| `content` | string | 否 | 电子邮件正文内容 \(除非使用具有预定义内容的模板,否则必需\) | +| `contentType` | string | 否 | 内容类型 \(text/plain 或 text/html\) | +| `cc` | string | 否 | 抄送电子邮件地址 | +| `bcc` | string | 否 | 密送电子邮件地址 | +| `replyTo` | string | 否 | 回复电子邮件地址 | +| `replyToName` | string | 否 | 回复名称 | +| `attachments` | file[] | 否 | 附加到电子邮件的文件 | +| `templateId` | string | 否 | 要使用的 SendGrid 模板 ID | +| `dynamicTemplateData` | json | 否 | 动态模板数据的 JSON 对象 | + +#### 输出 + +| 参数 | 类型 | 描述 | +| --------- | ---- | ----------- | +| `success` | boolean | 邮件是否成功发送 | +| `messageId` | string | SendGrid 消息 ID | +| `to` | string | 收件人邮箱地址 | +| `subject` | string | 邮件主题 | + +### `sendgrid_add_contact` + +向 SendGrid 添加新联系人 + +#### 输入 + +| 参数 | 类型 | 必需 | 描述 | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | 是 | SendGrid API 密钥 | +| `email` | string | 是 | 联系人邮箱地址 | +| `firstName` | string | 否 | 联系人名字 | +| `lastName` | string | 否 | 联系人姓氏 | +| `customFields` | json | 否 | 自定义字段键值对的 JSON 对象 \(使用字段 ID,如 e1_T, e2_N, e3_D,而不是字段名称\) | +| `listIds` | string | 否 | 用逗号分隔的列表 ID,用于添加联系人 | + +#### 输出 + +| 参数 | 类型 | 描述 | +| --------- | ---- | ----------- | +| `jobId` | string | 用于跟踪异步联系人创建的作业 ID | +| `email` | string | 联系人邮箱地址 | +| `firstName` | string | 联系人名字 | +| `lastName` | string | 联系人姓氏 | +| `message` | string | 状态消息 | + +### `sendgrid_get_contact` + +通过 ID 从 SendGrid 获取特定联系人 + +#### 输入 + +| 参数 | 类型 | 必需 | 描述 | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | 是 | SendGrid API 密钥 | +| `contactId` | string | 是 | 联系人 ID | + +#### 输出 + +| 参数 | 类型 | 描述 | +| --------- | ---- | ----------- | +| `id` | string | 联系人 ID | +| `email` | string | 联系人邮箱地址 | +| `firstName` | string | 联系人名字 | +| `lastName` | string | 联系人姓氏 | +| `createdAt` | string | 创建时间戳 | +| `updatedAt` | string | 最后更新时间戳 | +| `listIds` | json | 联系人所属列表 ID 的数组 | +| `customFields` | json | 自定义字段值 | + +### `sendgrid_search_contacts` + +使用查询在 SendGrid 中搜索联系人 + +#### 输入 + +| 参数 | 类型 | 必需 | 描述 | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | 是 | SendGrid API 密钥 | +| `query` | string | 是 | 搜索查询 \(例如,\"email LIKE '%example.com%' AND CONTAINS\(list_ids, 'list-id'\)\"\) | + +#### 输出 + +| 参数 | 类型 | 描述 | +| --------- | ---- | ----------- | +| `contacts` | json | 匹配联系人的数组 | +| `contactCount` | number | 找到的联系人总数 | + +### `sendgrid_delete_contacts` + +从 SendGrid 中删除一个或多个联系人 + +#### 输入 + +| 参数 | 类型 | 必需 | 描述 | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | 是 | SendGrid API 密钥 | +| `contactIds` | string | 是 | 要删除的联系人 ID,逗号分隔 | + +#### 输出 + +| 参数 | 类型 | 描述 | +| --------- | ---- | ----------- | +| `jobId` | string | 删除请求的作业 ID | + +### `sendgrid_create_list` + +在 SendGrid 中创建一个新的联系人列表 + +#### 输入 + +| 参数 | 类型 | 必需 | 描述 | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | 是 | SendGrid API 密钥 | +| `name` | string | 是 | 列表名称 | + +#### 输出 + +| 参数 | 类型 | 描述 | +| --------- | ---- | ----------- | +| `id` | string | 列表 ID | +| `name` | string | 列表名称 | +| `contactCount` | number | 列表中的联系人数量 | + +### `sendgrid_get_list` + +通过 ID 从 SendGrid 获取特定列表 + +#### 输入 + +| 参数 | 类型 | 必需 | 描述 | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | 是 | SendGrid API 密钥 | +| `listId` | string | 是 | 列表 ID | + +#### 输出 + +| 参数 | 类型 | 描述 | +| --------- | ---- | ----------- | +| `id` | string | 列表 ID | +| `name` | string | 列表名称 | +| `contactCount` | number | 列表中的联系人数量 | + +### `sendgrid_list_all_lists` + +从 SendGrid 获取所有联系人列表 + +#### 输入 + +| 参数 | 类型 | 必需 | 描述 | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | 是 | SendGrid API 密钥 | +| `pageSize` | number | 否 | 每页返回的列表数量 \(默认值: 100\) | + +#### 输出 + +| 参数 | 类型 | 描述 | +| --------- | ---- | ----------- | +| `lists` | json | 列表数组 | + +### `sendgrid_delete_list` + +从 SendGrid 删除联系人列表 + +#### 输入 + +| 参数 | 类型 | 必需 | 描述 | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | 是 | SendGrid API 密钥 | +| `listId` | string | 是 | 要删除的列表 ID | + +#### 输出 + +| 参数 | 类型 | 描述 | +| --------- | ---- | ----------- | +| `message` | string | 成功消息 | + +### `sendgrid_add_contacts_to_list` + +在 SendGrid 中添加或更新联系人并将其分配到列表中(使用 PUT /v3/marketing/contacts) + +#### 输入 + +| 参数 | 类型 | 必需 | 描述 | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | 是 | SendGrid API 密钥 | +| `listId` | string | 是 | 要添加联系人的列表 ID | +| `contacts` | json | 是 | 联系人对象的 JSON 数组。每个联系人必须至少包含:email(或 phone_number_id/external_id/anonymous_id)。示例:\[\{"email": "user@example.com", "first_name": "John"\}\] | + +#### 输出 + +| 参数 | 类型 | 描述 | +| --------- | ---- | ----------- | +| `jobId` | string | 用于跟踪异步操作的作业 ID | +| `message` | string | 状态消息 | + +### `sendgrid_remove_contacts_from_list` + +从 SendGrid 的特定列表中移除联系人 + +#### 输入 + +| 参数 | 类型 | 必需 | 描述 | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | 是 | SendGrid API 密钥 | +| `listId` | string | 是 | 列表 ID | +| `contactIds` | string | 是 | 要从列表中移除的逗号分隔的联系人 ID | + +#### 输出 + +| 参数 | 类型 | 描述 | +| --------- | ---- | ----------- | +| `jobId` | string | 请求的作业 ID | + +### `sendgrid_create_template` + +在 SendGrid 中创建一个新的电子邮件模板 + +#### 输入 + +| 参数 | 类型 | 必需 | 描述 | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | 是 | SendGrid API 密钥 | +| `name` | string | 是 | 模板名称 | +| `generation` | string | 否 | 模板生成类型(legacy 或 dynamic,默认值:dynamic) | + +#### 输出 + +| 参数 | 类型 | 描述 | +| --------- | ---- | ----------- | +| `id` | string | 模板 ID | +| `name` | string | 模板名称 | +| `generation` | string | 模板生成 | +| `updatedAt` | string | 最后更新时间戳 | +| `versions` | json | 模板版本数组 | + +### `sendgrid_get_template` + +通过 ID 从 SendGrid 获取特定模板 + +#### 输入 + +| 参数 | 类型 | 必需 | 描述 | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | 是 | SendGrid API 密钥 | +| `templateId` | string | 是 | 模板 ID | + +#### 输出 + +| 参数 | 类型 | 描述 | +| --------- | ---- | ----------- | +| `id` | string | 模板 ID | +| `name` | string | 模板名称 | +| `generation` | string | 模板生成 | +| `updatedAt` | string | 最后更新时间戳 | +| `versions` | json | 模板版本数组 | + +### `sendgrid_list_templates` + +从 SendGrid 获取所有电子邮件模板 + +#### 输入 + +| 参数 | 类型 | 必需 | 描述 | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | 是 | SendGrid API 密钥 | +| `generations` | string | 否 | 按生成方式筛选 \(legacy、dynamic 或 both\) | +| `pageSize` | number | 否 | 每页返回的模板数量 \(默认值: 20\) | + +#### 输出 + +| 参数 | 类型 | 描述 | +| --------- | ---- | ----------- | +| `templates` | json | 模板数组 | + +### `sendgrid_delete_template` + +从 SendGrid 删除电子邮件模板 + +#### 输入 + +| 参数 | 类型 | 必需 | 描述 | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | 是 | SendGrid API 密钥 | +| `templateId` | string | 是 | 要删除的模板 ID | + +#### 输出 + +| 参数 | 类型 | 描述 | +| --------- | ---- | ----------- | +| `success` | boolean | 操作成功状态 | +| `messageId` | string | 电子邮件消息 ID \(send_mail\) | +| `id` | string | 资源 ID | +| `jobId` | string | 异步操作的作业 ID | +| `email` | string | 电子邮件地址 | +| `firstName` | string | 名字 | +| `lastName` | string | 姓氏 | +| `contacts` | json | 联系人数组 | +| `contactCount` | number | 联系人数量 | +| `lists` | json | 列表数组 | +| `templates` | json | 模板数组 | +| `message` | string | 状态或成功消息 | +| `name` | string | 资源名称 | +| `generation` | string | 模板生成方式 | + +### `sendgrid_create_template_version` + +在 SendGrid 中创建一个新的电子邮件模板版本 + +#### 输入 + +| 参数 | 类型 | 必需 | 描述 | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | 是 | SendGrid API 密钥 | +| `templateId` | string | 是 | 模板 ID | +| `name` | string | 是 | 版本名称 | +| `subject` | string | 是 | 电子邮件主题行 | +| `htmlContent` | string | 否 | 模板的 HTML 内容 | +| `plainContent` | string | 否 | 模板的纯文本内容 | +| `active` | boolean | 否 | 此版本是否为激活状态(默认:true) | + +#### 输出 + +| 参数 | 类型 | 描述 | +| --------- | ---- | ----------- | +| `id` | string | 版本 ID | +| `templateId` | string | 模板 ID | +| `name` | string | 版本名称 | +| `subject` | string | 电子邮件主题 | +| `active` | boolean | 此版本是否为激活状态 | +| `htmlContent` | string | HTML 内容 | +| `plainContent` | string | 纯文本内容 | +| `updatedAt` | string | 最后更新时间戳 | + +## 注意事项 + +- 类别:`tools` +- 类型:`sendgrid` diff --git a/apps/docs/content/docs/zh/tools/smtp.mdx b/apps/docs/content/docs/zh/tools/smtp.mdx new file mode 100644 index 0000000000..ea2b6da153 --- /dev/null +++ b/apps/docs/content/docs/zh/tools/smtp.mdx @@ -0,0 +1,73 @@ +--- +title: SMTP +description: 通过任何 SMTP 邮件服务器发送电子邮件 +--- + +import { BlockInfoCard } from "@/components/ui/block-info-card" + + + +{/* MANUAL-CONTENT-START:intro */} +[SMTP(简单邮件传输协议)](https://en.wikipedia.org/wiki/Simple_Mail_Transfer_Protocol) 是互联网电子邮件传输的基础标准。通过连接任何兼容 SMTP 的服务器(如 Gmail、Outlook 或您组织的邮件基础设施),您可以以编程方式发送电子邮件并自动化您的外发通信。 + +SMTP 集成允许您通过直接的服务器连接完全自定义电子邮件发送,支持基本和高级的电子邮件使用场景。使用 SMTP,您可以控制消息传递、收件人管理和内容格式的每个方面,使其适用于事务性通知、大量邮件发送以及任何需要强大外发电子邮件传递的自动化工作流程。 + +**通过 SMTP 集成可用的关键功能包括:** + +- **通用电子邮件传递:** 通过配置标准服务器连接参数,使用任何 SMTP 服务器发送电子邮件。 +- **可自定义的发件人和收件人:** 指定发件人地址、显示名称、主要收件人,以及抄送 (CC) 和密送 (BCC) 字段。 +- **丰富的内容支持:** 根据您的需求发送纯文本或格式丰富的 HTML 电子邮件。 +- **附件:** 在外发电子邮件中包含多个文件作为附件。 +- **灵活的安全性:** 根据您的 SMTP 提供商支持的协议,使用 TLS、SSL 或标准(未加密)协议进行连接。 +- **高级头信息:** 设置回复地址头和其他高级电子邮件选项,以满足复杂的邮件流和用户交互需求。 + +通过将 SMTP 与 Sim 集成,代理和工作流程可以以编程方式将电子邮件作为任何自动化流程的一部分发送——从发送通知和确认,到自动化外部通信、报告和文档传递。这提供了一种高度灵活、与提供商无关的方法,可以直接在您的 AI 驱动流程中管理电子邮件。 +{/* MANUAL-CONTENT-END */} + +## 使用说明 + +使用任何 SMTP 服务器(如 Gmail、Outlook、自定义服务器等)发送电子邮件。配置 SMTP 连接设置,并完全控制内容、收件人和附件来发送电子邮件。 + +## 工具 + +### `smtp_send_mail` + +通过 SMTP 服务器发送电子邮件 + +#### 输入 + +| 参数 | 类型 | 必需 | 描述 | +| --------- | ---- | -------- | ----------- | +| `smtpHost` | string | 是 | SMTP 服务器主机名(例如:smtp.gmail.com) | +| `smtpPort` | number | 是 | SMTP 服务器端口(TLS 为 587,SSL 为 465) | +| `smtpUsername` | string | 是 | SMTP 身份验证用户名 | +| `smtpPassword` | string | 是 | SMTP 身份验证密码 | +| `smtpSecure` | string | 是 | 安全协议(TLS、SSL 或无) | +| `from` | string | 是 | 发件人电子邮件地址 | +| `to` | string | 是 | 收件人电子邮件地址 | +| `subject` | string | 是 | 电子邮件主题 | +| `body` | string | 是 | 电子邮件正文内容 | +| `contentType` | string | 否 | 内容类型(text 或 html) | +| `fromName` | string | 否 | 发件人显示名称 | +| `cc` | string | 否 | 抄送收件人(逗号分隔) | +| `bcc` | string | 否 | 密送收件人(逗号分隔) | +| `replyTo` | string | 否 | 回复电子邮件地址 | +| `attachments` | file[] | 否 | 附加到电子邮件的文件 | + +#### 输出 + +| 参数 | 类型 | 描述 | +| --------- | ---- | ----------- | +| `success` | boolean | 邮件是否成功发送 | +| `messageId` | string | 来自 SMTP 服务器的消息 ID | +| `to` | string | 收件人电子邮件地址 | +| `subject` | string | 电子邮件主题 | +| `error` | string | 如果发送失败的错误消息 | + +## 注意 + +- 分类:`tools` +- 类型:`smtp` diff --git a/apps/docs/i18n.lock b/apps/docs/i18n.lock index da130b768f..01bbc831c3 100644 --- a/apps/docs/i18n.lock +++ b/apps/docs/i18n.lock @@ -47114,3 +47114,227 @@ checksums: content/104: c6d621ee3cdc66de2c20b70a39aafe12 content/105: b3f310d5ef115bea5a8b75bf25d7ea9a content/106: 9d45ccf1c14d61412169be8f8510a960 + 9ed109808041fe9022eed66e1feedfdd: + meta/title: cba6e4eab965c94b8973e60e9ea10c05 + meta/description: 366d196f8f11ecd0e96516bb9181f8d5 + content/0: 1b031fb0c62c46b177aeed5c3d3f8f80 + content/1: dcf2843a8d5eb40192a44104c9c788a4 + content/2: 36ce181b1ca29664a1b6ddf4090623ae + content/3: 0a9d2b209e2a8b8fadda104bc42ea92e + content/4: 646bc61a952c9733ad296f441ae5ed9e + content/5: 40acc2cabeac1517944e2cb7b798b1b2 + content/6: c398c5b62380e61ee01e211a35d51aba + content/7: 821e6394b0a953e2b0842b04ae8f3105 + content/8: 46cd469dc3ba6864acfe2aedecb7d187 + content/9: 9c8aa3f09c9b2bd50ea4cdff3598ea4e + content/10: 7c66bb1ee02987bc4bc88217e9b3bac7 + content/11: bd55d02bd4275b49af4b4c8b7c43628e + content/12: 371d0e46b4bd2c23f559b8bc112f6955 + content/13: a962eddcfdc6875bcb08a64d34c9cf1d + content/14: bcadfc362b69078beee0088e5936c98b + content/15: 0dc1675d63e9b8cf974548f7f33baff9 + content/16: b3f310d5ef115bea5a8b75bf25d7ea9a + content/17: 591b0b21fdd6f07241c97381dcc7a554 + 21c5c74229b0ec1318fd47b3bff76fbb: + meta/title: 84ced5c0ab02fb2b72e8b6cfb40b4596 + meta/description: dca3d318d04d8b35a5a308daa424b261 + content/0: 1b031fb0c62c46b177aeed5c3d3f8f80 + content/1: 1731401b29cfa7e72b7e5b65f65c6267 + content/2: 3c4b8ba9b9a18779cc3946a989f8ef84 + content/3: be9b4ba1386fdfc17722872f13d8b065 + content/4: d503580fe34361dcb6496ec6694bc9e1 + content/5: 9dc3d3ec6dda629e88ae029b2d658bda + content/6: 9152b2bb77feff0b825c6520a86487b5 + content/7: dc6788f18a57dcb0577312e34e5d97db + content/8: 8b04440694729de9b0b36edd5ccba509 + content/9: 821e6394b0a953e2b0842b04ae8f3105 + content/10: 5363c89d96b289212e3b5a73f70c3189 + content/11: 9c8aa3f09c9b2bd50ea4cdff3598ea4e + content/12: da4762bf046b4612a3d998ca8933d92d + content/13: aa3b814b4a9c5553373e52aac8b87a52 + content/14: 371d0e46b4bd2c23f559b8bc112f6955 + content/15: 887b87a8f3a5bb5ea3fd8793f47b7c61 + content/16: bcadfc362b69078beee0088e5936c98b + content/17: e22392f49f990400f91cbb4cbee946e1 + content/18: 78d42fb8ee8a68ffa92ded3cc705edf1 + content/19: 911dab823f8bd10d7d8032976b3a6c8e + content/20: 371d0e46b4bd2c23f559b8bc112f6955 + content/21: 2bbd6012cfb6e25424f3b0f02aad3ce8 + content/22: bcadfc362b69078beee0088e5936c98b + content/23: 1b595fc6d3e2bb3848b99027ff373009 + content/24: df354436708823f474ec0fc1cd363b3c + content/25: f5fae0bbb4a96a36cda6feb280be5616 + content/26: 371d0e46b4bd2c23f559b8bc112f6955 + content/27: cbbc03735b74fd325a091ed38fe04e9e + content/28: bcadfc362b69078beee0088e5936c98b + content/29: 95e0542011571ed7f06b49a4ae797954 + content/30: 807141bcd9f7eae7756fdc6c7f3806da + content/31: cd7161901aeba94cb2ad2d99d22481f8 + content/32: 371d0e46b4bd2c23f559b8bc112f6955 + content/33: f9e775fe3343f469407896cf20b547e6 + content/34: bcadfc362b69078beee0088e5936c98b + content/35: b5e93d9a3d2d708d3b99e9d189c19646 + content/36: 179ccfc6418c245583fc29f53c15c39e + content/37: 1087b0f7d5002dfa4c48eb546245c81d + content/38: 371d0e46b4bd2c23f559b8bc112f6955 + content/39: 239897f78db49f1283dc5a78538a2a06 + content/40: bcadfc362b69078beee0088e5936c98b + content/41: d1b67021ac01a002ec893803e62ed45e + content/42: df8777f6df9c498e1585ffb5dd830410 + content/43: d6c88c6b676978de09aa638118477ae3 + content/44: 371d0e46b4bd2c23f559b8bc112f6955 + content/45: 2b306db45de9c58570b65d6cdcb6f247 + content/46: bcadfc362b69078beee0088e5936c98b + content/47: a42eb9722e411fdbe979e2da1ce0b151 + content/48: f3216a0403673adcb4a519dbdcfd4f15 + content/49: 937ed84a57f0ae6f8d4e6ad43de884ea + content/50: 371d0e46b4bd2c23f559b8bc112f6955 + content/51: d723f832f4ecf3110fd9cba4846d4e2d + content/52: bcadfc362b69078beee0088e5936c98b + content/53: a42eb9722e411fdbe979e2da1ce0b151 + content/54: 61d9d10a79f2efadbf1a4620a6ab23d4 + content/55: 8882e6b7157c5c200aa8fed20a510697 + content/56: 371d0e46b4bd2c23f559b8bc112f6955 + content/57: 44a38e8028982d5dbcb2f3c874fc9a61 + content/58: bcadfc362b69078beee0088e5936c98b + content/59: 8b48d2809c6fa1801db032f00f6d3358 + content/60: 50559acbfd25cd27b2a089d7118752c5 + content/61: a3c1b2172bf5f755bb418a33af668049 + content/62: 371d0e46b4bd2c23f559b8bc112f6955 + content/63: 215eb40066ac37e888a6f2e11350b43d + content/64: bcadfc362b69078beee0088e5936c98b + content/65: 2b3c80bcbce92fe344b5d92ace204b15 + content/66: 151113c0d69feef323a5b908914a7c26 + content/67: c858d6ce22f63c2b7e87889bbba17af8 + content/68: 371d0e46b4bd2c23f559b8bc112f6955 + content/69: 7a7210108b3f95a91a6dd7ab05d540e5 + content/70: bcadfc362b69078beee0088e5936c98b + content/71: 682c8f618848c1863ed7c349e1d2bd1e + content/72: 29d7490bf106ad4aec4dac9ee0e03d8e + content/73: e162edb4a88f5bb2772a6602061c5431 + content/74: 371d0e46b4bd2c23f559b8bc112f6955 + content/75: 52b03f6ee6d9127d28c257b56798e115 + content/76: bcadfc362b69078beee0088e5936c98b + content/77: 9faba3cf91d5594a2322f8312d081aef + content/78: cdf86d7591c580bec3e74ae3a3693bef + content/79: 3423a59063d9a61dd32733a60f93cff6 + content/80: 371d0e46b4bd2c23f559b8bc112f6955 + content/81: 331770e146f9a6b6030dfb970d02cd40 + content/82: bcadfc362b69078beee0088e5936c98b + content/83: 5144b9278e7aed0173286d6519681f92 + content/84: bd4c89e713278c619f95e5172e68d720 + content/85: 6694790c2343e744289bea26560c587d + content/86: 371d0e46b4bd2c23f559b8bc112f6955 + content/87: d12e5058c0c39696a7348b8e90805e15 + content/88: bcadfc362b69078beee0088e5936c98b + content/89: 5144b9278e7aed0173286d6519681f92 + content/90: a7aeeb8f5eab372cb2fe1f733ccfc011 + content/91: 38a0744c3a333cf6914314dfee7cae6e + content/92: 371d0e46b4bd2c23f559b8bc112f6955 + content/93: e43952eea5785b1057955aa786dc886d + content/94: bcadfc362b69078beee0088e5936c98b + content/95: 6234f5259e8566496dc450b45a01d9d1 + content/96: bdb0431ec63f0513e6babe371ba64242 + content/97: 8970f32aeb56c03b00e2ade3c37a93fc + content/98: 371d0e46b4bd2c23f559b8bc112f6955 + content/99: 23aaf026b4d450b5bd6047e3acfe9a71 + content/100: bcadfc362b69078beee0088e5936c98b + content/101: 7dec1de52492e6d0575c136baa1a8f92 + content/102: 22512b23811c21236e3ec39743e30267 + content/103: e70757a620b6d53b8232652c6f224100 + content/104: 371d0e46b4bd2c23f559b8bc112f6955 + content/105: 84e1bbd2e9a45147bb63d122082e4e5b + content/106: bcadfc362b69078beee0088e5936c98b + content/107: acced4eaee40332522d797538a7c626f + content/108: b3f310d5ef115bea5a8b75bf25d7ea9a + content/109: 545417dfa5925e97177baf6f0bea938a + f2d0730708c24f29942744f48297520b: + meta/title: b0301322c66fcbf604c6988c11a8a0b6 + meta/description: 54233683a87a944c333d0a27a15f297e + content/0: 1b031fb0c62c46b177aeed5c3d3f8f80 + content/1: 0aefa3b41a9d2ecaf2cfafe6818ed5d2 + content/2: 3f99340b6a2b22d8f91d8cabd457f4f5 + content/3: e64b467b3c7f0ade59c79c0a9a8da002 + content/4: a639faec4ba8d6237dd700c4c986f8cd + content/5: 533ecdbe1ca2f2c741613ad29d92ec3a + content/6: 856ec6f97e01acb2640d34a97299caee + content/7: 821e6394b0a953e2b0842b04ae8f3105 + content/8: 57ea3ddd02ed5668f79c3943eeb3dc76 + content/9: 9c8aa3f09c9b2bd50ea4cdff3598ea4e + content/10: 1dc07b63872647bf31f3a659eca63670 + content/11: d4f9d183b3eb7c221f2c407489a652c5 + content/12: 371d0e46b4bd2c23f559b8bc112f6955 + content/13: f1d12e7ac02f81ccf00664735284675d + content/14: bcadfc362b69078beee0088e5936c98b + content/15: 388eb8cab2572fad0d8e65e48ad71644 + content/16: e4e994f0ae036ee5029a316e0daa5294 + content/17: 63b60341cc9c1b453e8596dd70e51f1b + content/18: 371d0e46b4bd2c23f559b8bc112f6955 + content/19: df1d35c7ecc90e9ed2658561aa90d530 + content/20: bcadfc362b69078beee0088e5936c98b + content/21: 13df40111ce5ea2b93233798c40584e1 + content/22: 976dd71bcfd3d46c025abb54cdc55840 + content/23: d2af563f749bc199cb9680779f23bee8 + content/24: 371d0e46b4bd2c23f559b8bc112f6955 + content/25: 5808af08b8e5d0ab78a1552500867be3 + content/26: bcadfc362b69078beee0088e5936c98b + content/27: 678132234f320b948590cfe658b57c1d + content/28: 9f67006276134ac8926b413a1d313885 + content/29: 0db8b422ae23ee6da45b980902ce258c + content/30: 371d0e46b4bd2c23f559b8bc112f6955 + content/31: e69d59f4199d43f83756b63ae881254f + content/32: bcadfc362b69078beee0088e5936c98b + content/33: f6096e61d6e1fd14969b9a71672ff3fd + content/34: 46079dce2e875dfd4492ee61e3609bb6 + content/35: 97434ab9eddd245e0fe7b14ee242af6e + content/36: 371d0e46b4bd2c23f559b8bc112f6955 + content/37: d2d970ef7193db4c7358a08f580096a5 + content/38: bcadfc362b69078beee0088e5936c98b + content/39: ba4a733914da618ac8e703d18d35b7ff + content/40: 0ec0e400f9e3a1513126ad872ae2cfd1 + content/41: 9de50bb7fa9ef9e440680fba4022cfa7 + content/42: 371d0e46b4bd2c23f559b8bc112f6955 + content/43: 8a34532b8d71279eb841adcd6df3f8bb + content/44: bcadfc362b69078beee0088e5936c98b + content/45: ef8d1c704e7355d1c5c495641f85abc6 + content/46: 8a30961afc7ff0df6da3b9fa24a06490 + content/47: c6c81afbd48ed9f53de42cc945011dc3 + content/48: 371d0e46b4bd2c23f559b8bc112f6955 + content/49: e3722fb0dd04eaebcce70296b456acbc + content/50: bcadfc362b69078beee0088e5936c98b + content/51: 7f581ea28a88daa6235f93139c602778 + content/52: 18fbe27d3cd1f34db5fd225c07c5ed92 + content/53: 40c86fdce96ea2900fe530a7376b505c + content/54: 371d0e46b4bd2c23f559b8bc112f6955 + content/55: 94b2bd0c99bf1c4238a074ec656d5b95 + content/56: bcadfc362b69078beee0088e5936c98b + content/57: d05d281cd29c0d01b05d59ae86fca97c + content/58: b3f310d5ef115bea5a8b75bf25d7ea9a + content/59: 944967ad6f93d68dcc558ed4c596007a + 245cfde62d1f4c088b441aeb697ba253: + meta/title: f29b78f253094277c2e9ef79d10b5e4f + meta/description: 46968f07e726825dfd597fae01d571b7 + content/0: 1b031fb0c62c46b177aeed5c3d3f8f80 + content/1: 46c206e964c4a6a8aa2aab9ad583d4b4 + content/2: 7a80ab974b86980eedf9c963682af79c + content/3: 5707efa20a4903bed94356d557743546 + content/4: ebd030c32aef5a2dae774c4786fb6b62 + content/5: eb35ac44dc9c5e6d569b426251a7bdc7 + content/6: a14e113e70ac234065e31ab59bc82f8c + content/7: 821e6394b0a953e2b0842b04ae8f3105 + content/8: 025c8bd1feda3927e30b54bdd27a61c6 + content/9: 9c8aa3f09c9b2bd50ea4cdff3598ea4e + content/10: 35fd69ba2ad9468531fd35d31550ff24 + content/11: 0b70c103e0b75a1b268c4c1c2f6a65e1 + content/12: 371d0e46b4bd2c23f559b8bc112f6955 + content/13: 667ede88de3709d56afc2109da5482e6 + content/14: bcadfc362b69078beee0088e5936c98b + content/15: 0a7a099d582a926686c199dd7cc1f28c + content/16: 57863aa36fddd82b172a2ebd415c0105 + content/17: b7f6f6c25d65128ca1e361a03dbdd000 + content/18: 371d0e46b4bd2c23f559b8bc112f6955 + content/19: d71b6bb8e2dd6ce98101aec6a1dd77f2 + content/20: bcadfc362b69078beee0088e5936c98b + content/21: 0a7a099d582a926686c199dd7cc1f28c + content/22: b3f310d5ef115bea5a8b75bf25d7ea9a + content/23: 5edfd3643d5fa96be8bdbdb3c6e6905d From a8f87f7e3a104d4745616d6de50787ec5785bfaa Mon Sep 17 00:00:00 2001 From: Waleed Date: Sat, 29 Nov 2025 20:58:18 -0800 Subject: [PATCH 04/16] feat(creators): add verification for creators (#2135) --- .../[id]/route.ts | 6 +- .../sim/app/api/creators/[id]/verify/route.ts | 114 + .../{creator-profiles => creators}/route.ts | 4 +- apps/sim/app/templates/[id]/template.tsx | 68 +- .../templates/components/template-card.tsx | 8 +- apps/sim/app/templates/templates.tsx | 2 + .../templates/components/template-card.tsx | 8 +- .../[workspaceId]/templates/templates.tsx | 2 + .../components/template-deploy.tsx | 2 +- apps/sim/components/ui/verified-badge.tsx | 33 + apps/sim/hooks/queries/creator-profile.ts | 6 +- apps/sim/hooks/queries/templates.ts | 1 + .../db/migrations/0115_redundant_cerebro.sql | 1 + .../db/migrations/meta/0115_snapshot.json | 7702 +++++++++++++++++ packages/db/migrations/meta/_journal.json | 7 + packages/db/schema.ts | 1 + 16 files changed, 7944 insertions(+), 21 deletions(-) rename apps/sim/app/api/{creator-profiles => creators}/[id]/route.ts (96%) create mode 100644 apps/sim/app/api/creators/[id]/verify/route.ts rename apps/sim/app/api/{creator-profiles => creators}/route.ts (98%) create mode 100644 apps/sim/components/ui/verified-badge.tsx create mode 100644 packages/db/migrations/0115_redundant_cerebro.sql create mode 100644 packages/db/migrations/meta/0115_snapshot.json diff --git a/apps/sim/app/api/creator-profiles/[id]/route.ts b/apps/sim/app/api/creators/[id]/route.ts similarity index 96% rename from apps/sim/app/api/creator-profiles/[id]/route.ts rename to apps/sim/app/api/creators/[id]/route.ts index 6188d1ab70..886f5b7ddf 100644 --- a/apps/sim/app/api/creator-profiles/[id]/route.ts +++ b/apps/sim/app/api/creators/[id]/route.ts @@ -45,7 +45,7 @@ async function hasPermission(userId: string, profile: any): Promise { return false } -// GET /api/creator-profiles/[id] - Get a specific creator profile +// GET /api/creators/[id] - Get a specific creator profile export async function GET(request: NextRequest, { params }: { params: Promise<{ id: string }> }) { const requestId = generateRequestId() const { id } = await params @@ -70,7 +70,7 @@ export async function GET(request: NextRequest, { params }: { params: Promise<{ } } -// PUT /api/creator-profiles/[id] - Update a creator profile +// PUT /api/creators/[id] - Update a creator profile export async function PUT(request: NextRequest, { params }: { params: Promise<{ id: string }> }) { const requestId = generateRequestId() const { id } = await params @@ -135,7 +135,7 @@ export async function PUT(request: NextRequest, { params }: { params: Promise<{ } } -// DELETE /api/creator-profiles/[id] - Delete a creator profile +// DELETE /api/creators/[id] - Delete a creator profile export async function DELETE( request: NextRequest, { params }: { params: Promise<{ id: string }> } diff --git a/apps/sim/app/api/creators/[id]/verify/route.ts b/apps/sim/app/api/creators/[id]/verify/route.ts new file mode 100644 index 0000000000..9e29bbdfe5 --- /dev/null +++ b/apps/sim/app/api/creators/[id]/verify/route.ts @@ -0,0 +1,114 @@ +import { db } from '@sim/db' +import { templateCreators, user } from '@sim/db/schema' +import { eq } from 'drizzle-orm' +import { type NextRequest, NextResponse } from 'next/server' +import { getSession } from '@/lib/auth' +import { createLogger } from '@/lib/logs/console/logger' +import { generateRequestId } from '@/lib/utils' + +const logger = createLogger('CreatorVerificationAPI') + +export const revalidate = 0 + +// POST /api/creators/[id]/verify - Verify a creator (super users only) +export async function POST(request: NextRequest, { params }: { params: Promise<{ id: string }> }) { + const requestId = generateRequestId() + const { id } = await params + + try { + const session = await getSession() + if (!session?.user?.id) { + logger.warn(`[${requestId}] Unauthorized verification attempt for creator: ${id}`) + return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }) + } + + // Check if user is a super user + const currentUser = await db.select().from(user).where(eq(user.id, session.user.id)).limit(1) + + if (!currentUser[0]?.isSuperUser) { + logger.warn(`[${requestId}] Non-super user attempted to verify creator: ${id}`) + return NextResponse.json({ error: 'Only super users can verify creators' }, { status: 403 }) + } + + // Check if creator exists + const existingCreator = await db + .select() + .from(templateCreators) + .where(eq(templateCreators.id, id)) + .limit(1) + + if (existingCreator.length === 0) { + logger.warn(`[${requestId}] Creator not found for verification: ${id}`) + return NextResponse.json({ error: 'Creator not found' }, { status: 404 }) + } + + // Update creator verified status to true + await db + .update(templateCreators) + .set({ verified: true, updatedAt: new Date() }) + .where(eq(templateCreators.id, id)) + + logger.info(`[${requestId}] Creator verified: ${id} by super user: ${session.user.id}`) + + return NextResponse.json({ + message: 'Creator verified successfully', + creatorId: id, + }) + } catch (error) { + logger.error(`[${requestId}] Error verifying creator ${id}`, error) + return NextResponse.json({ error: 'Internal server error' }, { status: 500 }) + } +} + +// DELETE /api/creators/[id]/verify - Unverify a creator (super users only) +export async function DELETE( + request: NextRequest, + { params }: { params: Promise<{ id: string }> } +) { + const requestId = generateRequestId() + const { id } = await params + + try { + const session = await getSession() + if (!session?.user?.id) { + logger.warn(`[${requestId}] Unauthorized unverification attempt for creator: ${id}`) + return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }) + } + + // Check if user is a super user + const currentUser = await db.select().from(user).where(eq(user.id, session.user.id)).limit(1) + + if (!currentUser[0]?.isSuperUser) { + logger.warn(`[${requestId}] Non-super user attempted to unverify creator: ${id}`) + return NextResponse.json({ error: 'Only super users can unverify creators' }, { status: 403 }) + } + + // Check if creator exists + const existingCreator = await db + .select() + .from(templateCreators) + .where(eq(templateCreators.id, id)) + .limit(1) + + if (existingCreator.length === 0) { + logger.warn(`[${requestId}] Creator not found for unverification: ${id}`) + return NextResponse.json({ error: 'Creator not found' }, { status: 404 }) + } + + // Update creator verified status to false + await db + .update(templateCreators) + .set({ verified: false, updatedAt: new Date() }) + .where(eq(templateCreators.id, id)) + + logger.info(`[${requestId}] Creator unverified: ${id} by super user: ${session.user.id}`) + + return NextResponse.json({ + message: 'Creator unverified successfully', + creatorId: id, + }) + } catch (error) { + logger.error(`[${requestId}] Error unverifying creator ${id}`, error) + return NextResponse.json({ error: 'Internal server error' }, { status: 500 }) + } +} diff --git a/apps/sim/app/api/creator-profiles/route.ts b/apps/sim/app/api/creators/route.ts similarity index 98% rename from apps/sim/app/api/creator-profiles/route.ts rename to apps/sim/app/api/creators/route.ts index f6f67ea3d5..13c6d34f18 100644 --- a/apps/sim/app/api/creator-profiles/route.ts +++ b/apps/sim/app/api/creators/route.ts @@ -27,7 +27,7 @@ const CreateCreatorProfileSchema = z.object({ details: CreatorProfileDetailsSchema.optional(), }) -// GET /api/creator-profiles - Get creator profiles for current user +// GET /api/creators - Get creator profiles for current user export async function GET(request: NextRequest) { const requestId = generateRequestId() const { searchParams } = new URL(request.url) @@ -81,7 +81,7 @@ export async function GET(request: NextRequest) { } } -// POST /api/creator-profiles - Create a new creator profile +// POST /api/creators - Create a new creator profile export async function POST(request: NextRequest) { const requestId = generateRequestId() diff --git a/apps/sim/app/templates/[id]/template.tsx b/apps/sim/app/templates/[id]/template.tsx index 4f87e24b15..881141e6af 100644 --- a/apps/sim/app/templates/[id]/template.tsx +++ b/apps/sim/app/templates/[id]/template.tsx @@ -29,6 +29,7 @@ import { DropdownMenuItem, DropdownMenuTrigger, } from '@/components/ui/dropdown-menu' +import { VerifiedBadge } from '@/components/ui/verified-badge' import { useSession } from '@/lib/auth-client' import { createLogger } from '@/lib/logs/console/logger' import { getBaseUrl } from '@/lib/urls/utils' @@ -64,6 +65,7 @@ export default function TemplateDetails({ isWorkspaceContext = false }: Template const [isEditing, setIsEditing] = useState(false) const [isApproving, setIsApproving] = useState(false) const [isRejecting, setIsRejecting] = useState(false) + const [isVerifying, setIsVerifying] = useState(false) const [hasWorkspaceAccess, setHasWorkspaceAccess] = useState(null) const [workspaces, setWorkspaces] = useState< Array<{ id: string; name: string; permissions: string }> @@ -462,6 +464,32 @@ export default function TemplateDetails({ isWorkspaceContext = false }: Template } } + const handleToggleVerification = async () => { + if (isVerifying || !template?.creator?.id) return + + setIsVerifying(true) + try { + const endpoint = `/api/creators/${template.creator.id}/verify` + const method = template.creator.verified ? 'DELETE' : 'POST' + + const response = await fetch(endpoint, { method }) + + if (response.ok) { + // Refresh page to show updated verification status + window.location.reload() + } else { + const error = await response.json() + logger.error('Error toggling verification:', error) + alert(`Failed to ${template.creator.verified ? 'unverify' : 'verify'} creator`) + } + } catch (error) { + logger.error('Error toggling verification:', error) + alert('An error occurred while toggling verification') + } finally { + setIsVerifying(false) + } + } + /** * Shares the template to X (Twitter) */ @@ -718,9 +746,12 @@ export default function TemplateDetails({ isWorkspaceContext = false }: Template )} {/* Creator name */} - - {template.creator?.name || 'Unknown'} - +
+ + {template.creator?.name || 'Unknown'} + + {template.creator?.verified && } +
{/* Credentials needed */} @@ -849,9 +880,25 @@ export default function TemplateDetails({ isWorkspaceContext = false }: Template template.creator.details?.websiteUrl || template.creator.details?.contactEmail) && (
-

- About the Creator -

+
+

+ About the Creator +

+ {isSuperUser && template.creator && ( + + )} +
{/* Creator profile image */} {template.creator.profileImageUrl ? ( @@ -871,9 +918,12 @@ export default function TemplateDetails({ isWorkspaceContext = false }: Template {/* Creator details */}
-

- {template.creator.name} -

+
+

+ {template.creator.name} +

+ {template.creator.verified && } +
{/* Social links */}
diff --git a/apps/sim/app/templates/components/template-card.tsx b/apps/sim/app/templates/components/template-card.tsx index 9ec3cacc6d..1731cc97f1 100644 --- a/apps/sim/app/templates/components/template-card.tsx +++ b/apps/sim/app/templates/components/template-card.tsx @@ -1,6 +1,7 @@ import { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react' import { Star, User } from 'lucide-react' import { useParams, useRouter } from 'next/navigation' +import { VerifiedBadge } from '@/components/ui/verified-badge' import { createLogger } from '@/lib/logs/console/logger' import { cn } from '@/lib/utils' import { WorkflowPreview } from '@/app/workspace/[workspaceId]/w/components/workflow-preview/workflow-preview' @@ -21,6 +22,7 @@ interface TemplateCardProps { className?: string state?: WorkflowState isStarred?: boolean + isVerified?: boolean } export function TemplateCardSkeleton({ className }: { className?: string }) { @@ -125,6 +127,7 @@ function TemplateCardInner({ className, state, isStarred = false, + isVerified = false, }: TemplateCardProps) { const router = useRouter() const params = useParams() @@ -276,7 +279,10 @@ function TemplateCardInner({
)} - {author} +
+ {author} + {isVerified && } +
diff --git a/apps/sim/app/templates/templates.tsx b/apps/sim/app/templates/templates.tsx index 45a3e0956d..75b4e5905a 100644 --- a/apps/sim/app/templates/templates.tsx +++ b/apps/sim/app/templates/templates.tsx @@ -30,6 +30,7 @@ export interface Template { details?: CreatorProfileDetails | null referenceType: 'user' | 'organization' referenceId: string + verified?: boolean } | null views: number stars: number @@ -203,6 +204,7 @@ export default function Templates({ stars={template.stars} state={template.state} isStarred={template.isStarred} + isVerified={template.creator?.verified || false} /> )) )} diff --git a/apps/sim/app/workspace/[workspaceId]/templates/components/template-card.tsx b/apps/sim/app/workspace/[workspaceId]/templates/components/template-card.tsx index 250503898b..5723806965 100644 --- a/apps/sim/app/workspace/[workspaceId]/templates/components/template-card.tsx +++ b/apps/sim/app/workspace/[workspaceId]/templates/components/template-card.tsx @@ -1,6 +1,7 @@ import { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react' import { Star, User } from 'lucide-react' import { useParams, useRouter } from 'next/navigation' +import { VerifiedBadge } from '@/components/ui/verified-badge' import { createLogger } from '@/lib/logs/console/logger' import { cn } from '@/lib/utils' import { WorkflowPreview } from '@/app/workspace/[workspaceId]/w/components/workflow-preview/workflow-preview' @@ -21,6 +22,7 @@ interface TemplateCardProps { className?: string state?: WorkflowState isStarred?: boolean + isVerified?: boolean } export function TemplateCardSkeleton({ className }: { className?: string }) { @@ -126,6 +128,7 @@ function TemplateCardInner({ className, state, isStarred = false, + isVerified = false, }: TemplateCardProps) { const router = useRouter() const params = useParams() @@ -277,7 +280,10 @@ function TemplateCardInner({
)} - {author} +
+ {author} + {isVerified && } +
diff --git a/apps/sim/app/workspace/[workspaceId]/templates/templates.tsx b/apps/sim/app/workspace/[workspaceId]/templates/templates.tsx index 5a3b95c53f..d572c2baf9 100644 --- a/apps/sim/app/workspace/[workspaceId]/templates/templates.tsx +++ b/apps/sim/app/workspace/[workspaceId]/templates/templates.tsx @@ -34,6 +34,7 @@ export interface Template { details?: CreatorProfileDetails | null referenceType: 'user' | 'organization' referenceId: string + verified?: boolean } | null views: number stars: number @@ -223,6 +224,7 @@ export default function Templates({ stars={template.stars} state={template.state} isStarred={template.isStarred} + isVerified={template.creator?.verified || false} /> ) }) diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/deploy/components/deploy-modal/components/template-deploy.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/deploy/components/deploy-modal/components/template-deploy.tsx index e56b7c7564..76e5e8ebd2 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/deploy/components/deploy-modal/components/template-deploy.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/deploy/components/deploy-modal/components/template-deploy.tsx @@ -87,7 +87,7 @@ export function TemplateDeploy({ workflowId, onDeploymentComplete }: TemplateDep setLoadingCreators(true) try { - const response = await fetch('/api/creator-profiles') + const response = await fetch('/api/creators') if (response.ok) { const data = await response.json() const profiles = (data.profiles || []).map((profile: any) => ({ diff --git a/apps/sim/components/ui/verified-badge.tsx b/apps/sim/components/ui/verified-badge.tsx new file mode 100644 index 0000000000..e17dd53d0a --- /dev/null +++ b/apps/sim/components/ui/verified-badge.tsx @@ -0,0 +1,33 @@ +import { cn } from '@/lib/utils' + +interface VerifiedBadgeProps { + className?: string + size?: 'sm' | 'md' | 'lg' +} + +export function VerifiedBadge({ className, size = 'md' }: VerifiedBadgeProps) { + const sizeMap = { + sm: 12, + md: 14, + lg: 16, + } + + const dimension = sizeMap[size] + + return ( +
+ + + +
+ ) +} diff --git a/apps/sim/hooks/queries/creator-profile.ts b/apps/sim/hooks/queries/creator-profile.ts index 7dea4f5838..59197ca623 100644 --- a/apps/sim/hooks/queries/creator-profile.ts +++ b/apps/sim/hooks/queries/creator-profile.ts @@ -67,7 +67,7 @@ export function useOrganizations() { * Fetch creator profile for a user */ async function fetchCreatorProfile(userId: string): Promise { - const response = await fetch(`/api/creator-profiles?userId=${userId}`) + const response = await fetch(`/api/creators?userId=${userId}`) // Treat 404 as "no profile" if (response.status === 404) { @@ -133,9 +133,7 @@ export function useSaveCreatorProfile() { details: details && Object.keys(details).length > 0 ? details : undefined, } - const url = existingProfileId - ? `/api/creator-profiles/${existingProfileId}` - : '/api/creator-profiles' + const url = existingProfileId ? `/api/creators/${existingProfileId}` : '/api/creators' const method = existingProfileId ? 'PUT' : 'POST' const response = await fetch(url, { diff --git a/apps/sim/hooks/queries/templates.ts b/apps/sim/hooks/queries/templates.ts index 1b3824a248..8e9166b8c2 100644 --- a/apps/sim/hooks/queries/templates.ts +++ b/apps/sim/hooks/queries/templates.ts @@ -30,6 +30,7 @@ export interface TemplateCreator { email?: string website?: string profileImageUrl?: string | null + verified?: boolean details?: { about?: string xUrl?: string diff --git a/packages/db/migrations/0115_redundant_cerebro.sql b/packages/db/migrations/0115_redundant_cerebro.sql new file mode 100644 index 0000000000..718aa9492b --- /dev/null +++ b/packages/db/migrations/0115_redundant_cerebro.sql @@ -0,0 +1 @@ +ALTER TABLE "template_creators" ADD COLUMN "verified" boolean DEFAULT false NOT NULL; \ No newline at end of file diff --git a/packages/db/migrations/meta/0115_snapshot.json b/packages/db/migrations/meta/0115_snapshot.json new file mode 100644 index 0000000000..d032e489cb --- /dev/null +++ b/packages/db/migrations/meta/0115_snapshot.json @@ -0,0 +1,7702 @@ +{ + "id": "462d46ca-8c69-4c3e-b11d-373938063d38", + "prevId": "eaeb84c0-4e54-4530-afb5-66ee0f62e163", + "version": "7", + "dialect": "postgresql", + "tables": { + "public.account": { + "name": "account", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "account_id": { + "name": "account_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "provider_id": { + "name": "provider_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "access_token": { + "name": "access_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "refresh_token": { + "name": "refresh_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "id_token": { + "name": "id_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "access_token_expires_at": { + "name": "access_token_expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "refresh_token_expires_at": { + "name": "refresh_token_expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "scope": { + "name": "scope", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "password": { + "name": "password", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "account_user_id_idx": { + "name": "account_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_account_on_account_id_provider_id": { + "name": "idx_account_on_account_id_provider_id", + "columns": [ + { + "expression": "account_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "provider_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "account_user_id_user_id_fk": { + "name": "account_user_id_user_id_fk", + "tableFrom": "account", + "tableTo": "user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.api_key": { + "name": "api_key", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_by": { + "name": "created_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'personal'" + }, + "last_used": { + "name": "last_used", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "api_key_user_id_user_id_fk": { + "name": "api_key_user_id_user_id_fk", + "tableFrom": "api_key", + "tableTo": "user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "api_key_workspace_id_workspace_id_fk": { + "name": "api_key_workspace_id_workspace_id_fk", + "tableFrom": "api_key", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "api_key_created_by_user_id_fk": { + "name": "api_key_created_by_user_id_fk", + "tableFrom": "api_key", + "tableTo": "user", + "columnsFrom": ["created_by"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "api_key_key_unique": { + "name": "api_key_key_unique", + "nullsNotDistinct": false, + "columns": ["key"] + } + }, + "policies": {}, + "checkConstraints": { + "workspace_type_check": { + "name": "workspace_type_check", + "value": "(type = 'workspace' AND workspace_id IS NOT NULL) OR (type = 'personal' AND workspace_id IS NULL)" + } + }, + "isRLSEnabled": false + }, + "public.chat": { + "name": "chat", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "identifier": { + "name": "identifier", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "is_active": { + "name": "is_active", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "customizations": { + "name": "customizations", + "type": "json", + "primaryKey": false, + "notNull": false, + "default": "'{}'" + }, + "auth_type": { + "name": "auth_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'public'" + }, + "password": { + "name": "password", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "allowed_emails": { + "name": "allowed_emails", + "type": "json", + "primaryKey": false, + "notNull": false, + "default": "'[]'" + }, + "output_configs": { + "name": "output_configs", + "type": "json", + "primaryKey": false, + "notNull": false, + "default": "'[]'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "identifier_idx": { + "name": "identifier_idx", + "columns": [ + { + "expression": "identifier", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "chat_workflow_id_workflow_id_fk": { + "name": "chat_workflow_id_workflow_id_fk", + "tableFrom": "chat", + "tableTo": "workflow", + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "chat_user_id_user_id_fk": { + "name": "chat_user_id_user_id_fk", + "tableFrom": "chat", + "tableTo": "user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.copilot_chats": { + "name": "copilot_chats", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "messages": { + "name": "messages", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'[]'" + }, + "model": { + "name": "model", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'claude-3-7-sonnet-latest'" + }, + "conversation_id": { + "name": "conversation_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "preview_yaml": { + "name": "preview_yaml", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "plan_artifact": { + "name": "plan_artifact", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "config": { + "name": "config", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "copilot_chats_user_id_idx": { + "name": "copilot_chats_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "copilot_chats_workflow_id_idx": { + "name": "copilot_chats_workflow_id_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "copilot_chats_user_workflow_idx": { + "name": "copilot_chats_user_workflow_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "copilot_chats_created_at_idx": { + "name": "copilot_chats_created_at_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "copilot_chats_updated_at_idx": { + "name": "copilot_chats_updated_at_idx", + "columns": [ + { + "expression": "updated_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "copilot_chats_user_id_user_id_fk": { + "name": "copilot_chats_user_id_user_id_fk", + "tableFrom": "copilot_chats", + "tableTo": "user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "copilot_chats_workflow_id_workflow_id_fk": { + "name": "copilot_chats_workflow_id_workflow_id_fk", + "tableFrom": "copilot_chats", + "tableTo": "workflow", + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.copilot_feedback": { + "name": "copilot_feedback", + "schema": "", + "columns": { + "feedback_id": { + "name": "feedback_id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "chat_id": { + "name": "chat_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "user_query": { + "name": "user_query", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "agent_response": { + "name": "agent_response", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "is_positive": { + "name": "is_positive", + "type": "boolean", + "primaryKey": false, + "notNull": true + }, + "feedback": { + "name": "feedback", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "workflow_yaml": { + "name": "workflow_yaml", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "copilot_feedback_user_id_idx": { + "name": "copilot_feedback_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "copilot_feedback_chat_id_idx": { + "name": "copilot_feedback_chat_id_idx", + "columns": [ + { + "expression": "chat_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "copilot_feedback_user_chat_idx": { + "name": "copilot_feedback_user_chat_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "chat_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "copilot_feedback_is_positive_idx": { + "name": "copilot_feedback_is_positive_idx", + "columns": [ + { + "expression": "is_positive", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "copilot_feedback_created_at_idx": { + "name": "copilot_feedback_created_at_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "copilot_feedback_user_id_user_id_fk": { + "name": "copilot_feedback_user_id_user_id_fk", + "tableFrom": "copilot_feedback", + "tableTo": "user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "copilot_feedback_chat_id_copilot_chats_id_fk": { + "name": "copilot_feedback_chat_id_copilot_chats_id_fk", + "tableFrom": "copilot_feedback", + "tableTo": "copilot_chats", + "columnsFrom": ["chat_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.custom_tools": { + "name": "custom_tools", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "schema": { + "name": "schema", + "type": "json", + "primaryKey": false, + "notNull": true + }, + "code": { + "name": "code", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "custom_tools_workspace_id_idx": { + "name": "custom_tools_workspace_id_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "custom_tools_workspace_title_unique": { + "name": "custom_tools_workspace_title_unique", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "title", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "custom_tools_workspace_id_workspace_id_fk": { + "name": "custom_tools_workspace_id_workspace_id_fk", + "tableFrom": "custom_tools", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "custom_tools_user_id_user_id_fk": { + "name": "custom_tools_user_id_user_id_fk", + "tableFrom": "custom_tools", + "tableTo": "user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.docs_embeddings": { + "name": "docs_embeddings", + "schema": "", + "columns": { + "chunk_id": { + "name": "chunk_id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "chunk_text": { + "name": "chunk_text", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "source_document": { + "name": "source_document", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "source_link": { + "name": "source_link", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "header_text": { + "name": "header_text", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "header_level": { + "name": "header_level", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "token_count": { + "name": "token_count", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "embedding": { + "name": "embedding", + "type": "vector(1536)", + "primaryKey": false, + "notNull": true + }, + "embedding_model": { + "name": "embedding_model", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'text-embedding-3-small'" + }, + "metadata": { + "name": "metadata", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "chunk_text_tsv": { + "name": "chunk_text_tsv", + "type": "tsvector", + "primaryKey": false, + "notNull": false, + "generated": { + "as": "to_tsvector('english', \"docs_embeddings\".\"chunk_text\")", + "type": "stored" + } + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "docs_emb_source_document_idx": { + "name": "docs_emb_source_document_idx", + "columns": [ + { + "expression": "source_document", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "docs_emb_header_level_idx": { + "name": "docs_emb_header_level_idx", + "columns": [ + { + "expression": "header_level", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "docs_emb_source_header_idx": { + "name": "docs_emb_source_header_idx", + "columns": [ + { + "expression": "source_document", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "header_level", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "docs_emb_model_idx": { + "name": "docs_emb_model_idx", + "columns": [ + { + "expression": "embedding_model", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "docs_emb_created_at_idx": { + "name": "docs_emb_created_at_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "docs_embedding_vector_hnsw_idx": { + "name": "docs_embedding_vector_hnsw_idx", + "columns": [ + { + "expression": "embedding", + "isExpression": false, + "asc": true, + "nulls": "last", + "opclass": "vector_cosine_ops" + } + ], + "isUnique": false, + "concurrently": false, + "method": "hnsw", + "with": { + "m": 16, + "ef_construction": 64 + } + }, + "docs_emb_metadata_gin_idx": { + "name": "docs_emb_metadata_gin_idx", + "columns": [ + { + "expression": "metadata", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "gin", + "with": {} + }, + "docs_emb_chunk_text_fts_idx": { + "name": "docs_emb_chunk_text_fts_idx", + "columns": [ + { + "expression": "chunk_text_tsv", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "gin", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "docs_embedding_not_null_check": { + "name": "docs_embedding_not_null_check", + "value": "\"embedding\" IS NOT NULL" + }, + "docs_header_level_check": { + "name": "docs_header_level_check", + "value": "\"header_level\" >= 1 AND \"header_level\" <= 6" + } + }, + "isRLSEnabled": false + }, + "public.document": { + "name": "document", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "knowledge_base_id": { + "name": "knowledge_base_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "filename": { + "name": "filename", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "file_url": { + "name": "file_url", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "file_size": { + "name": "file_size", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "mime_type": { + "name": "mime_type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "chunk_count": { + "name": "chunk_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "token_count": { + "name": "token_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "character_count": { + "name": "character_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "processing_status": { + "name": "processing_status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "processing_started_at": { + "name": "processing_started_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "processing_completed_at": { + "name": "processing_completed_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "processing_error": { + "name": "processing_error", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "enabled": { + "name": "enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "deleted_at": { + "name": "deleted_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "tag1": { + "name": "tag1", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tag2": { + "name": "tag2", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tag3": { + "name": "tag3", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tag4": { + "name": "tag4", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tag5": { + "name": "tag5", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tag6": { + "name": "tag6", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tag7": { + "name": "tag7", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "uploaded_at": { + "name": "uploaded_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "doc_kb_id_idx": { + "name": "doc_kb_id_idx", + "columns": [ + { + "expression": "knowledge_base_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "doc_filename_idx": { + "name": "doc_filename_idx", + "columns": [ + { + "expression": "filename", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "doc_processing_status_idx": { + "name": "doc_processing_status_idx", + "columns": [ + { + "expression": "knowledge_base_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "processing_status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "doc_tag1_idx": { + "name": "doc_tag1_idx", + "columns": [ + { + "expression": "tag1", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "doc_tag2_idx": { + "name": "doc_tag2_idx", + "columns": [ + { + "expression": "tag2", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "doc_tag3_idx": { + "name": "doc_tag3_idx", + "columns": [ + { + "expression": "tag3", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "doc_tag4_idx": { + "name": "doc_tag4_idx", + "columns": [ + { + "expression": "tag4", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "doc_tag5_idx": { + "name": "doc_tag5_idx", + "columns": [ + { + "expression": "tag5", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "doc_tag6_idx": { + "name": "doc_tag6_idx", + "columns": [ + { + "expression": "tag6", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "doc_tag7_idx": { + "name": "doc_tag7_idx", + "columns": [ + { + "expression": "tag7", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "document_knowledge_base_id_knowledge_base_id_fk": { + "name": "document_knowledge_base_id_knowledge_base_id_fk", + "tableFrom": "document", + "tableTo": "knowledge_base", + "columnsFrom": ["knowledge_base_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.embedding": { + "name": "embedding", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "knowledge_base_id": { + "name": "knowledge_base_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "document_id": { + "name": "document_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "chunk_index": { + "name": "chunk_index", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "chunk_hash": { + "name": "chunk_hash", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "content": { + "name": "content", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "content_length": { + "name": "content_length", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "token_count": { + "name": "token_count", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "embedding": { + "name": "embedding", + "type": "vector(1536)", + "primaryKey": false, + "notNull": false + }, + "embedding_model": { + "name": "embedding_model", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'text-embedding-3-small'" + }, + "start_offset": { + "name": "start_offset", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "end_offset": { + "name": "end_offset", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "tag1": { + "name": "tag1", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tag2": { + "name": "tag2", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tag3": { + "name": "tag3", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tag4": { + "name": "tag4", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tag5": { + "name": "tag5", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tag6": { + "name": "tag6", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tag7": { + "name": "tag7", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "enabled": { + "name": "enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "content_tsv": { + "name": "content_tsv", + "type": "tsvector", + "primaryKey": false, + "notNull": false, + "generated": { + "as": "to_tsvector('english', \"embedding\".\"content\")", + "type": "stored" + } + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "emb_kb_id_idx": { + "name": "emb_kb_id_idx", + "columns": [ + { + "expression": "knowledge_base_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "emb_doc_id_idx": { + "name": "emb_doc_id_idx", + "columns": [ + { + "expression": "document_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "emb_doc_chunk_idx": { + "name": "emb_doc_chunk_idx", + "columns": [ + { + "expression": "document_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "chunk_index", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "emb_kb_model_idx": { + "name": "emb_kb_model_idx", + "columns": [ + { + "expression": "knowledge_base_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "embedding_model", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "emb_kb_enabled_idx": { + "name": "emb_kb_enabled_idx", + "columns": [ + { + "expression": "knowledge_base_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "enabled", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "emb_doc_enabled_idx": { + "name": "emb_doc_enabled_idx", + "columns": [ + { + "expression": "document_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "enabled", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "embedding_vector_hnsw_idx": { + "name": "embedding_vector_hnsw_idx", + "columns": [ + { + "expression": "embedding", + "isExpression": false, + "asc": true, + "nulls": "last", + "opclass": "vector_cosine_ops" + } + ], + "isUnique": false, + "concurrently": false, + "method": "hnsw", + "with": { + "m": 16, + "ef_construction": 64 + } + }, + "emb_tag1_idx": { + "name": "emb_tag1_idx", + "columns": [ + { + "expression": "tag1", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "emb_tag2_idx": { + "name": "emb_tag2_idx", + "columns": [ + { + "expression": "tag2", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "emb_tag3_idx": { + "name": "emb_tag3_idx", + "columns": [ + { + "expression": "tag3", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "emb_tag4_idx": { + "name": "emb_tag4_idx", + "columns": [ + { + "expression": "tag4", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "emb_tag5_idx": { + "name": "emb_tag5_idx", + "columns": [ + { + "expression": "tag5", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "emb_tag6_idx": { + "name": "emb_tag6_idx", + "columns": [ + { + "expression": "tag6", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "emb_tag7_idx": { + "name": "emb_tag7_idx", + "columns": [ + { + "expression": "tag7", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "emb_content_fts_idx": { + "name": "emb_content_fts_idx", + "columns": [ + { + "expression": "content_tsv", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "gin", + "with": {} + } + }, + "foreignKeys": { + "embedding_knowledge_base_id_knowledge_base_id_fk": { + "name": "embedding_knowledge_base_id_knowledge_base_id_fk", + "tableFrom": "embedding", + "tableTo": "knowledge_base", + "columnsFrom": ["knowledge_base_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "embedding_document_id_document_id_fk": { + "name": "embedding_document_id_document_id_fk", + "tableFrom": "embedding", + "tableTo": "document", + "columnsFrom": ["document_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "embedding_not_null_check": { + "name": "embedding_not_null_check", + "value": "\"embedding\" IS NOT NULL" + } + }, + "isRLSEnabled": false + }, + "public.environment": { + "name": "environment", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "variables": { + "name": "variables", + "type": "json", + "primaryKey": false, + "notNull": true + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "environment_user_id_user_id_fk": { + "name": "environment_user_id_user_id_fk", + "tableFrom": "environment", + "tableTo": "user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "environment_user_id_unique": { + "name": "environment_user_id_unique", + "nullsNotDistinct": false, + "columns": ["user_id"] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.idempotency_key": { + "name": "idempotency_key", + "schema": "", + "columns": { + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "namespace": { + "name": "namespace", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'default'" + }, + "result": { + "name": "result", + "type": "json", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "idempotency_key_namespace_unique": { + "name": "idempotency_key_namespace_unique", + "columns": [ + { + "expression": "key", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "namespace", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idempotency_key_created_at_idx": { + "name": "idempotency_key_created_at_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idempotency_key_namespace_idx": { + "name": "idempotency_key_namespace_idx", + "columns": [ + { + "expression": "namespace", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.invitation": { + "name": "invitation", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "inviter_id": { + "name": "inviter_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "invitation_email_idx": { + "name": "invitation_email_idx", + "columns": [ + { + "expression": "email", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "invitation_organization_id_idx": { + "name": "invitation_organization_id_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "invitation_inviter_id_user_id_fk": { + "name": "invitation_inviter_id_user_id_fk", + "tableFrom": "invitation", + "tableTo": "user", + "columnsFrom": ["inviter_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "invitation_organization_id_organization_id_fk": { + "name": "invitation_organization_id_organization_id_fk", + "tableFrom": "invitation", + "tableTo": "organization", + "columnsFrom": ["organization_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.knowledge_base": { + "name": "knowledge_base", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "token_count": { + "name": "token_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "embedding_model": { + "name": "embedding_model", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'text-embedding-3-small'" + }, + "embedding_dimension": { + "name": "embedding_dimension", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 1536 + }, + "chunking_config": { + "name": "chunking_config", + "type": "json", + "primaryKey": false, + "notNull": true, + "default": "'{\"maxSize\": 1024, \"minSize\": 1, \"overlap\": 200}'" + }, + "deleted_at": { + "name": "deleted_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "kb_user_id_idx": { + "name": "kb_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "kb_workspace_id_idx": { + "name": "kb_workspace_id_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "kb_user_workspace_idx": { + "name": "kb_user_workspace_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "kb_deleted_at_idx": { + "name": "kb_deleted_at_idx", + "columns": [ + { + "expression": "deleted_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "knowledge_base_user_id_user_id_fk": { + "name": "knowledge_base_user_id_user_id_fk", + "tableFrom": "knowledge_base", + "tableTo": "user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "knowledge_base_workspace_id_workspace_id_fk": { + "name": "knowledge_base_workspace_id_workspace_id_fk", + "tableFrom": "knowledge_base", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.knowledge_base_tag_definitions": { + "name": "knowledge_base_tag_definitions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "knowledge_base_id": { + "name": "knowledge_base_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "tag_slot": { + "name": "tag_slot", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "display_name": { + "name": "display_name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "field_type": { + "name": "field_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'text'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "kb_tag_definitions_kb_slot_idx": { + "name": "kb_tag_definitions_kb_slot_idx", + "columns": [ + { + "expression": "knowledge_base_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "tag_slot", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "kb_tag_definitions_kb_display_name_idx": { + "name": "kb_tag_definitions_kb_display_name_idx", + "columns": [ + { + "expression": "knowledge_base_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "display_name", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "kb_tag_definitions_kb_id_idx": { + "name": "kb_tag_definitions_kb_id_idx", + "columns": [ + { + "expression": "knowledge_base_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "knowledge_base_tag_definitions_knowledge_base_id_knowledge_base_id_fk": { + "name": "knowledge_base_tag_definitions_knowledge_base_id_knowledge_base_id_fk", + "tableFrom": "knowledge_base_tag_definitions", + "tableTo": "knowledge_base", + "columnsFrom": ["knowledge_base_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.marketplace": { + "name": "marketplace", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "state": { + "name": "state", + "type": "json", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "author_id": { + "name": "author_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "author_name": { + "name": "author_name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "views": { + "name": "views", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "category": { + "name": "category", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "marketplace_workflow_id_workflow_id_fk": { + "name": "marketplace_workflow_id_workflow_id_fk", + "tableFrom": "marketplace", + "tableTo": "workflow", + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "marketplace_author_id_user_id_fk": { + "name": "marketplace_author_id_user_id_fk", + "tableFrom": "marketplace", + "tableTo": "user", + "columnsFrom": ["author_id"], + "columnsTo": ["id"], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.mcp_servers": { + "name": "mcp_servers", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_by": { + "name": "created_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "transport": { + "name": "transport", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "url": { + "name": "url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "headers": { + "name": "headers", + "type": "json", + "primaryKey": false, + "notNull": false, + "default": "'{}'" + }, + "timeout": { + "name": "timeout", + "type": "integer", + "primaryKey": false, + "notNull": false, + "default": 30000 + }, + "retries": { + "name": "retries", + "type": "integer", + "primaryKey": false, + "notNull": false, + "default": 3 + }, + "enabled": { + "name": "enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "last_connected": { + "name": "last_connected", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "connection_status": { + "name": "connection_status", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "'disconnected'" + }, + "last_error": { + "name": "last_error", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tool_count": { + "name": "tool_count", + "type": "integer", + "primaryKey": false, + "notNull": false, + "default": 0 + }, + "last_tools_refresh": { + "name": "last_tools_refresh", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "total_requests": { + "name": "total_requests", + "type": "integer", + "primaryKey": false, + "notNull": false, + "default": 0 + }, + "last_used": { + "name": "last_used", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "deleted_at": { + "name": "deleted_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "mcp_servers_workspace_enabled_idx": { + "name": "mcp_servers_workspace_enabled_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "enabled", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "mcp_servers_workspace_deleted_idx": { + "name": "mcp_servers_workspace_deleted_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "deleted_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "mcp_servers_workspace_id_workspace_id_fk": { + "name": "mcp_servers_workspace_id_workspace_id_fk", + "tableFrom": "mcp_servers", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "mcp_servers_created_by_user_id_fk": { + "name": "mcp_servers_created_by_user_id_fk", + "tableFrom": "mcp_servers", + "tableTo": "user", + "columnsFrom": ["created_by"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.member": { + "name": "member", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "member_user_id_idx": { + "name": "member_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "member_organization_id_idx": { + "name": "member_organization_id_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "member_user_id_user_id_fk": { + "name": "member_user_id_user_id_fk", + "tableFrom": "member", + "tableTo": "user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "member_organization_id_organization_id_fk": { + "name": "member_organization_id_organization_id_fk", + "tableFrom": "member", + "tableTo": "organization", + "columnsFrom": ["organization_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.memory": { + "name": "memory", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "data": { + "name": "data", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "deleted_at": { + "name": "deleted_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "memory_key_idx": { + "name": "memory_key_idx", + "columns": [ + { + "expression": "key", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "memory_workflow_idx": { + "name": "memory_workflow_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "memory_workflow_key_idx": { + "name": "memory_workflow_key_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "key", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "memory_workflow_id_workflow_id_fk": { + "name": "memory_workflow_id_workflow_id_fk", + "tableFrom": "memory", + "tableTo": "workflow", + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.organization": { + "name": "organization", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "slug": { + "name": "slug", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "logo": { + "name": "logo", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "metadata": { + "name": "metadata", + "type": "json", + "primaryKey": false, + "notNull": false + }, + "org_usage_limit": { + "name": "org_usage_limit", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "storage_used_bytes": { + "name": "storage_used_bytes", + "type": "bigint", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "departed_member_usage": { + "name": "departed_member_usage", + "type": "numeric", + "primaryKey": false, + "notNull": true, + "default": "'0'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.paused_executions": { + "name": "paused_executions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "execution_id": { + "name": "execution_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "execution_snapshot": { + "name": "execution_snapshot", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "pause_points": { + "name": "pause_points", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "total_pause_count": { + "name": "total_pause_count", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "resumed_count": { + "name": "resumed_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'paused'" + }, + "metadata": { + "name": "metadata", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'::jsonb" + }, + "paused_at": { + "name": "paused_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "paused_executions_workflow_id_idx": { + "name": "paused_executions_workflow_id_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "paused_executions_status_idx": { + "name": "paused_executions_status_idx", + "columns": [ + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "paused_executions_execution_id_unique": { + "name": "paused_executions_execution_id_unique", + "columns": [ + { + "expression": "execution_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "paused_executions_workflow_id_workflow_id_fk": { + "name": "paused_executions_workflow_id_workflow_id_fk", + "tableFrom": "paused_executions", + "tableTo": "workflow", + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.permissions": { + "name": "permissions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "entity_type": { + "name": "entity_type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "entity_id": { + "name": "entity_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "permission_type": { + "name": "permission_type", + "type": "permission_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "permissions_user_id_idx": { + "name": "permissions_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "permissions_entity_idx": { + "name": "permissions_entity_idx", + "columns": [ + { + "expression": "entity_type", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "entity_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "permissions_user_entity_type_idx": { + "name": "permissions_user_entity_type_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "entity_type", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "permissions_user_entity_permission_idx": { + "name": "permissions_user_entity_permission_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "entity_type", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "permission_type", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "permissions_user_entity_idx": { + "name": "permissions_user_entity_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "entity_type", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "entity_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "permissions_unique_constraint": { + "name": "permissions_unique_constraint", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "entity_type", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "entity_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "permissions_user_id_user_id_fk": { + "name": "permissions_user_id_user_id_fk", + "tableFrom": "permissions", + "tableTo": "user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.resume_queue": { + "name": "resume_queue", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "paused_execution_id": { + "name": "paused_execution_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "parent_execution_id": { + "name": "parent_execution_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "new_execution_id": { + "name": "new_execution_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "context_id": { + "name": "context_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "resume_input": { + "name": "resume_input", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "queued_at": { + "name": "queued_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "claimed_at": { + "name": "claimed_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "completed_at": { + "name": "completed_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "failure_reason": { + "name": "failure_reason", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "resume_queue_parent_status_idx": { + "name": "resume_queue_parent_status_idx", + "columns": [ + { + "expression": "parent_execution_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "queued_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "resume_queue_new_execution_idx": { + "name": "resume_queue_new_execution_idx", + "columns": [ + { + "expression": "new_execution_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "resume_queue_paused_execution_id_paused_executions_id_fk": { + "name": "resume_queue_paused_execution_id_paused_executions_id_fk", + "tableFrom": "resume_queue", + "tableTo": "paused_executions", + "columnsFrom": ["paused_execution_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.session": { + "name": "session", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "token": { + "name": "token", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "ip_address": { + "name": "ip_address", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_agent": { + "name": "user_agent", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "active_organization_id": { + "name": "active_organization_id", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "session_user_id_idx": { + "name": "session_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "session_token_idx": { + "name": "session_token_idx", + "columns": [ + { + "expression": "token", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "session_user_id_user_id_fk": { + "name": "session_user_id_user_id_fk", + "tableFrom": "session", + "tableTo": "user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "session_active_organization_id_organization_id_fk": { + "name": "session_active_organization_id_organization_id_fk", + "tableFrom": "session", + "tableTo": "organization", + "columnsFrom": ["active_organization_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "session_token_unique": { + "name": "session_token_unique", + "nullsNotDistinct": false, + "columns": ["token"] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.settings": { + "name": "settings", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "theme": { + "name": "theme", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'system'" + }, + "auto_connect": { + "name": "auto_connect", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "auto_pan": { + "name": "auto_pan", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "console_expanded_by_default": { + "name": "console_expanded_by_default", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "telemetry_enabled": { + "name": "telemetry_enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "email_preferences": { + "name": "email_preferences", + "type": "json", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "billing_usage_notifications_enabled": { + "name": "billing_usage_notifications_enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "show_floating_controls": { + "name": "show_floating_controls", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "show_training_controls": { + "name": "show_training_controls", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "super_user_mode_enabled": { + "name": "super_user_mode_enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "error_notifications_enabled": { + "name": "error_notifications_enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "copilot_enabled_models": { + "name": "copilot_enabled_models", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "settings_user_id_user_id_fk": { + "name": "settings_user_id_user_id_fk", + "tableFrom": "settings", + "tableTo": "user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "settings_user_id_unique": { + "name": "settings_user_id_unique", + "nullsNotDistinct": false, + "columns": ["user_id"] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.sso_provider": { + "name": "sso_provider", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "issuer": { + "name": "issuer", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "domain": { + "name": "domain", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "oidc_config": { + "name": "oidc_config", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "saml_config": { + "name": "saml_config", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "provider_id": { + "name": "provider_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "sso_provider_provider_id_idx": { + "name": "sso_provider_provider_id_idx", + "columns": [ + { + "expression": "provider_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "sso_provider_domain_idx": { + "name": "sso_provider_domain_idx", + "columns": [ + { + "expression": "domain", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "sso_provider_user_id_idx": { + "name": "sso_provider_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "sso_provider_organization_id_idx": { + "name": "sso_provider_organization_id_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "sso_provider_user_id_user_id_fk": { + "name": "sso_provider_user_id_user_id_fk", + "tableFrom": "sso_provider", + "tableTo": "user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "sso_provider_organization_id_organization_id_fk": { + "name": "sso_provider_organization_id_organization_id_fk", + "tableFrom": "sso_provider", + "tableTo": "organization", + "columnsFrom": ["organization_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.subscription": { + "name": "subscription", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "plan": { + "name": "plan", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "reference_id": { + "name": "reference_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "stripe_customer_id": { + "name": "stripe_customer_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "stripe_subscription_id": { + "name": "stripe_subscription_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "period_start": { + "name": "period_start", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "period_end": { + "name": "period_end", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "cancel_at_period_end": { + "name": "cancel_at_period_end", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "seats": { + "name": "seats", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "trial_start": { + "name": "trial_start", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "trial_end": { + "name": "trial_end", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "metadata": { + "name": "metadata", + "type": "json", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "subscription_reference_status_idx": { + "name": "subscription_reference_status_idx", + "columns": [ + { + "expression": "reference_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "check_enterprise_metadata": { + "name": "check_enterprise_metadata", + "value": "plan != 'enterprise' OR metadata IS NOT NULL" + } + }, + "isRLSEnabled": false + }, + "public.template_creators": { + "name": "template_creators", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "reference_type": { + "name": "reference_type", + "type": "template_creator_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "reference_id": { + "name": "reference_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "profile_image_url": { + "name": "profile_image_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "details": { + "name": "details", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "verified": { + "name": "verified", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "created_by": { + "name": "created_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "template_creators_reference_idx": { + "name": "template_creators_reference_idx", + "columns": [ + { + "expression": "reference_type", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "reference_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "template_creators_reference_id_idx": { + "name": "template_creators_reference_id_idx", + "columns": [ + { + "expression": "reference_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "template_creators_created_by_idx": { + "name": "template_creators_created_by_idx", + "columns": [ + { + "expression": "created_by", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "template_creators_created_by_user_id_fk": { + "name": "template_creators_created_by_user_id_fk", + "tableFrom": "template_creators", + "tableTo": "user", + "columnsFrom": ["created_by"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.template_stars": { + "name": "template_stars", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "template_id": { + "name": "template_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "starred_at": { + "name": "starred_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "template_stars_user_id_idx": { + "name": "template_stars_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "template_stars_template_id_idx": { + "name": "template_stars_template_id_idx", + "columns": [ + { + "expression": "template_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "template_stars_user_template_idx": { + "name": "template_stars_user_template_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "template_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "template_stars_template_user_idx": { + "name": "template_stars_template_user_idx", + "columns": [ + { + "expression": "template_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "template_stars_starred_at_idx": { + "name": "template_stars_starred_at_idx", + "columns": [ + { + "expression": "starred_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "template_stars_template_starred_at_idx": { + "name": "template_stars_template_starred_at_idx", + "columns": [ + { + "expression": "template_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "starred_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "template_stars_user_template_unique": { + "name": "template_stars_user_template_unique", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "template_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "template_stars_user_id_user_id_fk": { + "name": "template_stars_user_id_user_id_fk", + "tableFrom": "template_stars", + "tableTo": "user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "template_stars_template_id_templates_id_fk": { + "name": "template_stars_template_id_templates_id_fk", + "tableFrom": "template_stars", + "tableTo": "templates", + "columnsFrom": ["template_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.templates": { + "name": "templates", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "details": { + "name": "details", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "creator_id": { + "name": "creator_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "views": { + "name": "views", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "stars": { + "name": "stars", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "status": { + "name": "status", + "type": "template_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "tags": { + "name": "tags", + "type": "text[]", + "primaryKey": false, + "notNull": true, + "default": "'{}'::text[]" + }, + "required_credentials": { + "name": "required_credentials", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'[]'" + }, + "state": { + "name": "state", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "templates_status_idx": { + "name": "templates_status_idx", + "columns": [ + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "templates_creator_id_idx": { + "name": "templates_creator_id_idx", + "columns": [ + { + "expression": "creator_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "templates_views_idx": { + "name": "templates_views_idx", + "columns": [ + { + "expression": "views", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "templates_stars_idx": { + "name": "templates_stars_idx", + "columns": [ + { + "expression": "stars", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "templates_status_views_idx": { + "name": "templates_status_views_idx", + "columns": [ + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "views", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "templates_status_stars_idx": { + "name": "templates_status_stars_idx", + "columns": [ + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "stars", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "templates_created_at_idx": { + "name": "templates_created_at_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "templates_updated_at_idx": { + "name": "templates_updated_at_idx", + "columns": [ + { + "expression": "updated_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "templates_workflow_id_workflow_id_fk": { + "name": "templates_workflow_id_workflow_id_fk", + "tableFrom": "templates", + "tableTo": "workflow", + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + }, + "templates_creator_id_template_creators_id_fk": { + "name": "templates_creator_id_template_creators_id_fk", + "tableFrom": "templates", + "tableTo": "template_creators", + "columnsFrom": ["creator_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.user": { + "name": "user", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "email_verified": { + "name": "email_verified", + "type": "boolean", + "primaryKey": false, + "notNull": true + }, + "image": { + "name": "image", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "stripe_customer_id": { + "name": "stripe_customer_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "is_super_user": { + "name": "is_super_user", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "user_email_unique": { + "name": "user_email_unique", + "nullsNotDistinct": false, + "columns": ["email"] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.user_rate_limits": { + "name": "user_rate_limits", + "schema": "", + "columns": { + "reference_id": { + "name": "reference_id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "sync_api_requests": { + "name": "sync_api_requests", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "async_api_requests": { + "name": "async_api_requests", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "api_endpoint_requests": { + "name": "api_endpoint_requests", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "window_start": { + "name": "window_start", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "last_request_at": { + "name": "last_request_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "is_rate_limited": { + "name": "is_rate_limited", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "rate_limit_reset_at": { + "name": "rate_limit_reset_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.user_stats": { + "name": "user_stats", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "total_manual_executions": { + "name": "total_manual_executions", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "total_api_calls": { + "name": "total_api_calls", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "total_webhook_triggers": { + "name": "total_webhook_triggers", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "total_scheduled_executions": { + "name": "total_scheduled_executions", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "total_chat_executions": { + "name": "total_chat_executions", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "total_tokens_used": { + "name": "total_tokens_used", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "total_cost": { + "name": "total_cost", + "type": "numeric", + "primaryKey": false, + "notNull": true, + "default": "'0'" + }, + "current_usage_limit": { + "name": "current_usage_limit", + "type": "numeric", + "primaryKey": false, + "notNull": false, + "default": "'10'" + }, + "usage_limit_updated_at": { + "name": "usage_limit_updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + }, + "current_period_cost": { + "name": "current_period_cost", + "type": "numeric", + "primaryKey": false, + "notNull": true, + "default": "'0'" + }, + "last_period_cost": { + "name": "last_period_cost", + "type": "numeric", + "primaryKey": false, + "notNull": false, + "default": "'0'" + }, + "billed_overage_this_period": { + "name": "billed_overage_this_period", + "type": "numeric", + "primaryKey": false, + "notNull": true, + "default": "'0'" + }, + "pro_period_cost_snapshot": { + "name": "pro_period_cost_snapshot", + "type": "numeric", + "primaryKey": false, + "notNull": false, + "default": "'0'" + }, + "total_copilot_cost": { + "name": "total_copilot_cost", + "type": "numeric", + "primaryKey": false, + "notNull": true, + "default": "'0'" + }, + "current_period_copilot_cost": { + "name": "current_period_copilot_cost", + "type": "numeric", + "primaryKey": false, + "notNull": true, + "default": "'0'" + }, + "last_period_copilot_cost": { + "name": "last_period_copilot_cost", + "type": "numeric", + "primaryKey": false, + "notNull": false, + "default": "'0'" + }, + "total_copilot_tokens": { + "name": "total_copilot_tokens", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "total_copilot_calls": { + "name": "total_copilot_calls", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "storage_used_bytes": { + "name": "storage_used_bytes", + "type": "bigint", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "last_active": { + "name": "last_active", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "billing_blocked": { + "name": "billing_blocked", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + } + }, + "indexes": {}, + "foreignKeys": { + "user_stats_user_id_user_id_fk": { + "name": "user_stats_user_id_user_id_fk", + "tableFrom": "user_stats", + "tableTo": "user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "user_stats_user_id_unique": { + "name": "user_stats_user_id_unique", + "nullsNotDistinct": false, + "columns": ["user_id"] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.verification": { + "name": "verification", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "identifier": { + "name": "identifier", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "verification_identifier_idx": { + "name": "verification_identifier_idx", + "columns": [ + { + "expression": "identifier", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.waitlist": { + "name": "waitlist", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "waitlist_email_unique": { + "name": "waitlist_email_unique", + "nullsNotDistinct": false, + "columns": ["email"] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.webhook": { + "name": "webhook", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "block_id": { + "name": "block_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "path": { + "name": "path", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "provider": { + "name": "provider", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "provider_config": { + "name": "provider_config", + "type": "json", + "primaryKey": false, + "notNull": false + }, + "is_active": { + "name": "is_active", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "failed_count": { + "name": "failed_count", + "type": "integer", + "primaryKey": false, + "notNull": false, + "default": 0 + }, + "last_failed_at": { + "name": "last_failed_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "path_idx": { + "name": "path_idx", + "columns": [ + { + "expression": "path", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_webhook_on_workflow_id_block_id": { + "name": "idx_webhook_on_workflow_id_block_id", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "block_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "webhook_workflow_id_workflow_id_fk": { + "name": "webhook_workflow_id_workflow_id_fk", + "tableFrom": "webhook", + "tableTo": "workflow", + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "webhook_block_id_workflow_blocks_id_fk": { + "name": "webhook_block_id_workflow_blocks_id_fk", + "tableFrom": "webhook", + "tableTo": "workflow_blocks", + "columnsFrom": ["block_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workflow": { + "name": "workflow", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "folder_id": { + "name": "folder_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "color": { + "name": "color", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'#3972F6'" + }, + "last_synced": { + "name": "last_synced", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "is_deployed": { + "name": "is_deployed", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "deployed_at": { + "name": "deployed_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "run_count": { + "name": "run_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "last_run_at": { + "name": "last_run_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "variables": { + "name": "variables", + "type": "json", + "primaryKey": false, + "notNull": false, + "default": "'{}'" + } + }, + "indexes": { + "workflow_user_id_idx": { + "name": "workflow_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_workspace_id_idx": { + "name": "workflow_workspace_id_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_user_workspace_idx": { + "name": "workflow_user_workspace_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workflow_user_id_user_id_fk": { + "name": "workflow_user_id_user_id_fk", + "tableFrom": "workflow", + "tableTo": "user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workflow_workspace_id_workspace_id_fk": { + "name": "workflow_workspace_id_workspace_id_fk", + "tableFrom": "workflow", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workflow_folder_id_workflow_folder_id_fk": { + "name": "workflow_folder_id_workflow_folder_id_fk", + "tableFrom": "workflow", + "tableTo": "workflow_folder", + "columnsFrom": ["folder_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workflow_blocks": { + "name": "workflow_blocks", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "position_x": { + "name": "position_x", + "type": "numeric", + "primaryKey": false, + "notNull": true + }, + "position_y": { + "name": "position_y", + "type": "numeric", + "primaryKey": false, + "notNull": true + }, + "enabled": { + "name": "enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "horizontal_handles": { + "name": "horizontal_handles", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "is_wide": { + "name": "is_wide", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "advanced_mode": { + "name": "advanced_mode", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "trigger_mode": { + "name": "trigger_mode", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "height": { + "name": "height", + "type": "numeric", + "primaryKey": false, + "notNull": true, + "default": "'0'" + }, + "sub_blocks": { + "name": "sub_blocks", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "outputs": { + "name": "outputs", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "data": { + "name": "data", + "type": "jsonb", + "primaryKey": false, + "notNull": false, + "default": "'{}'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workflow_blocks_workflow_id_idx": { + "name": "workflow_blocks_workflow_id_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workflow_blocks_workflow_id_workflow_id_fk": { + "name": "workflow_blocks_workflow_id_workflow_id_fk", + "tableFrom": "workflow_blocks", + "tableTo": "workflow", + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workflow_checkpoints": { + "name": "workflow_checkpoints", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "chat_id": { + "name": "chat_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "message_id": { + "name": "message_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "workflow_state": { + "name": "workflow_state", + "type": "json", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workflow_checkpoints_user_id_idx": { + "name": "workflow_checkpoints_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_checkpoints_workflow_id_idx": { + "name": "workflow_checkpoints_workflow_id_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_checkpoints_chat_id_idx": { + "name": "workflow_checkpoints_chat_id_idx", + "columns": [ + { + "expression": "chat_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_checkpoints_message_id_idx": { + "name": "workflow_checkpoints_message_id_idx", + "columns": [ + { + "expression": "message_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_checkpoints_user_workflow_idx": { + "name": "workflow_checkpoints_user_workflow_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_checkpoints_workflow_chat_idx": { + "name": "workflow_checkpoints_workflow_chat_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "chat_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_checkpoints_created_at_idx": { + "name": "workflow_checkpoints_created_at_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_checkpoints_chat_created_at_idx": { + "name": "workflow_checkpoints_chat_created_at_idx", + "columns": [ + { + "expression": "chat_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workflow_checkpoints_user_id_user_id_fk": { + "name": "workflow_checkpoints_user_id_user_id_fk", + "tableFrom": "workflow_checkpoints", + "tableTo": "user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workflow_checkpoints_workflow_id_workflow_id_fk": { + "name": "workflow_checkpoints_workflow_id_workflow_id_fk", + "tableFrom": "workflow_checkpoints", + "tableTo": "workflow", + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workflow_checkpoints_chat_id_copilot_chats_id_fk": { + "name": "workflow_checkpoints_chat_id_copilot_chats_id_fk", + "tableFrom": "workflow_checkpoints", + "tableTo": "copilot_chats", + "columnsFrom": ["chat_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workflow_deployment_version": { + "name": "workflow_deployment_version", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "version": { + "name": "version", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "state": { + "name": "state", + "type": "json", + "primaryKey": false, + "notNull": true + }, + "is_active": { + "name": "is_active", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "created_by": { + "name": "created_by", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "workflow_deployment_version_workflow_version_unique": { + "name": "workflow_deployment_version_workflow_version_unique", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "version", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_deployment_version_workflow_active_idx": { + "name": "workflow_deployment_version_workflow_active_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "is_active", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_deployment_version_created_at_idx": { + "name": "workflow_deployment_version_created_at_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workflow_deployment_version_workflow_id_workflow_id_fk": { + "name": "workflow_deployment_version_workflow_id_workflow_id_fk", + "tableFrom": "workflow_deployment_version", + "tableTo": "workflow", + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workflow_edges": { + "name": "workflow_edges", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "source_block_id": { + "name": "source_block_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "target_block_id": { + "name": "target_block_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "source_handle": { + "name": "source_handle", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "target_handle": { + "name": "target_handle", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workflow_edges_workflow_id_idx": { + "name": "workflow_edges_workflow_id_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_edges_workflow_source_idx": { + "name": "workflow_edges_workflow_source_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "source_block_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_edges_workflow_target_idx": { + "name": "workflow_edges_workflow_target_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "target_block_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workflow_edges_workflow_id_workflow_id_fk": { + "name": "workflow_edges_workflow_id_workflow_id_fk", + "tableFrom": "workflow_edges", + "tableTo": "workflow", + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workflow_edges_source_block_id_workflow_blocks_id_fk": { + "name": "workflow_edges_source_block_id_workflow_blocks_id_fk", + "tableFrom": "workflow_edges", + "tableTo": "workflow_blocks", + "columnsFrom": ["source_block_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workflow_edges_target_block_id_workflow_blocks_id_fk": { + "name": "workflow_edges_target_block_id_workflow_blocks_id_fk", + "tableFrom": "workflow_edges", + "tableTo": "workflow_blocks", + "columnsFrom": ["target_block_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workflow_execution_logs": { + "name": "workflow_execution_logs", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "execution_id": { + "name": "execution_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "state_snapshot_id": { + "name": "state_snapshot_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "level": { + "name": "level", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "trigger": { + "name": "trigger", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "started_at": { + "name": "started_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "ended_at": { + "name": "ended_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "total_duration_ms": { + "name": "total_duration_ms", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "execution_data": { + "name": "execution_data", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "cost": { + "name": "cost", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "files": { + "name": "files", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workflow_execution_logs_workflow_id_idx": { + "name": "workflow_execution_logs_workflow_id_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_execution_logs_state_snapshot_id_idx": { + "name": "workflow_execution_logs_state_snapshot_id_idx", + "columns": [ + { + "expression": "state_snapshot_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_execution_logs_trigger_idx": { + "name": "workflow_execution_logs_trigger_idx", + "columns": [ + { + "expression": "trigger", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_execution_logs_level_idx": { + "name": "workflow_execution_logs_level_idx", + "columns": [ + { + "expression": "level", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_execution_logs_started_at_idx": { + "name": "workflow_execution_logs_started_at_idx", + "columns": [ + { + "expression": "started_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_execution_logs_execution_id_unique": { + "name": "workflow_execution_logs_execution_id_unique", + "columns": [ + { + "expression": "execution_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_execution_logs_workflow_started_at_idx": { + "name": "workflow_execution_logs_workflow_started_at_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "started_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workflow_execution_logs_workflow_id_workflow_id_fk": { + "name": "workflow_execution_logs_workflow_id_workflow_id_fk", + "tableFrom": "workflow_execution_logs", + "tableTo": "workflow", + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workflow_execution_logs_state_snapshot_id_workflow_execution_snapshots_id_fk": { + "name": "workflow_execution_logs_state_snapshot_id_workflow_execution_snapshots_id_fk", + "tableFrom": "workflow_execution_logs", + "tableTo": "workflow_execution_snapshots", + "columnsFrom": ["state_snapshot_id"], + "columnsTo": ["id"], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workflow_execution_snapshots": { + "name": "workflow_execution_snapshots", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "state_hash": { + "name": "state_hash", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "state_data": { + "name": "state_data", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workflow_snapshots_workflow_id_idx": { + "name": "workflow_snapshots_workflow_id_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_snapshots_hash_idx": { + "name": "workflow_snapshots_hash_idx", + "columns": [ + { + "expression": "state_hash", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_snapshots_workflow_hash_idx": { + "name": "workflow_snapshots_workflow_hash_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "state_hash", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_snapshots_created_at_idx": { + "name": "workflow_snapshots_created_at_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workflow_execution_snapshots_workflow_id_workflow_id_fk": { + "name": "workflow_execution_snapshots_workflow_id_workflow_id_fk", + "tableFrom": "workflow_execution_snapshots", + "tableTo": "workflow", + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workflow_folder": { + "name": "workflow_folder", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "parent_id": { + "name": "parent_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "color": { + "name": "color", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "'#6B7280'" + }, + "is_expanded": { + "name": "is_expanded", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "sort_order": { + "name": "sort_order", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workflow_folder_user_idx": { + "name": "workflow_folder_user_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_folder_workspace_parent_idx": { + "name": "workflow_folder_workspace_parent_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_folder_parent_sort_idx": { + "name": "workflow_folder_parent_sort_idx", + "columns": [ + { + "expression": "parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "sort_order", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workflow_folder_user_id_user_id_fk": { + "name": "workflow_folder_user_id_user_id_fk", + "tableFrom": "workflow_folder", + "tableTo": "user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workflow_folder_workspace_id_workspace_id_fk": { + "name": "workflow_folder_workspace_id_workspace_id_fk", + "tableFrom": "workflow_folder", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workflow_log_webhook": { + "name": "workflow_log_webhook", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "url": { + "name": "url", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "secret": { + "name": "secret", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "include_final_output": { + "name": "include_final_output", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "include_trace_spans": { + "name": "include_trace_spans", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "include_rate_limits": { + "name": "include_rate_limits", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "include_usage_data": { + "name": "include_usage_data", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "level_filter": { + "name": "level_filter", + "type": "text[]", + "primaryKey": false, + "notNull": true, + "default": "ARRAY['info', 'error']::text[]" + }, + "trigger_filter": { + "name": "trigger_filter", + "type": "text[]", + "primaryKey": false, + "notNull": true, + "default": "ARRAY['api', 'webhook', 'schedule', 'manual', 'chat']::text[]" + }, + "active": { + "name": "active", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workflow_log_webhook_workflow_id_idx": { + "name": "workflow_log_webhook_workflow_id_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_log_webhook_active_idx": { + "name": "workflow_log_webhook_active_idx", + "columns": [ + { + "expression": "active", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workflow_log_webhook_workflow_id_workflow_id_fk": { + "name": "workflow_log_webhook_workflow_id_workflow_id_fk", + "tableFrom": "workflow_log_webhook", + "tableTo": "workflow", + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workflow_log_webhook_delivery": { + "name": "workflow_log_webhook_delivery", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "subscription_id": { + "name": "subscription_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "execution_id": { + "name": "execution_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "webhook_delivery_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "attempts": { + "name": "attempts", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "last_attempt_at": { + "name": "last_attempt_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "next_attempt_at": { + "name": "next_attempt_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "response_status": { + "name": "response_status", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "response_body": { + "name": "response_body", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "error_message": { + "name": "error_message", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workflow_log_webhook_delivery_subscription_id_idx": { + "name": "workflow_log_webhook_delivery_subscription_id_idx", + "columns": [ + { + "expression": "subscription_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_log_webhook_delivery_execution_id_idx": { + "name": "workflow_log_webhook_delivery_execution_id_idx", + "columns": [ + { + "expression": "execution_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_log_webhook_delivery_status_idx": { + "name": "workflow_log_webhook_delivery_status_idx", + "columns": [ + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_log_webhook_delivery_next_attempt_idx": { + "name": "workflow_log_webhook_delivery_next_attempt_idx", + "columns": [ + { + "expression": "next_attempt_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workflow_log_webhook_delivery_subscription_id_workflow_log_webhook_id_fk": { + "name": "workflow_log_webhook_delivery_subscription_id_workflow_log_webhook_id_fk", + "tableFrom": "workflow_log_webhook_delivery", + "tableTo": "workflow_log_webhook", + "columnsFrom": ["subscription_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workflow_log_webhook_delivery_workflow_id_workflow_id_fk": { + "name": "workflow_log_webhook_delivery_workflow_id_workflow_id_fk", + "tableFrom": "workflow_log_webhook_delivery", + "tableTo": "workflow", + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workflow_schedule": { + "name": "workflow_schedule", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "block_id": { + "name": "block_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "cron_expression": { + "name": "cron_expression", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "next_run_at": { + "name": "next_run_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "last_ran_at": { + "name": "last_ran_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "last_queued_at": { + "name": "last_queued_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "trigger_type": { + "name": "trigger_type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "timezone": { + "name": "timezone", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'UTC'" + }, + "failed_count": { + "name": "failed_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'active'" + }, + "last_failed_at": { + "name": "last_failed_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workflow_schedule_workflow_block_unique": { + "name": "workflow_schedule_workflow_block_unique", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "block_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workflow_schedule_workflow_id_workflow_id_fk": { + "name": "workflow_schedule_workflow_id_workflow_id_fk", + "tableFrom": "workflow_schedule", + "tableTo": "workflow", + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workflow_schedule_block_id_workflow_blocks_id_fk": { + "name": "workflow_schedule_block_id_workflow_blocks_id_fk", + "tableFrom": "workflow_schedule", + "tableTo": "workflow_blocks", + "columnsFrom": ["block_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workflow_subflows": { + "name": "workflow_subflows", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workflow_id": { + "name": "workflow_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "config": { + "name": "config", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workflow_subflows_workflow_id_idx": { + "name": "workflow_subflows_workflow_id_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workflow_subflows_workflow_type_idx": { + "name": "workflow_subflows_workflow_type_idx", + "columns": [ + { + "expression": "workflow_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "type", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workflow_subflows_workflow_id_workflow_id_fk": { + "name": "workflow_subflows_workflow_id_workflow_id_fk", + "tableFrom": "workflow_subflows", + "tableTo": "workflow", + "columnsFrom": ["workflow_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workspace": { + "name": "workspace", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "owner_id": { + "name": "owner_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "billed_account_user_id": { + "name": "billed_account_user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "allow_personal_api_keys": { + "name": "allow_personal_api_keys", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "workspace_owner_id_user_id_fk": { + "name": "workspace_owner_id_user_id_fk", + "tableFrom": "workspace", + "tableTo": "user", + "columnsFrom": ["owner_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workspace_billed_account_user_id_user_id_fk": { + "name": "workspace_billed_account_user_id_user_id_fk", + "tableFrom": "workspace", + "tableTo": "user", + "columnsFrom": ["billed_account_user_id"], + "columnsTo": ["id"], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workspace_environment": { + "name": "workspace_environment", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "variables": { + "name": "variables", + "type": "json", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workspace_environment_workspace_unique": { + "name": "workspace_environment_workspace_unique", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workspace_environment_workspace_id_workspace_id_fk": { + "name": "workspace_environment_workspace_id_workspace_id_fk", + "tableFrom": "workspace_environment", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workspace_file": { + "name": "workspace_file", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "size": { + "name": "size", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "uploaded_by": { + "name": "uploaded_by", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "uploaded_at": { + "name": "uploaded_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workspace_file_workspace_id_idx": { + "name": "workspace_file_workspace_id_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workspace_file_key_idx": { + "name": "workspace_file_key_idx", + "columns": [ + { + "expression": "key", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workspace_file_workspace_id_workspace_id_fk": { + "name": "workspace_file_workspace_id_workspace_id_fk", + "tableFrom": "workspace_file", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workspace_file_uploaded_by_user_id_fk": { + "name": "workspace_file_uploaded_by_user_id_fk", + "tableFrom": "workspace_file", + "tableTo": "user", + "columnsFrom": ["uploaded_by"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "workspace_file_key_unique": { + "name": "workspace_file_key_unique", + "nullsNotDistinct": false, + "columns": ["key"] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workspace_files": { + "name": "workspace_files", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "context": { + "name": "context", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "original_name": { + "name": "original_name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "content_type": { + "name": "content_type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "size": { + "name": "size", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "uploaded_at": { + "name": "uploaded_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workspace_files_key_idx": { + "name": "workspace_files_key_idx", + "columns": [ + { + "expression": "key", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workspace_files_user_id_idx": { + "name": "workspace_files_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workspace_files_workspace_id_idx": { + "name": "workspace_files_workspace_id_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workspace_files_context_idx": { + "name": "workspace_files_context_idx", + "columns": [ + { + "expression": "context", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workspace_files_user_id_user_id_fk": { + "name": "workspace_files_user_id_user_id_fk", + "tableFrom": "workspace_files", + "tableTo": "user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workspace_files_workspace_id_workspace_id_fk": { + "name": "workspace_files_workspace_id_workspace_id_fk", + "tableFrom": "workspace_files", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "workspace_files_key_unique": { + "name": "workspace_files_key_unique", + "nullsNotDistinct": false, + "columns": ["key"] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workspace_invitation": { + "name": "workspace_invitation", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "inviter_id": { + "name": "inviter_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'member'" + }, + "status": { + "name": "status", + "type": "workspace_invitation_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "token": { + "name": "token", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "permissions": { + "name": "permissions", + "type": "permission_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'admin'" + }, + "org_invitation_id": { + "name": "org_invitation_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "workspace_invitation_workspace_id_workspace_id_fk": { + "name": "workspace_invitation_workspace_id_workspace_id_fk", + "tableFrom": "workspace_invitation", + "tableTo": "workspace", + "columnsFrom": ["workspace_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workspace_invitation_inviter_id_user_id_fk": { + "name": "workspace_invitation_inviter_id_user_id_fk", + "tableFrom": "workspace_invitation", + "tableTo": "user", + "columnsFrom": ["inviter_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "workspace_invitation_token_unique": { + "name": "workspace_invitation_token_unique", + "nullsNotDistinct": false, + "columns": ["token"] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + } + }, + "enums": { + "public.permission_type": { + "name": "permission_type", + "schema": "public", + "values": ["admin", "write", "read"] + }, + "public.template_creator_type": { + "name": "template_creator_type", + "schema": "public", + "values": ["user", "organization"] + }, + "public.template_status": { + "name": "template_status", + "schema": "public", + "values": ["pending", "approved", "rejected"] + }, + "public.webhook_delivery_status": { + "name": "webhook_delivery_status", + "schema": "public", + "values": ["pending", "in_progress", "success", "failed"] + }, + "public.workspace_invitation_status": { + "name": "workspace_invitation_status", + "schema": "public", + "values": ["pending", "accepted", "rejected", "cancelled"] + } + }, + "schemas": {}, + "sequences": {}, + "roles": {}, + "policies": {}, + "views": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} diff --git a/packages/db/migrations/meta/_journal.json b/packages/db/migrations/meta/_journal.json index 43821012ee..be8e52f8ab 100644 --- a/packages/db/migrations/meta/_journal.json +++ b/packages/db/migrations/meta/_journal.json @@ -799,6 +799,13 @@ "when": 1764468360258, "tag": "0114_wise_sunfire", "breakpoints": true + }, + { + "idx": 115, + "version": "7", + "when": 1764477997303, + "tag": "0115_redundant_cerebro", + "breakpoints": true } ] } diff --git a/packages/db/schema.ts b/packages/db/schema.ts index 10bfc43857..5570e2af2b 100644 --- a/packages/db/schema.ts +++ b/packages/db/schema.ts @@ -1335,6 +1335,7 @@ export const templateCreators = pgTable( name: text('name').notNull(), profileImageUrl: text('profile_image_url'), details: jsonb('details'), + verified: boolean('verified').notNull().default(false), createdBy: text('created_by').references(() => user.id, { onDelete: 'set null' }), createdAt: timestamp('created_at').notNull().defaultNow(), updatedAt: timestamp('updated_at').notNull().defaultNow(), From d7a650a355d0c42ed6f3356cf815cffc6b5f7758 Mon Sep 17 00:00:00 2001 From: Waleed Date: Sat, 29 Nov 2025 23:42:43 -0800 Subject: [PATCH 05/16] feat(tools): added apify block/tools (#2136) * feat(tools): added apify * cleanup --- apps/docs/components/icons.tsx | 847 ++++------------------ apps/docs/components/ui/icon-mapping.ts | 2 + apps/docs/content/docs/en/tools/apify.mdx | 94 +++ apps/docs/content/docs/en/tools/meta.json | 1 + apps/sim/blocks/blocks/apify.ts | 142 ++++ apps/sim/blocks/registry.ts | 2 + apps/sim/components/icons.tsx | 847 ++++------------------ apps/sim/tools/apify/index.ts | 3 + apps/sim/tools/apify/run_actor_async.ts | 213 ++++++ apps/sim/tools/apify/run_actor_sync.ts | 107 +++ apps/sim/tools/apify/types.ts | 54 ++ apps/sim/tools/registry.ts | 3 + 12 files changed, 873 insertions(+), 1442 deletions(-) create mode 100644 apps/docs/content/docs/en/tools/apify.mdx create mode 100644 apps/sim/blocks/blocks/apify.ts create mode 100644 apps/sim/tools/apify/index.ts create mode 100644 apps/sim/tools/apify/run_actor_async.ts create mode 100644 apps/sim/tools/apify/run_actor_sync.ts create mode 100644 apps/sim/tools/apify/types.ts diff --git a/apps/docs/components/icons.tsx b/apps/docs/components/icons.tsx index c848e36eb6..61c0267375 100644 --- a/apps/docs/components/icons.tsx +++ b/apps/docs/components/icons.tsx @@ -1,47 +1,5 @@ import type { SVGProps } from 'react' -export function UsersIcon(props: SVGProps) { - return ( - - - - - - - ) -} - -export function SettingsIcon(props: SVGProps) { - return ( - - - - - ) -} - export function SearchIcon(props: SVGProps) { return ( ) { strokeLinejoin='round' > - - - ) -} - -export function Spinner() { - return ( -
- - - - -
- ) -} - -export function AgentIcon(props: SVGProps) { - return ( - - - - - - ) -} - -export function ApiIcon(props: SVGProps) { - return ( - - - - ) -} - -export function ConditionalIcon(props: SVGProps) { - return ( - - - - ) -} - -export function NoteIcon(props: SVGProps) { - return ( - - - - - - - ) -} - -export function AirplaneIcon(props: SVGProps) { - return ( - - - - ) -} - -export function WorkIcon(props: SVGProps) { - return ( - - - - - ) -} - -export function WorkflowIcon(props: SVGProps) { - return ( - - - - - - - - ) -} - -export function WarnIcon(props: SVGProps) { - return ( - - - - ) -} - -export function UploadIcon(props: SVGProps) { - return ( - - - - - ) -} - -export function TrashIcon(props: SVGProps) { - return ( - - - - ) -} - -export function StudentIcon(props: SVGProps) { - return ( - - - - - ) -} - -export function SignalIcon(props: SVGProps) { - return ( - - - - ) -} - -export function SectionIcon(props: SVGProps) { - return ( - - - - ) -} - -export function ReminderIcon(props: SVGProps) { - return ( - - - - - ) -} - -export function DatabaseIcon(props: SVGProps) { - return ( - - - - - ) -} - -export function CrateIcon(props: SVGProps) { - return ( - - - - ) -} - -export function CookieIcon(props: SVGProps) { - return ( - - - - ) -} - -export function ErrorIcon(props: SVGProps) { - return ( - - + ) } -export function ChromeIcon(props: SVGProps) { +export function AgentIcon(props: SVGProps) { return ( - - ) -} - -export function CalendarIcon(props: SVGProps) { - return ( - @@ -616,7 +55,7 @@ export function CalendarIcon(props: SVGProps) { ) } -export function MessagesIcon(props: SVGProps) { +export function ApiIcon(props: SVGProps) { return ( ) { xmlns='http://www.w3.org/2000/svg' > ) { ) } -export function NotificationsIcon(props: SVGProps) { +export function ConditionalIcon(props: SVGProps) { return ( ) } -export function MailIcon(props: SVGProps) { +export function NoteIcon(props: SVGProps) { return ( - + + + ) } -export function CodeIcon(props: SVGProps) { +export function WorkflowIcon(props: SVGProps) { return ( - - - ) -} - -export function ChartBarIcon(props: SVGProps) { - return ( - - - - ) -} - -export function AtomIcon(props: SVGProps) { - return ( - - - - - ) -} - -export function ElevatorIcon(props: SVGProps) { - return ( - - - ) -} - -export function DollarIcon(props: SVGProps) { - return ( - - @@ -788,18 +190,18 @@ export function DollarIcon(props: SVGProps) { ) } -export function CreditCardIcon(props: SVGProps) { +export function SignalIcon(props: SVGProps) { return ( ) { ) } -export function BoatIcon(props: SVGProps) { +export function CalendarIcon(props: SVGProps) { return ( ) { xmlns='http://www.w3.org/2000/svg' > ) { ) } -export function CancelIcon(props: SVGProps) { +export function MessagesIcon(props: SVGProps) { return ( ) { xmlns='http://www.w3.org/2000/svg' > - ) { ) } -export function BankIcon(props: SVGProps) { +export function NotificationsIcon(props: SVGProps) { return ( ) { ) } -export function AmbulanceIcon(props: SVGProps) { +export function MailIcon(props: SVGProps) { return ( ) { xmlns='http://www.w3.org/2000/svg' > - - ) -} - -export function ComponentIcon(props: SVGProps) { - return ( - - ) { ) } -export function BrightIcon(props: SVGProps) { +export function CodeIcon(props: SVGProps) { return ( @@ -942,21 +316,19 @@ export function BrightIcon(props: SVGProps) { ) } -export function CrewAIIcon(props: SVGProps) { +export function ChartBarIcon(props: SVGProps) { return ( ) @@ -4428,3 +3800,36 @@ export function SmtpIcon(props: SVGProps) { ) } + +export function ApifyIcon(props: SVGProps) { + return ( + + + + + + + + + + + + + ) +} diff --git a/apps/docs/components/ui/icon-mapping.ts b/apps/docs/components/ui/icon-mapping.ts index 3ace0e3907..5a31d3c47d 100644 --- a/apps/docs/components/ui/icon-mapping.ts +++ b/apps/docs/components/ui/icon-mapping.ts @@ -5,6 +5,7 @@ import type { ComponentType, SVGProps } from 'react' import { AirtableIcon, + ApifyIcon, ApolloIcon, ArxivIcon, AsanaIcon, @@ -187,5 +188,6 @@ export const blockTypeToIconMap: Record = { asana: AsanaIcon, arxiv: ArxivIcon, apollo: ApolloIcon, + apify: ApifyIcon, airtable: AirtableIcon, } diff --git a/apps/docs/content/docs/en/tools/apify.mdx b/apps/docs/content/docs/en/tools/apify.mdx new file mode 100644 index 0000000000..d26a1eb70a --- /dev/null +++ b/apps/docs/content/docs/en/tools/apify.mdx @@ -0,0 +1,94 @@ +--- +title: Apify +description: Run Apify actors and retrieve results +--- + +import { BlockInfoCard } from "@/components/ui/block-info-card" + + + +{/* MANUAL-CONTENT-START:intro */} +[Apify](https://apify.com/) is a powerful platform for building, deploying, and running web automation and web scraping actors at scale. Apify enables you to extract useful data from any website, automate workflows, and connect your data pipelines seamlessly. + +With Apify, you can: + +- **Run ready-made or custom actors**: Integrate public actors or develop your own, automating a wide range of web data extraction and browser tasks. +- **Retrieve datasets**: Access and manage structured datasets collected by actors in real time. +- **Scale web automation**: Leverage cloud infrastructure to run tasks reliably, asynchronously or synchronously, with robust error handling. + +In Sim, the Apify integration allows your agents to perform core Apify operations programmatically: + +- **Run Actor (Sync)**: Use `apify_run_actor_sync` to launch an Apify actor and wait for its completion, retrieving the results as soon as the run finishes. +- **Run Actor (Async)**: Use `apify_run_actor_async` to start an actor in the background and periodically poll for results, suitable for longer or complex jobs. + +These operations equip your agents to automate, scrape, and orchestrate data collection or browser automation tasks directly inside workflows — all with flexible configuration and result handling, without the need for manual runs or external tools. Integrate Apify as a dynamic automation and data-extraction engine that programmatically powers your agents' web-scale workflows. +{/* MANUAL-CONTENT-END */} + + +## Usage Instructions + +Integrate Apify into your workflow. Run any Apify actor with custom input and retrieve results. Supports both synchronous and asynchronous execution with automatic dataset fetching. + + + +## Tools + +### `apify_run_actor_sync` + +Run an APIFY actor synchronously and get results (max 5 minutes) + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | APIFY API token from console.apify.com/account#/integrations | +| `actorId` | string | Yes | Actor ID or username/actor-name \(e.g., "janedoe/my-actor" or actor ID\) | +| `input` | string | No | Actor input as JSON string. See actor documentation for required fields. | +| `timeout` | number | No | Timeout in seconds \(default: actor default\) | +| `build` | string | No | Actor build to run \(e.g., "latest", "beta", or build tag/number\) | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `success` | boolean | Whether the actor run succeeded | +| `runId` | string | APIFY run ID | +| `status` | string | Run status \(SUCCEEDED, FAILED, etc.\) | +| `datasetId` | string | Dataset ID containing results | +| `items` | array | Dataset items \(if completed\) | + +### `apify_run_actor_async` + +Run an APIFY actor asynchronously with polling for long-running tasks + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | APIFY API token from console.apify.com/account#/integrations | +| `actorId` | string | Yes | Actor ID or username/actor-name \(e.g., "janedoe/my-actor" or actor ID\) | +| `input` | string | No | Actor input as JSON string | +| `waitForFinish` | number | No | Initial wait time in seconds \(0-60\) before polling starts | +| `itemLimit` | number | No | Max dataset items to fetch \(1-250000, default 100\) | +| `timeout` | number | No | Timeout in seconds \(default: actor default\) | +| `build` | string | No | Actor build to run \(e.g., "latest", "beta", or build tag/number\) | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `success` | boolean | Whether the actor run succeeded | +| `runId` | string | APIFY run ID | +| `status` | string | Run status \(SUCCEEDED, FAILED, etc.\) | +| `datasetId` | string | Dataset ID containing results | +| `items` | array | Dataset items \(if completed\) | + + + +## Notes + +- Category: `tools` +- Type: `apify` diff --git a/apps/docs/content/docs/en/tools/meta.json b/apps/docs/content/docs/en/tools/meta.json index e8a4b7478a..a49297bad1 100644 --- a/apps/docs/content/docs/en/tools/meta.json +++ b/apps/docs/content/docs/en/tools/meta.json @@ -2,6 +2,7 @@ "pages": [ "index", "airtable", + "apify", "apollo", "arxiv", "asana", diff --git a/apps/sim/blocks/blocks/apify.ts b/apps/sim/blocks/blocks/apify.ts new file mode 100644 index 0000000000..e619be80e8 --- /dev/null +++ b/apps/sim/blocks/blocks/apify.ts @@ -0,0 +1,142 @@ +import { ApifyIcon } from '@/components/icons' +import type { BlockConfig } from '@/blocks/types' +import type { RunActorResult } from '@/tools/apify/types' + +export const ApifyBlock: BlockConfig = { + type: 'apify', + name: 'Apify', + description: 'Run Apify actors and retrieve results', + longDescription: + 'Integrate Apify into your workflow. Run any Apify actor with custom input and retrieve results. Supports both synchronous and asynchronous execution with automatic dataset fetching.', + docsLink: 'https://docs.sim.ai/tools/apify', + category: 'tools', + bgColor: '#E0E0E0', + icon: ApifyIcon, + + subBlocks: [ + { + id: 'operation', + title: 'Operation', + type: 'dropdown', + options: [ + { label: 'Run Actor', id: 'apify_run_actor_sync' }, + { label: 'Run Actor (Async)', id: 'apify_run_actor_async' }, + ], + value: () => 'apify_run_actor_sync', + }, + { + id: 'apiKey', + title: 'Apify API Token', + type: 'short-input', + password: true, + placeholder: 'Enter your Apify API token', + required: true, + }, + { + id: 'actorId', + title: 'Actor ID', + type: 'short-input', + placeholder: 'e.g., janedoe/my-actor or actor ID', + required: true, + }, + { + id: 'input', + title: 'Actor Input', + type: 'code', + language: 'json', + placeholder: '{\n "startUrl": "https://example.com",\n "maxPages": 10\n}', + required: false, + }, + { + id: 'timeout', + title: 'Timeout', + type: 'short-input', + placeholder: 'Actor timeout in seconds', + required: false, + }, + { + id: 'build', + title: 'Build', + type: 'short-input', + placeholder: 'Actor build (e.g., "latest", "beta", or build tag)', + required: false, + }, + { + id: 'waitForFinish', + title: 'Wait For Finish', + type: 'short-input', + placeholder: 'Initial wait time in seconds (0-60)', + required: false, + condition: { + field: 'operation', + value: 'apify_run_actor_async', + }, + }, + { + id: 'itemLimit', + title: 'Item Limit', + type: 'short-input', + placeholder: 'Max dataset items to fetch (1-250000)', + required: false, + condition: { + field: 'operation', + value: 'apify_run_actor_async', + }, + }, + ], + + tools: { + access: ['apify_run_actor_sync', 'apify_run_actor_async'], + config: { + tool: (params) => params.operation, + params: (params: Record) => { + const { operation, ...rest } = params + const result: Record = { + apiKey: rest.apiKey, + actorId: rest.actorId, + } + + if (rest.input) { + result.input = rest.input + } + + if (rest.timeout) { + result.timeout = Number(rest.timeout) + } + + if (rest.build) { + result.build = rest.build + } + + if (rest.waitForFinish) { + result.waitForFinish = Number(rest.waitForFinish) + } + + if (rest.itemLimit) { + result.itemLimit = Number(rest.itemLimit) + } + + return result + }, + }, + }, + + inputs: { + operation: { type: 'string', description: 'Operation to perform' }, + apiKey: { type: 'string', description: 'Apify API token' }, + actorId: { type: 'string', description: 'Actor ID or username/actor-name' }, + input: { type: 'string', description: 'Actor input as JSON string' }, + timeout: { type: 'number', description: 'Timeout in seconds' }, + build: { type: 'string', description: 'Actor build version' }, + waitForFinish: { type: 'number', description: 'Initial wait time in seconds' }, + itemLimit: { type: 'number', description: 'Max dataset items to fetch' }, + }, + + outputs: { + success: { type: 'boolean', description: 'Whether the actor run succeeded' }, + runId: { type: 'string', description: 'Apify run ID' }, + status: { type: 'string', description: 'Run status (SUCCEEDED, FAILED, etc.)' }, + datasetId: { type: 'string', description: 'Dataset ID containing results' }, + items: { type: 'json', description: 'Dataset items (if completed)' }, + }, +} diff --git a/apps/sim/blocks/registry.ts b/apps/sim/blocks/registry.ts index e7da0a7e57..994f3402cd 100644 --- a/apps/sim/blocks/registry.ts +++ b/apps/sim/blocks/registry.ts @@ -2,6 +2,7 @@ import { AgentBlock } from '@/blocks/blocks/agent' import { AirtableBlock } from '@/blocks/blocks/airtable' import { ApiBlock } from '@/blocks/blocks/api' import { ApiTriggerBlock } from '@/blocks/blocks/api_trigger' +import { ApifyBlock } from '@/blocks/blocks/apify' import { ApolloBlock } from '@/blocks/blocks/apollo' import { ArxivBlock } from '@/blocks/blocks/arxiv' import { AsanaBlock } from '@/blocks/blocks/asana' @@ -119,6 +120,7 @@ import type { BlockConfig } from '@/blocks/types' export const registry: Record = { agent: AgentBlock, airtable: AirtableBlock, + apify: ApifyBlock, apollo: ApolloBlock, api: ApiBlock, arxiv: ArxivBlock, diff --git a/apps/sim/components/icons.tsx b/apps/sim/components/icons.tsx index c848e36eb6..61c0267375 100644 --- a/apps/sim/components/icons.tsx +++ b/apps/sim/components/icons.tsx @@ -1,47 +1,5 @@ import type { SVGProps } from 'react' -export function UsersIcon(props: SVGProps) { - return ( - - - - - - - ) -} - -export function SettingsIcon(props: SVGProps) { - return ( - - - - - ) -} - export function SearchIcon(props: SVGProps) { return ( ) { strokeLinejoin='round' > - - - ) -} - -export function Spinner() { - return ( -
- - - - -
- ) -} - -export function AgentIcon(props: SVGProps) { - return ( - - - - - - ) -} - -export function ApiIcon(props: SVGProps) { - return ( - - - - ) -} - -export function ConditionalIcon(props: SVGProps) { - return ( - - - - ) -} - -export function NoteIcon(props: SVGProps) { - return ( - - - - - - - ) -} - -export function AirplaneIcon(props: SVGProps) { - return ( - - - - ) -} - -export function WorkIcon(props: SVGProps) { - return ( - - - - - ) -} - -export function WorkflowIcon(props: SVGProps) { - return ( - - - - - - - - ) -} - -export function WarnIcon(props: SVGProps) { - return ( - - - - ) -} - -export function UploadIcon(props: SVGProps) { - return ( - - - - - ) -} - -export function TrashIcon(props: SVGProps) { - return ( - - - - ) -} - -export function StudentIcon(props: SVGProps) { - return ( - - - - - ) -} - -export function SignalIcon(props: SVGProps) { - return ( - - - - ) -} - -export function SectionIcon(props: SVGProps) { - return ( - - - - ) -} - -export function ReminderIcon(props: SVGProps) { - return ( - - - - - ) -} - -export function DatabaseIcon(props: SVGProps) { - return ( - - - - - ) -} - -export function CrateIcon(props: SVGProps) { - return ( - - - - ) -} - -export function CookieIcon(props: SVGProps) { - return ( - - - - ) -} - -export function ErrorIcon(props: SVGProps) { - return ( - - + ) } -export function ChromeIcon(props: SVGProps) { +export function AgentIcon(props: SVGProps) { return ( - - ) -} - -export function CalendarIcon(props: SVGProps) { - return ( - @@ -616,7 +55,7 @@ export function CalendarIcon(props: SVGProps) { ) } -export function MessagesIcon(props: SVGProps) { +export function ApiIcon(props: SVGProps) { return ( ) { xmlns='http://www.w3.org/2000/svg' > ) { ) } -export function NotificationsIcon(props: SVGProps) { +export function ConditionalIcon(props: SVGProps) { return ( ) } -export function MailIcon(props: SVGProps) { +export function NoteIcon(props: SVGProps) { return ( - + + + ) } -export function CodeIcon(props: SVGProps) { +export function WorkflowIcon(props: SVGProps) { return ( - - - ) -} - -export function ChartBarIcon(props: SVGProps) { - return ( - - - - ) -} - -export function AtomIcon(props: SVGProps) { - return ( - - - - - ) -} - -export function ElevatorIcon(props: SVGProps) { - return ( - - - ) -} - -export function DollarIcon(props: SVGProps) { - return ( - - @@ -788,18 +190,18 @@ export function DollarIcon(props: SVGProps) { ) } -export function CreditCardIcon(props: SVGProps) { +export function SignalIcon(props: SVGProps) { return ( ) { ) } -export function BoatIcon(props: SVGProps) { +export function CalendarIcon(props: SVGProps) { return ( ) { xmlns='http://www.w3.org/2000/svg' > ) { ) } -export function CancelIcon(props: SVGProps) { +export function MessagesIcon(props: SVGProps) { return ( ) { xmlns='http://www.w3.org/2000/svg' > - ) { ) } -export function BankIcon(props: SVGProps) { +export function NotificationsIcon(props: SVGProps) { return ( ) { ) } -export function AmbulanceIcon(props: SVGProps) { +export function MailIcon(props: SVGProps) { return ( ) { xmlns='http://www.w3.org/2000/svg' > - - ) -} - -export function ComponentIcon(props: SVGProps) { - return ( - - ) { ) } -export function BrightIcon(props: SVGProps) { +export function CodeIcon(props: SVGProps) { return ( @@ -942,21 +316,19 @@ export function BrightIcon(props: SVGProps) { ) } -export function CrewAIIcon(props: SVGProps) { +export function ChartBarIcon(props: SVGProps) { return ( ) @@ -4428,3 +3800,36 @@ export function SmtpIcon(props: SVGProps) { ) } + +export function ApifyIcon(props: SVGProps) { + return ( + + + + + + + + + + + + + ) +} diff --git a/apps/sim/tools/apify/index.ts b/apps/sim/tools/apify/index.ts new file mode 100644 index 0000000000..673855f12f --- /dev/null +++ b/apps/sim/tools/apify/index.ts @@ -0,0 +1,3 @@ +export { apifyRunActorAsyncTool } from './run_actor_async' +export { apifyRunActorSyncTool } from './run_actor_sync' +export type { RunActorParams, RunActorResult } from './types' diff --git a/apps/sim/tools/apify/run_actor_async.ts b/apps/sim/tools/apify/run_actor_async.ts new file mode 100644 index 0000000000..1c613dcde6 --- /dev/null +++ b/apps/sim/tools/apify/run_actor_async.ts @@ -0,0 +1,213 @@ +import type { ToolConfig } from '@/tools/types' +import type { RunActorParams, RunActorResult } from './types' + +const POLL_INTERVAL_MS = 5000 // 5 seconds between polls +const MAX_POLL_TIME_MS = 300000 // 5 minutes maximum polling time + +export const apifyRunActorAsyncTool: ToolConfig = { + id: 'apify_run_actor_async', + name: 'APIFY Run Actor (Async)', + description: 'Run an APIFY actor asynchronously with polling for long-running tasks', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'APIFY API token from console.apify.com/account#/integrations', + }, + actorId: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'Actor ID or username/actor-name (e.g., "janedoe/my-actor" or actor ID)', + }, + input: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Actor input as JSON string', + }, + waitForFinish: { + type: 'number', + required: false, + visibility: 'user-or-llm', + description: 'Initial wait time in seconds (0-60) before polling starts', + }, + itemLimit: { + type: 'number', + required: false, + default: 100, + visibility: 'user-or-llm', + description: 'Max dataset items to fetch (1-250000, default 100)', + }, + timeout: { + type: 'number', + required: false, + visibility: 'user-or-llm', + description: 'Timeout in seconds (default: actor default)', + }, + build: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Actor build to run (e.g., "latest", "beta", or build tag/number)', + }, + }, + + request: { + url: (params) => { + const encodedActorId = encodeURIComponent(params.actorId) + const baseUrl = `https://api.apify.com/v2/acts/${encodedActorId}/runs` + const queryParams = new URLSearchParams() + + queryParams.set('token', params.apiKey) + + if (params.waitForFinish !== undefined) { + const waitTime = Math.max(0, Math.min(params.waitForFinish, 60)) + queryParams.set('waitForFinish', waitTime.toString()) + } + if (params.timeout) { + queryParams.set('timeout', params.timeout.toString()) + } + if (params.build) { + queryParams.set('build', params.build) + } + + return `${baseUrl}?${queryParams.toString()}` + }, + method: 'POST', + headers: (params) => ({ + Authorization: `Bearer ${params.apiKey}`, + 'Content-Type': 'application/json', + }), + body: (params) => { + let inputData = {} + if (params.input) { + try { + inputData = JSON.parse(params.input) + } catch (e) { + throw new Error('Invalid JSON in input parameter') + } + } + return inputData + }, + }, + + transformResponse: async (response) => { + if (!response.ok) { + const errorText = await response.text() + return { + success: false, + output: { success: false, runId: '', status: 'ERROR' }, + error: `APIFY API error: ${errorText}`, + } + } + + const data = await response.json() + return { + success: true, + output: data.data, + } + }, + + postProcess: async (result, params) => { + if (!result.success) { + return result + } + + const runData = result.output as any + const runId = runData.id + + let elapsedTime = 0 + + while (elapsedTime < MAX_POLL_TIME_MS) { + await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS)) + elapsedTime += POLL_INTERVAL_MS + + const encodedActorId = encodeURIComponent(params.actorId) + const statusResponse = await fetch( + `https://api.apify.com/v2/acts/${encodedActorId}/runs/${runId}?token=${params.apiKey}`, + { + headers: { + Authorization: `Bearer ${params.apiKey}`, + }, + } + ) + + if (!statusResponse.ok) { + return { + success: false, + output: { success: false, runId, status: 'UNKNOWN' }, + error: 'Failed to fetch run status', + } + } + + const statusData = await statusResponse.json() + const run = statusData.data + + if ( + run.status === 'SUCCEEDED' || + run.status === 'FAILED' || + run.status === 'ABORTED' || + run.status === 'TIMED-OUT' + ) { + if (run.status === 'SUCCEEDED') { + const limit = Math.max(1, Math.min(params.itemLimit || 100, 250000)) + const itemsResponse = await fetch( + `https://api.apify.com/v2/datasets/${run.defaultDatasetId}/items?token=${params.apiKey}&limit=${limit}`, + { + headers: { + Authorization: `Bearer ${params.apiKey}`, + }, + } + ) + + if (itemsResponse.ok) { + const items = await itemsResponse.json() + return { + success: true, + output: { + success: true, + runId, + status: run.status, + datasetId: run.defaultDatasetId, + items, + }, + } + } + } + + return { + success: run.status === 'SUCCEEDED', + output: { + success: run.status === 'SUCCEEDED', + runId, + status: run.status, + datasetId: run.defaultDatasetId, + }, + error: run.status !== 'SUCCEEDED' ? `Actor run ${run.status}` : undefined, + } + } + } + + return { + success: false, + output: { + success: false, + runId, + status: 'TIMEOUT', + }, + error: 'Actor run timed out after 5 minutes of polling', + } + }, + + outputs: { + success: { type: 'boolean', description: 'Whether the actor run succeeded' }, + runId: { type: 'string', description: 'APIFY run ID' }, + status: { type: 'string', description: 'Run status (SUCCEEDED, FAILED, etc.)' }, + datasetId: { type: 'string', description: 'Dataset ID containing results' }, + items: { type: 'array', description: 'Dataset items (if completed)' }, + }, +} diff --git a/apps/sim/tools/apify/run_actor_sync.ts b/apps/sim/tools/apify/run_actor_sync.ts new file mode 100644 index 0000000000..8ef5533a04 --- /dev/null +++ b/apps/sim/tools/apify/run_actor_sync.ts @@ -0,0 +1,107 @@ +import type { ToolConfig } from '@/tools/types' +import type { RunActorParams, RunActorResult } from './types' + +export const apifyRunActorSyncTool: ToolConfig = { + id: 'apify_run_actor_sync', + name: 'APIFY Run Actor (Sync)', + description: 'Run an APIFY actor synchronously and get results (max 5 minutes)', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'APIFY API token from console.apify.com/account#/integrations', + }, + actorId: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'Actor ID or username/actor-name (e.g., "janedoe/my-actor" or actor ID)', + }, + input: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Actor input as JSON string. See actor documentation for required fields.', + }, + timeout: { + type: 'number', + required: false, + visibility: 'user-or-llm', + description: 'Timeout in seconds (default: actor default)', + }, + build: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Actor build to run (e.g., "latest", "beta", or build tag/number)', + }, + }, + + request: { + url: (params) => { + const encodedActorId = encodeURIComponent(params.actorId) + const baseUrl = `https://api.apify.com/v2/acts/${encodedActorId}/run-sync-get-dataset-items` + const queryParams = new URLSearchParams() + + queryParams.set('token', params.apiKey) + + if (params.timeout) { + queryParams.set('timeout', params.timeout.toString()) + } + if (params.build) { + queryParams.set('build', params.build) + } + + return `${baseUrl}?${queryParams.toString()}` + }, + method: 'POST', + headers: (params) => ({ + Authorization: `Bearer ${params.apiKey}`, + 'Content-Type': 'application/json', + }), + body: (params) => { + let inputData = {} + if (params.input) { + try { + inputData = JSON.parse(params.input) + } catch (e) { + throw new Error('Invalid JSON in input parameter') + } + } + return inputData + }, + }, + + transformResponse: async (response) => { + if (!response.ok) { + const errorText = await response.text() + return { + success: false, + output: { success: false, runId: '', status: 'ERROR', items: [] }, + error: `APIFY API error: ${errorText}`, + } + } + + const items = await response.json() + return { + success: true, + output: { + success: true, + runId: 'sync-execution', + status: 'SUCCEEDED', + items, + }, + } + }, + + outputs: { + success: { type: 'boolean', description: 'Whether the actor run succeeded' }, + runId: { type: 'string', description: 'APIFY run ID' }, + status: { type: 'string', description: 'Run status (SUCCEEDED, FAILED, etc.)' }, + datasetId: { type: 'string', description: 'Dataset ID containing results' }, + items: { type: 'array', description: 'Dataset items (if completed)' }, + }, +} diff --git a/apps/sim/tools/apify/types.ts b/apps/sim/tools/apify/types.ts new file mode 100644 index 0000000000..4face19c80 --- /dev/null +++ b/apps/sim/tools/apify/types.ts @@ -0,0 +1,54 @@ +import type { ToolResponse } from '@/tools/types' + +export interface ApifyActor { + id: string + name: string + username: string + description?: string + stats?: { + lastRunStartedAt?: string + } +} + +export interface RunActorParams { + apiKey: string + actorId: string + input?: string + waitForFinish?: number // For async tool: 0-60 seconds initial wait + itemLimit?: number // For async tool: 1-250000 items, default 100 + timeout?: number + build?: string // Actor build to run (e.g., "latest", "beta", build tag/number) +} + +export interface ApifyRun { + id: string + actId: string + status: + | 'READY' + | 'RUNNING' + | 'SUCCEEDED' + | 'FAILED' + | 'ABORTED' + | 'TIMED-OUT' + | 'ABORTING' + | 'TIMING-OUT' + startedAt: string + finishedAt?: string + defaultDatasetId: string + defaultKeyValueStoreId: string +} + +export interface RunActorResult extends ToolResponse { + output: { + success: boolean + runId: string + status: string + datasetId?: string + items?: any[] + stats?: { + inputRecords?: number + outputRecords?: number + duration?: number + } + } +} diff --git a/apps/sim/tools/registry.ts b/apps/sim/tools/registry.ts index 9d993891b6..2a0c55ab99 100644 --- a/apps/sim/tools/registry.ts +++ b/apps/sim/tools/registry.ts @@ -4,6 +4,7 @@ import { airtableListRecordsTool, airtableUpdateRecordTool, } from '@/tools/airtable' +import { apifyRunActorAsyncTool, apifyRunActorSyncTool } from '@/tools/apify' import { apolloAccountBulkCreateTool, apolloAccountBulkUpdateTool, @@ -1404,6 +1405,8 @@ export const tools: Record = { airtable_get_record: airtableGetRecordTool, airtable_list_records: airtableListRecordsTool, airtable_update_record: airtableUpdateRecordTool, + apify_run_actor_sync: apifyRunActorSyncTool, + apify_run_actor_async: apifyRunActorAsyncTool, apollo_people_search: apolloPeopleSearchTool, apollo_people_enrich: apolloPeopleEnrichTool, apollo_people_bulk_enrich: apolloPeopleBulkEnrichTool, From f56d85bda64e0136b54047c2d03bcbd9d7c679eb Mon Sep 17 00:00:00 2001 From: Waleed Date: Sun, 30 Nov 2025 09:07:35 -0800 Subject: [PATCH 06/16] feat(i18n): update translations (#2137) Co-authored-by: waleedlatif1 --- apps/docs/content/docs/de/tools/apify.mdx | 89 +++++++++++++++++++++++ apps/docs/content/docs/es/tools/apify.mdx | 89 +++++++++++++++++++++++ apps/docs/content/docs/fr/tools/apify.mdx | 89 +++++++++++++++++++++++ apps/docs/content/docs/ja/tools/apify.mdx | 89 +++++++++++++++++++++++ apps/docs/content/docs/zh/tools/apify.mdx | 89 +++++++++++++++++++++++ apps/docs/i18n.lock | 28 +++++++ 6 files changed, 473 insertions(+) create mode 100644 apps/docs/content/docs/de/tools/apify.mdx create mode 100644 apps/docs/content/docs/es/tools/apify.mdx create mode 100644 apps/docs/content/docs/fr/tools/apify.mdx create mode 100644 apps/docs/content/docs/ja/tools/apify.mdx create mode 100644 apps/docs/content/docs/zh/tools/apify.mdx diff --git a/apps/docs/content/docs/de/tools/apify.mdx b/apps/docs/content/docs/de/tools/apify.mdx new file mode 100644 index 0000000000..c8c82105c7 --- /dev/null +++ b/apps/docs/content/docs/de/tools/apify.mdx @@ -0,0 +1,89 @@ +--- +title: Apify +description: Führe Apify-Akteure aus und rufe Ergebnisse ab +--- + +import { BlockInfoCard } from "@/components/ui/block-info-card" + + + +{/* MANUAL-CONTENT-START:intro */} +[Apify](https://apify.com/) ist eine leistungsstarke Plattform zum Erstellen, Bereitstellen und Ausführen von Web-Automatisierung und Web-Scraping-Akteuren im großen Maßstab. Apify ermöglicht es dir, nützliche Daten von jeder Website zu extrahieren, Arbeitsabläufe zu automatisieren und deine Datenpipelines nahtlos zu verbinden. + +Mit Apify kannst du: + +- **Vorgefertigte oder benutzerdefinierte Akteure ausführen**: Integriere öffentliche Akteure oder entwickle deine eigenen, um eine breite Palette von Webdatenextraktions- und Browser-Aufgaben zu automatisieren. +- **Datensätze abrufen**: Greife auf strukturierte Datensätze zu, die von Akteuren in Echtzeit gesammelt wurden, und verwalte sie. +- **Web-Automatisierung skalieren**: Nutze Cloud-Infrastruktur, um Aufgaben zuverlässig, asynchron oder synchron mit robuster Fehlerbehandlung auszuführen. + +In Sim ermöglicht die Apify-Integration deinen Agenten, grundlegende Apify-Operationen programmatisch durchzuführen: + +- **Akteur ausführen (Synchron)**: Verwende `apify_run_actor_sync`, um einen Apify-Akteur zu starten und auf dessen Abschluss zu warten, wobei die Ergebnisse sofort nach Beendigung des Laufs abgerufen werden. +- **Akteur ausführen (Asynchron)**: Verwende `apify_run_actor_async`, um einen Akteur im Hintergrund zu starten und regelmäßig nach Ergebnissen zu fragen, was für längere oder komplexe Aufgaben geeignet ist. + +Diese Operationen statten deine Agenten aus, um Datenerfassungs- oder Browser-Automatisierungsaufgaben direkt in Workflows zu automatisieren, zu scrapen und zu orchestrieren – alles mit flexibler Konfiguration und Ergebnisverarbeitung, ohne dass manuelle Ausführungen oder externe Tools erforderlich sind. Integriere Apify als dynamische Automatisierungs- und Datenextraktions-Engine, die programmatisch die webbasierten Workflows deiner Agenten antreibt. +{/* MANUAL-CONTENT-END */} + +## Gebrauchsanweisung + +Integriere Apify in deinen Workflow. Führe jeden Apify-Akteur mit benutzerdefinierter Eingabe aus und rufe Ergebnisse ab. Unterstützt sowohl synchrone als auch asynchrone Ausführung mit automatischem Datensatz-Abruf. + +## Tools + +### `apify_run_actor_sync` + +Führe einen APIFY-Aktor synchron aus und erhalte Ergebnisse (maximal 5 Minuten) + +#### Eingabe + +| Parameter | Typ | Erforderlich | Beschreibung | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Ja | APIFY API-Token von console.apify.com/account#/integrations | +| `actorId` | string | Ja | Aktor-ID oder Benutzername/Aktor-Name \(z.B. "janedoe/my-actor" oder Aktor-ID\) | +| `input` | string | Nein | Aktor-Eingabe als JSON-String. Siehe Aktor-Dokumentation für erforderliche Felder. | +| `timeout` | number | Nein | Timeout in Sekunden \(Standard: Aktor-Standard\) | +| `build` | string | Nein | Aktor-Build zum Ausführen \(z.B. "latest", "beta" oder Build-Tag/Nummer\) | + +#### Ausgabe + +| Parameter | Typ | Beschreibung | +| --------- | ---- | ----------- | +| `success` | boolean | Ob die Aktor-Ausführung erfolgreich war | +| `runId` | string | APIFY-Ausführungs-ID | +| `status` | string | Ausführungsstatus \(SUCCEEDED, FAILED, usw.\) | +| `datasetId` | string | Dataset-ID mit Ergebnissen | +| `items` | array | Dataset-Elemente \(falls abgeschlossen\) | + +### `apify_run_actor_async` + +Führe einen APIFY-Aktor asynchron mit Polling für lang laufende Aufgaben aus + +#### Eingabe + +| Parameter | Typ | Erforderlich | Beschreibung | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Ja | APIFY API-Token von console.apify.com/account#/integrations | +| `actorId` | string | Ja | Aktor-ID oder Benutzername/Aktor-Name \(z.B. "janedoe/my-actor" oder Aktor-ID\) | +| `input` | string | Nein | Aktor-Eingabe als JSON-String | +| `waitForFinish` | number | Nein | Anfängliche Wartezeit in Sekunden \(0-60\) bevor Polling beginnt | +| `itemLimit` | number | Nein | Maximale Anzahl an Dataset-Elementen zum Abrufen \(1-250000, Standard 100\) | +| `timeout` | number | Nein | Timeout in Sekunden \(Standard: Aktor-Standard\) | +| `build` | string | Nein | Aktor-Build zum Ausführen \(z.B. "latest", "beta" oder Build-Tag/Nummer\) | + +#### Ausgabe + +| Parameter | Typ | Beschreibung | +| --------- | ---- | ----------- | +| `success` | boolean | Ob der Actor-Lauf erfolgreich war | +| `runId` | string | APIFY-Lauf-ID | +| `status` | string | Laufstatus \(SUCCEEDED, FAILED, usw.\) | +| `datasetId` | string | Dataset-ID mit Ergebnissen | +| `items` | array | Dataset-Elemente \(falls abgeschlossen\) | + +## Hinweise + +- Kategorie: `tools` +- Typ: `apify` diff --git a/apps/docs/content/docs/es/tools/apify.mdx b/apps/docs/content/docs/es/tools/apify.mdx new file mode 100644 index 0000000000..5a712eee12 --- /dev/null +++ b/apps/docs/content/docs/es/tools/apify.mdx @@ -0,0 +1,89 @@ +--- +title: Apify +description: Ejecuta actores de Apify y obtén resultados +--- + +import { BlockInfoCard } from "@/components/ui/block-info-card" + + + +{/* MANUAL-CONTENT-START:intro */} +[Apify](https://apify.com/) es una plataforma potente para crear, implementar y ejecutar automatización web y actores de scraping web a escala. Apify te permite extraer datos útiles de cualquier sitio web, automatizar flujos de trabajo y conectar tus canales de datos sin problemas. + +Con Apify, puedes: + +- **Ejecutar actores predefinidos o personalizados**: Integra actores públicos o desarrolla los tuyos propios, automatizando una amplia gama de tareas de extracción de datos web y navegador. +- **Recuperar conjuntos de datos**: Accede y gestiona conjuntos de datos estructurados recopilados por actores en tiempo real. +- **Escalar la automatización web**: Aprovecha la infraestructura en la nube para ejecutar tareas de manera confiable, de forma asíncrona o síncrona, con un manejo robusto de errores. + +En Sim, la integración de Apify permite a tus agentes realizar operaciones principales de Apify de forma programática: + +- **Ejecutar actor (Sincrónico)**: Usa `apify_run_actor_sync` para lanzar un actor de Apify y esperar a que se complete, obteniendo los resultados tan pronto como finalice la ejecución. +- **Ejecutar actor (Asincrónico)**: Usa `apify_run_actor_async` para iniciar un actor en segundo plano y consultar periódicamente los resultados, adecuado para trabajos más largos o complejos. + +Estas operaciones equipan a tus agentes para automatizar, extraer y orquestar tareas de recopilación de datos o automatización de navegador directamente dentro de los flujos de trabajo — todo con configuración flexible y manejo de resultados, sin necesidad de ejecuciones manuales o herramientas externas. Integra Apify como un motor dinámico de automatización y extracción de datos que impulsa programáticamente los flujos de trabajo a escala web de tus agentes. +{/* MANUAL-CONTENT-END */} + +## Instrucciones de uso + +Integra Apify en tu flujo de trabajo. Ejecuta cualquier actor de Apify con entrada personalizada y obtén resultados. Admite ejecución tanto síncrona como asíncrona con recuperación automática de conjuntos de datos. + +## Herramientas + +### `apify_run_actor_sync` + +Ejecuta un actor de APIFY de forma sincrónica y obtén resultados (máximo 5 minutos) + +#### Entrada + +| Parámetro | Tipo | Obligatorio | Descripción | +| --------- | ---- | ----------- | ----------- | +| `apiKey` | string | Sí | Token de API de APIFY desde console.apify.com/account#/integrations | +| `actorId` | string | Sí | ID del actor o nombreusuario/nombre-actor \(p.ej., "janedoe/my-actor" o ID del actor\) | +| `input` | string | No | Entrada del actor como cadena JSON. Consulta la documentación del actor para los campos requeridos. | +| `timeout` | number | No | Tiempo de espera en segundos \(predeterminado: el predeterminado del actor\) | +| `build` | string | No | Versión del actor a ejecutar \(p.ej., "latest", "beta", o etiqueta/número de versión\) | + +#### Salida + +| Parámetro | Tipo | Descripción | +| --------- | ---- | ----------- | +| `success` | boolean | Si la ejecución del actor tuvo éxito | +| `runId` | string | ID de ejecución de APIFY | +| `status` | string | Estado de la ejecución \(SUCCEEDED, FAILED, etc.\) | +| `datasetId` | string | ID del conjunto de datos que contiene los resultados | +| `items` | array | Elementos del conjunto de datos \(si se completó\) | + +### `apify_run_actor_async` + +Ejecuta un actor de APIFY de forma asincrónica con sondeo para tareas de larga duración + +#### Entrada + +| Parámetro | Tipo | Obligatorio | Descripción | +| --------- | ---- | ----------- | ----------- | +| `apiKey` | string | Sí | Token de API de APIFY desde console.apify.com/account#/integrations | +| `actorId` | string | Sí | ID del actor o nombreusuario/nombre-actor \(p.ej., "janedoe/my-actor" o ID del actor\) | +| `input` | string | No | Entrada del actor como cadena JSON | +| `waitForFinish` | number | No | Tiempo de espera inicial en segundos \(0-60\) antes de que comience el sondeo | +| `itemLimit` | number | No | Número máximo de elementos del conjunto de datos a recuperar \(1-250000, predeterminado 100\) | +| `timeout` | number | No | Tiempo de espera en segundos \(predeterminado: el predeterminado del actor\) | +| `build` | string | No | Versión del actor a ejecutar \(p.ej., "latest", "beta", o etiqueta/número de versión\) | + +#### Salida + +| Parámetro | Tipo | Descripción | +| --------- | ---- | ----------- | +| `success` | boolean | Si la ejecución del actor tuvo éxito | +| `runId` | string | ID de ejecución de APIFY | +| `status` | string | Estado de la ejecución \(SUCCEEDED, FAILED, etc.\) | +| `datasetId` | string | ID del conjunto de datos que contiene los resultados | +| `items` | array | Elementos del conjunto de datos \(si se completó\) | + +## Notas + +- Categoría: `tools` +- Tipo: `apify` diff --git a/apps/docs/content/docs/fr/tools/apify.mdx b/apps/docs/content/docs/fr/tools/apify.mdx new file mode 100644 index 0000000000..150c967ef7 --- /dev/null +++ b/apps/docs/content/docs/fr/tools/apify.mdx @@ -0,0 +1,89 @@ +--- +title: Apify +description: Exécutez des acteurs Apify et récupérez les résultats +--- + +import { BlockInfoCard } from "@/components/ui/block-info-card" + + + +{/* MANUAL-CONTENT-START:intro */} +[Apify](https://apify.com/) est une plateforme puissante pour créer, déployer et exécuter des automatisations web et des acteurs de scraping à grande échelle. Apify vous permet d'extraire des données utiles de n'importe quel site web, d'automatiser des flux de travail et de connecter vos pipelines de données de manière transparente. + +Avec Apify, vous pouvez : + +- **Exécuter des acteurs prêts à l'emploi ou personnalisés** : Intégrez des acteurs publics ou développez les vôtres, en automatisant un large éventail d'extractions de données web et de tâches de navigation. +- **Récupérer des ensembles de données** : Accédez et gérez des ensembles de données structurées collectées par les acteurs en temps réel. +- **Mettre à l'échelle l'automatisation web** : Exploitez l'infrastructure cloud pour exécuter des tâches de manière fiable, de façon asynchrone ou synchrone, avec une gestion robuste des erreurs. + +Dans Sim, l'intégration Apify permet à vos agents d'effectuer des opérations Apify essentielles de manière programmatique : + +- **Exécuter un acteur (Sync)** : Utilisez `apify_run_actor_sync` pour lancer un acteur Apify et attendre sa complétion, récupérant les résultats dès que l'exécution se termine. +- **Exécuter un acteur (Async)** : Utilisez `apify_run_actor_async` pour démarrer un acteur en arrière-plan et interroger périodiquement les résultats, adapté aux tâches plus longues ou complexes. + +Ces opérations équipent vos agents pour automatiser, scraper et orchestrer la collecte de données ou les tâches d'automatisation de navigateur directement dans les flux de travail — le tout avec une configuration flexible et une gestion des résultats, sans nécessiter d'exécutions manuelles ou d'outils externes. Intégrez Apify comme un moteur dynamique d'automatisation et d'extraction de données qui alimente de manière programmatique les flux de travail à l'échelle du web de vos agents. +{/* MANUAL-CONTENT-END */} + +## Instructions d'utilisation + +Intégrez Apify dans votre flux de travail. Exécutez n'importe quel acteur Apify avec des entrées personnalisées et récupérez les résultats. Prend en charge l'exécution synchrone et asynchrone avec récupération automatique des ensembles de données. + +## Outils + +### `apify_run_actor_sync` + +Exécuter un acteur APIFY de manière synchrone et obtenir les résultats (maximum 5 minutes) + +#### Entrée + +| Paramètre | Type | Obligatoire | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | chaîne | Oui | Jeton API APIFY depuis console.apify.com/account#/integrations | +| `actorId` | chaîne | Oui | ID de l'acteur ou nom d'utilisateur/nom-acteur \(ex. : "janedoe/my-actor" ou ID de l'acteur\) | +| `input` | chaîne | Non | Entrée de l'acteur sous forme de chaîne JSON. Voir la documentation de l'acteur pour les champs requis. | +| `timeout` | nombre | Non | Délai d'attente en secondes \(par défaut : valeur par défaut de l'acteur\) | +| `build` | chaîne | Non | Version de l'acteur à exécuter \(ex. : "latest", "beta", ou tag/numéro de build\) | + +#### Sortie + +| Paramètre | Type | Description | +| --------- | ---- | ----------- | +| `success` | booléen | Indique si l'exécution de l'acteur a réussi | +| `runId` | chaîne | ID d'exécution APIFY | +| `status` | chaîne | Statut d'exécution \(SUCCEEDED, FAILED, etc.\) | +| `datasetId` | chaîne | ID du jeu de données contenant les résultats | +| `items` | tableau | Éléments du jeu de données \(si terminé\) | + +### `apify_run_actor_async` + +Exécuter un acteur APIFY de manière asynchrone avec interrogation périodique pour les tâches de longue durée + +#### Entrée + +| Paramètre | Type | Obligatoire | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | chaîne | Oui | Jeton API APIFY depuis console.apify.com/account#/integrations | +| `actorId` | chaîne | Oui | ID de l'acteur ou nom d'utilisateur/nom-acteur \(ex. : "janedoe/my-actor" ou ID de l'acteur\) | +| `input` | chaîne | Non | Entrée de l'acteur sous forme de chaîne JSON | +| `waitForFinish` | nombre | Non | Temps d'attente initial en secondes \(0-60\) avant le début de l'interrogation | +| `itemLimit` | nombre | Non | Nombre maximum d'éléments de jeu de données à récupérer \(1-250000, par défaut 100\) | +| `timeout` | nombre | Non | Délai d'attente en secondes \(par défaut : valeur par défaut de l'acteur\) | +| `build` | chaîne | Non | Version de l'acteur à exécuter \(ex. : "latest", "beta", ou tag/numéro de build\) | + +#### Sortie + +| Paramètre | Type | Description | +| --------- | ---- | ----------- | +| `success` | boolean | Indique si l'exécution de l'acteur a réussi | +| `runId` | string | ID d'exécution APIFY | +| `status` | string | Statut d'exécution \(SUCCEEDED, FAILED, etc.\) | +| `datasetId` | string | ID du dataset contenant les résultats | +| `items` | array | Éléments du dataset \(si terminé\) | + +## Notes + +- Catégorie : `tools` +- Type : `apify` diff --git a/apps/docs/content/docs/ja/tools/apify.mdx b/apps/docs/content/docs/ja/tools/apify.mdx new file mode 100644 index 0000000000..ff5ef18f65 --- /dev/null +++ b/apps/docs/content/docs/ja/tools/apify.mdx @@ -0,0 +1,89 @@ +--- +title: Apify +description: Apifyアクターを実行して結果を取得する +--- + +import { BlockInfoCard } from "@/components/ui/block-info-card" + + + +{/* MANUAL-CONTENT-START:intro */} +[Apify](https://apify.com/)は、WebオートメーションとWebスクレイピングアクターを構築、デプロイ、大規模に実行するための強力なプラットフォームです。Apifyを使用すると、任意のWebサイトから有用なデータを抽出し、ワークフローを自動化し、データパイプラインをシームレスに接続できます。 + +Apifyでは以下のことが可能です: + +- **既製または独自のアクターを実行する**:公開アクターを統合するか、独自のアクターを開発して、幅広いWebデータ抽出とブラウザタスクを自動化します。 +- **データセットを取得する**:アクターによって収集された構造化データセットにリアルタイムでアクセスし管理します。 +- **Webオートメーションをスケールする**:クラウドインフラストラクチャを活用して、堅牢なエラー処理を備えた同期または非同期のタスクを確実に実行します。 + +Simでは、Apify統合によりエージェントがプログラムでApifyの主要な操作を実行できます: + +- **アクターの実行(同期)**:`apify_run_actor_sync`を使用してApifyアクターを起動し、完了を待って、実行が終了するとすぐに結果を取得します。 +- **アクターの実行(非同期)**:`apify_run_actor_async`を使用してバックグラウンドでアクターを開始し、定期的に結果をポーリングします。これは長時間または複雑なジョブに適しています。 + +これらの操作により、エージェントはワークフロー内で直接、自動化、スクレイピング、データ収集またはブラウザ自動化タスクのオーケストレーションを行うことができます — すべて柔軟な構成と結果処理を備え、手動実行や外部ツールを必要としません。Apifyを動的な自動化およびデータ抽出エンジンとして統合し、プログラムでエージェントのWebスケールワークフローを強化します。 +{/* MANUAL-CONTENT-END */} + +## 使用方法 + +Apifyをワークフローに統合します。カスタム入力で任意のApifyアクターを実行し、結果を取得します。自動データセット取得機能を備えた同期および非同期実行の両方をサポートしています。 + +## ツール + +### `apify_run_actor_sync` + +APIPYアクターを同期的に実行して結果を取得(最大5分) + +#### 入力 + +| パラメータ | 型 | 必須 | 説明 | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | はい | console.apify.com/account#/integrationsから取得したAPIFY APIトークン | +| `actorId` | string | はい | アクターIDまたはユーザー名/アクター名(例:"janedoe/my-actor"またはアクターID) | +| `input` | string | いいえ | JSON文字列としてのアクター入力。必須フィールドについてはアクターのドキュメントを参照してください。 | +| `timeout` | number | いいえ | タイムアウト(秒)(デフォルト:アクターのデフォルト) | +| `build` | string | いいえ | 実行するアクタービルド(例:"latest"、"beta"、またはビルドタグ/番号) | + +#### 出力 + +| パラメータ | 型 | 説明 | +| --------- | ---- | ----------- | +| `success` | boolean | アクター実行が成功したかどうか | +| `runId` | string | APIFY実行ID | +| `status` | string | 実行ステータス(SUCCEEDED、FAILEDなど) | +| `datasetId` | string | 結果を含むデータセットID | +| `items` | array | データセット項目(完了した場合) | + +### `apify_run_actor_async` + +長時間実行タスク用のポーリングを使用して、APIPYアクターを非同期で実行 + +#### 入力 + +| パラメータ | 型 | 必須 | 説明 | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | はい | console.apify.com/account#/integrationsから取得したAPIFY APIトークン | +| `actorId` | string | はい | アクターIDまたはユーザー名/アクター名(例:"janedoe/my-actor"またはアクターID) | +| `input` | string | いいえ | JSON文字列としてのアクター入力 | +| `waitForFinish` | number | いいえ | ポーリング開始前の初期待機時間(秒)(0-60) | +| `itemLimit` | number | いいえ | 取得する最大データセット項目数(1-250000、デフォルト100) | +| `timeout` | number | いいえ | タイムアウト(秒)(デフォルト:アクターのデフォルト) | +| `build` | string | いいえ | 実行するアクタービルド(例:"latest"、"beta"、またはビルドタグ/番号) | + +#### 出力 + +| パラメータ | 型 | 説明 | +| --------- | ---- | ----------- | +| `success` | boolean | アクターの実行が成功したかどうか | +| `runId` | string | APIFY実行ID | +| `status` | string | 実行ステータス(SUCCEEDED、FAILED、など) | +| `datasetId` | string | 結果を含むデータセットID | +| `items` | array | データセット項目(完了した場合) | + +## 注意事項 + +- カテゴリー: `tools` +- タイプ: `apify` diff --git a/apps/docs/content/docs/zh/tools/apify.mdx b/apps/docs/content/docs/zh/tools/apify.mdx new file mode 100644 index 0000000000..c384c060b8 --- /dev/null +++ b/apps/docs/content/docs/zh/tools/apify.mdx @@ -0,0 +1,89 @@ +--- +title: Apify +description: 运行 Apify actor 并获取结果 +--- + +import { BlockInfoCard } from "@/components/ui/block-info-card" + + + +{/* MANUAL-CONTENT-START:intro */} +[Apify](https://apify.com/) 是一个强大的平台,用于大规模构建、部署和运行网页自动化和网页抓取 actor。Apify 使您能够从任何网站提取有用的数据,自动化工作流程,并无缝连接您的数据管道。 + +使用 Apify,您可以: + +- **运行现成或自定义的 actor**:集成公共 actor 或开发您自己的,自动化各种网页数据提取和浏览器任务。 +- **获取数据集**:实时访问和管理由 actor 收集的结构化数据集。 +- **扩展网页自动化**:利用云基础设施可靠地运行任务,可以异步或同步运行,并具有强大的错误处理能力。 + +在 Sim 中,Apify 集成允许您的代理以编程方式执行核心 Apify 操作: + +- **运行 Actor(同步)**:使用 `apify_run_actor_sync` 启动一个 Apify actor 并等待其完成,在运行结束后立即获取结果。 +- **运行 Actor(异步)**:使用 `apify_run_actor_async` 在后台启动一个 actor 并定期轮询结果,适用于较长或复杂的任务。 + +这些操作使您的代理能够直接在工作流程中自动化、抓取和协调数据收集或浏览器自动化任务——所有这些都具有灵活的配置和结果处理,无需手动运行或外部工具。将 Apify 集成为一个动态的自动化和数据提取引擎,以编程方式为您的代理提供网页规模的工作流程支持。 +{/* MANUAL-CONTENT-END */} + +## 使用说明 + +将 Apify 集成到您的工作流程中。使用自定义输入运行任何 Apify actor 并获取结果。支持同步和异步执行,并自动获取数据集。 + +## 工具 + +### `apify_run_actor_sync` + +同步运行 APIFY actor 并获取结果(最长 5 分钟) + +#### 输入 + +| 参数 | 类型 | 必需 | 描述 | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | 是 | 来自 console.apify.com/account#/integrations 的 APIFY API 令牌 | +| `actorId` | string | 是 | Actor ID 或用户名/actor 名称 \(例如:"janedoe/my-actor" 或 actor ID\) | +| `input` | string | 否 | 作为 JSON 字符串的 actor 输入。请参阅 actor 文档以了解所需字段。 | +| `timeout` | number | 否 | 超时时间(秒)\(默认:actor 默认值\) | +| `build` | string | 否 | 要运行的 actor 构建版本 \(例如:"latest"、"beta" 或构建标签/编号\) | + +#### 输出 + +| 参数 | 类型 | 描述 | +| --------- | ---- | ----------- | +| `success` | boolean | actor 运行是否成功 | +| `runId` | string | APIFY 运行 ID | +| `status` | string | 运行状态 \(SUCCEEDED, FAILED 等\) | +| `datasetId` | string | 包含结果的数据集 ID | +| `items` | array | 数据集条目 \(如果已完成\) | + +### `apify_run_actor_async` + +异步运行 APIFY actor 并轮询长时间运行的任务 + +#### 输入 + +| 参数 | 类型 | 必需 | 描述 | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | 是 | 来自 console.apify.com/account#/integrations 的 APIFY API 令牌 | +| `actorId` | string | 是 | Actor ID 或用户名/actor 名称 \(例如:"janedoe/my-actor" 或 actor ID\) | +| `input` | string | 否 | 作为 JSON 字符串的 actor 输入 | +| `waitForFinish` | number | 否 | 轮询开始前的初始等待时间(秒)\(0-60\) | +| `itemLimit` | number | 否 | 要获取的最大数据集条目数 \(1-250000,默认 100\) | +| `timeout` | number | 否 | 超时时间(秒)\(默认:actor 默认值\) | +| `build` | string | 否 | 要运行的 actor 构建版本 \(例如:"latest"、"beta" 或构建标签/编号\) | + +#### 输出 + +| 参数 | 类型 | 描述 | +| --------- | ---- | ----------- | +| `success` | boolean | actor 运行是否成功 | +| `runId` | string | APIFY 运行 ID | +| `status` | string | 运行状态 \(SUCCEEDED, FAILED 等\) | +| `datasetId` | string | 包含结果的数据集 ID | +| `items` | array | 数据集条目 \(如果已完成\) | + +## 注意 + +- 类别: `tools` +- 类型: `apify` diff --git a/apps/docs/i18n.lock b/apps/docs/i18n.lock index 01bbc831c3..6cf7098fed 100644 --- a/apps/docs/i18n.lock +++ b/apps/docs/i18n.lock @@ -47338,3 +47338,31 @@ checksums: content/21: 0a7a099d582a926686c199dd7cc1f28c content/22: b3f310d5ef115bea5a8b75bf25d7ea9a content/23: 5edfd3643d5fa96be8bdbdb3c6e6905d + 1d31f77eb0b1c63c6a30a0021a1c91a7: + meta/title: 9f1084d4653cb60f1ce8db36f40496b0 + meta/description: 45de27663667ae7e6a583431fe4a5880 + content/0: 1b031fb0c62c46b177aeed5c3d3f8f80 + content/1: f0ca0a4c4900ee1d5b0f17ee3c533251 + content/2: 27d485e5e0595ae2bebb249da92db4e3 + content/3: 5a28d4a5bc7628a77a49b6e8691e6076 + content/4: b214a614c74fff80f2586a661afd4f7c + content/5: c6085ddc45eb3065a8a9c2b88dcf92b2 + content/6: 5135d9bb78c3bb9a5c686b7a135ce499 + content/7: 88c9e9e37c52903912f0bd09ce6587f1 + content/8: 821e6394b0a953e2b0842b04ae8f3105 + content/9: 5cc5269dad965982af56eed8d1957036 + content/10: 9c8aa3f09c9b2bd50ea4cdff3598ea4e + content/11: 8cc1d968c163eb0993c8cffe5142f9c4 + content/12: 1686853b699c5825bc3962ad4481dacb + content/13: 371d0e46b4bd2c23f559b8bc112f6955 + content/14: 6c217c31e3269045db51e0ca2e02dc40 + content/15: bcadfc362b69078beee0088e5936c98b + content/16: 9a5ecda96a3113d95900df597cffc636 + content/17: e28cdc705de05af33fc86ed8d5d900d3 + content/18: 0e38f19d9fbfbd36051d2e5c7f65d0c0 + content/19: 371d0e46b4bd2c23f559b8bc112f6955 + content/20: 9a0701ab299cc0a9bfd7b45f10c55449 + content/21: bcadfc362b69078beee0088e5936c98b + content/22: 9a5ecda96a3113d95900df597cffc636 + content/23: b3f310d5ef115bea5a8b75bf25d7ea9a + content/24: 052048d35cc259681ec571cb2a0ef40a From 08d57b4f8bbbaecdb5ce7057e7740e54e6b611fa Mon Sep 17 00:00:00 2001 From: Waleed Date: Sun, 30 Nov 2025 09:13:39 -0800 Subject: [PATCH 07/16] feat(env): added more optional env var examples (#2138) --- apps/sim/.env.example | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/sim/.env.example b/apps/sim/.env.example index 2c390dac1b..8e845f6b2a 100644 --- a/apps/sim/.env.example +++ b/apps/sim/.env.example @@ -14,6 +14,7 @@ NEXT_PUBLIC_APP_URL=http://localhost:3000 # Security (Required) ENCRYPTION_KEY=your_encryption_key # Use `openssl rand -hex 32` to generate, used to encrypt environment variables INTERNAL_API_SECRET=your_internal_api_secret # Use `openssl rand -hex 32` to generate, used to encrypt internal api routes +API_ENCRYPTION_KEY=your_api_encryption_key # Use `openssl rand -hex 32` to generate, used to encrypt api keys # Email Provider (Optional) # RESEND_API_KEY= # Uncomment and add your key from https://resend.com to send actual emails From f25db707d78fca9629573c53cc70b3bf74077b64 Mon Sep 17 00:00:00 2001 From: Waleed Date: Sun, 30 Nov 2025 10:46:18 -0800 Subject: [PATCH 08/16] feat(statuspage): added statuspage, updated list of tools in footer, renamed routes (#2139) * feat(statuspage): added statuspage, updated list of tools in footer, renamed routes * ack PR comments --- apps/sim/app/(landing)/actions/github.ts | 4 +- .../footer/components/compliance-badges.tsx | 26 ++ .../components/footer/components/index.ts | 6 + .../components/footer/components/logo.tsx | 17 ++ .../footer/components/social-links.tsx | 44 ++++ .../footer/components/status-indicator.tsx | 40 +++ .../app/(landing)/components/footer/consts.ts | 96 +++++++ .../(landing)/components/footer/footer.tsx | 249 ++++-------------- apps/sim/app/(landing)/components/nav/nav.tsx | 2 +- .../app/api/{github-stars => stars}/route.ts | 0 apps/sim/app/api/status/route.ts | 97 +++++++ apps/sim/app/api/status/types.ts | 48 ++++ .../app/api/{wand-generate => wand}/route.ts | 0 .../w/[workflowId]/hooks/use-wand.ts | 2 +- apps/sim/components/icons.tsx | 52 +++- apps/sim/hooks/queries/status.ts | 42 +++ apps/sim/lib/logs/get-trigger-options.ts | 10 +- apps/sim/lib/logs/search-suggestions.ts | 11 +- 18 files changed, 521 insertions(+), 225 deletions(-) create mode 100644 apps/sim/app/(landing)/components/footer/components/compliance-badges.tsx create mode 100644 apps/sim/app/(landing)/components/footer/components/index.ts create mode 100644 apps/sim/app/(landing)/components/footer/components/logo.tsx create mode 100644 apps/sim/app/(landing)/components/footer/components/social-links.tsx create mode 100644 apps/sim/app/(landing)/components/footer/components/status-indicator.tsx create mode 100644 apps/sim/app/(landing)/components/footer/consts.ts rename apps/sim/app/api/{github-stars => stars}/route.ts (100%) create mode 100644 apps/sim/app/api/status/route.ts create mode 100644 apps/sim/app/api/status/types.ts rename apps/sim/app/api/{wand-generate => wand}/route.ts (100%) create mode 100644 apps/sim/hooks/queries/status.ts diff --git a/apps/sim/app/(landing)/actions/github.ts b/apps/sim/app/(landing)/actions/github.ts index efd28a2124..527f29ea44 100644 --- a/apps/sim/app/(landing)/actions/github.ts +++ b/apps/sim/app/(landing)/actions/github.ts @@ -1,12 +1,12 @@ import { createLogger } from '@/lib/logs/console/logger' -const DEFAULT_STARS = '15.4k' +const DEFAULT_STARS = '18.6k' const logger = createLogger('GitHubStars') export async function getFormattedGitHubStars(): Promise { try { - const response = await fetch('/api/github-stars', { + const response = await fetch('/api/stars', { headers: { 'Cache-Control': 'max-age=3600', // Cache for 1 hour }, diff --git a/apps/sim/app/(landing)/components/footer/components/compliance-badges.tsx b/apps/sim/app/(landing)/components/footer/components/compliance-badges.tsx new file mode 100644 index 0000000000..3288fee422 --- /dev/null +++ b/apps/sim/app/(landing)/components/footer/components/compliance-badges.tsx @@ -0,0 +1,26 @@ +import Image from 'next/image' +import Link from 'next/link' +import { HIPAABadgeIcon } from '@/components/icons' + +export default function ComplianceBadges() { + return ( +
+ {/* SOC2 badge */} + + SOC2 Compliant + + {/* HIPAA badge */} + + + +
+ ) +} diff --git a/apps/sim/app/(landing)/components/footer/components/index.ts b/apps/sim/app/(landing)/components/footer/components/index.ts new file mode 100644 index 0000000000..2f9863a65e --- /dev/null +++ b/apps/sim/app/(landing)/components/footer/components/index.ts @@ -0,0 +1,6 @@ +import ComplianceBadges from './compliance-badges' +import Logo from './logo' +import SocialLinks from './social-links' +import StatusIndicator from './status-indicator' + +export { ComplianceBadges, Logo, SocialLinks, StatusIndicator } diff --git a/apps/sim/app/(landing)/components/footer/components/logo.tsx b/apps/sim/app/(landing)/components/footer/components/logo.tsx new file mode 100644 index 0000000000..f9c2ec12cd --- /dev/null +++ b/apps/sim/app/(landing)/components/footer/components/logo.tsx @@ -0,0 +1,17 @@ +import Image from 'next/image' +import Link from 'next/link' + +export default function Logo() { + return ( + + Sim - Workflows for LLMs + + ) +} diff --git a/apps/sim/app/(landing)/components/footer/components/social-links.tsx b/apps/sim/app/(landing)/components/footer/components/social-links.tsx new file mode 100644 index 0000000000..ccc6ef8d70 --- /dev/null +++ b/apps/sim/app/(landing)/components/footer/components/social-links.tsx @@ -0,0 +1,44 @@ +import { DiscordIcon, GithubIcon, LinkedInIcon, xIcon as XIcon } from '@/components/icons' + +export default function SocialLinks() { + return ( + + ) +} diff --git a/apps/sim/app/(landing)/components/footer/components/status-indicator.tsx b/apps/sim/app/(landing)/components/footer/components/status-indicator.tsx new file mode 100644 index 0000000000..7f6de994a3 --- /dev/null +++ b/apps/sim/app/(landing)/components/footer/components/status-indicator.tsx @@ -0,0 +1,40 @@ +'use client' + +import Link from 'next/link' +import { StatusDotIcon } from '@/components/icons' +import type { StatusType } from '@/app/api/status/types' +import { useStatus } from '@/hooks/queries/status' + +const STATUS_COLORS: Record = { + operational: 'text-[#10B981] hover:text-[#059669]', + degraded: 'text-[#F59E0B] hover:text-[#D97706]', + outage: 'text-[#EF4444] hover:text-[#DC2626]', + maintenance: 'text-[#3B82F6] hover:text-[#2563EB]', + loading: 'text-muted-foreground hover:text-foreground', + error: 'text-muted-foreground hover:text-foreground', +} + +export default function StatusIndicator() { + const { data, isLoading, isError } = useStatus() + + const status = isLoading ? 'loading' : isError ? 'error' : data?.status || 'error' + const message = isLoading + ? 'Checking Status...' + : isError + ? 'Status Unknown' + : data?.message || 'Status Unknown' + const statusUrl = data?.url || 'https://status.sim.ai' + + return ( + +